weaver-work-cli 0.1.40 → 0.1.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/dist/chunks/{archive-JHTONRST.js → archive-P6TBQGKL.js} +13 -5
- package/dist/chunks/{archive-oa-FCHLCPHC.js → archive-oa-7TQ2NXOH.js} +12 -5
- package/dist/chunks/{asset-RLIHC7DB.js → asset-3ELRG37G.js} +11 -4
- package/dist/chunks/{asset-idle-KVOFTLCP.js → asset-idle-WIGMUFMD.js} +7 -3
- package/dist/chunks/{attachment-content-RZYDB3MB.js → attachment-content-E3276UOV.js} +5 -4
- package/dist/chunks/{blog-42OZTJNP.js → blog-C5NMZAAC.js} +11 -4
- package/dist/chunks/{caizhilian-KRK547K5.js → caizhilian-5XSM2DFP.js} +13 -6
- package/dist/chunks/{calendar-RTWAMKHD.js → calendar-FI2WNSBO.js} +71 -26
- package/dist/chunks/{chunk-CXRQWOZ5.js → chunk-3YBDYOC4.js} +3 -3
- package/dist/chunks/{chunk-OOUTBLZ4.js → chunk-56EZERK4.js} +1 -1
- package/dist/chunks/chunk-6N4JPNFL.js +76 -0
- package/dist/chunks/{chunk-ZUX3P6BQ.js → chunk-727FH2NI.js} +1 -1
- package/dist/chunks/chunk-7BDPM5ST.js +11 -0
- package/dist/chunks/{chunk-LN447PY2.js → chunk-BCVYBYYT.js} +432 -2247
- package/dist/chunks/{chunk-7E6MUOEK.js → chunk-CWYGFU5B.js} +2 -2
- package/dist/chunks/{chunk-NOODWMCL.js → chunk-D4ADSZ7H.js} +1 -1
- package/dist/chunks/{chunk-WFFNM65B.js → chunk-ETNJSKMM.js} +281 -29
- package/dist/chunks/{chunk-CAQNBBQA.js → chunk-F4E4EM35.js} +3 -3
- package/dist/chunks/{chunk-4CTESSKI.js → chunk-FAZTGX7S.js} +6 -6
- package/dist/chunks/chunk-FRZKBMSW.js +2562 -0
- package/dist/chunks/{chunk-BYBSCN4X.js → chunk-G7PQWD4L.js} +6 -3
- package/dist/chunks/{chunk-NJKREDA3.js → chunk-GAMZLAG2.js} +1 -1
- package/dist/chunks/{chunk-FLS4DPGP.js → chunk-GM6J7Q4B.js} +28 -15
- package/dist/chunks/{chunk-NETCCARD.js → chunk-GRDRG6HP.js} +3 -3
- package/dist/chunks/chunk-HIT4Y6OI.js +1238 -0
- package/dist/chunks/{chunk-EZALDOQH.js → chunk-HP7JIYMT.js} +5 -2
- package/dist/chunks/{chunk-IZSSVYAG.js → chunk-IAZ3UPY6.js} +3 -3
- package/dist/chunks/{chunk-ZEDWSH32.js → chunk-IC62NFM5.js} +1 -1
- package/dist/chunks/{chunk-P26ZWSKU.js → chunk-KIHNAS25.js} +5 -2
- package/dist/chunks/{chunk-57IECMWX.js → chunk-N4M2DDFE.js} +29 -15
- package/dist/chunks/{chunk-JWRZM2H2.js → chunk-OF4S23UB.js} +4 -4
- package/dist/chunks/{chunk-VNBU55SL.js → chunk-PC7VKEB5.js} +80 -2458
- package/dist/chunks/{chunk-G2JSIUWF.js → chunk-PUQS5MWL.js} +91 -2
- package/dist/chunks/{chunk-E7OK5WD5.js → chunk-Q4OYAQYH.js} +5 -5
- package/dist/chunks/{chunk-7BRU4EFH.js → chunk-QVSWRLLU.js} +35 -6
- package/dist/chunks/{chunk-T6EGVBKU.js → chunk-TA7FXXJD.js} +6 -3
- package/dist/chunks/{chunk-GPMFD4RD.js → chunk-TXUG266F.js} +1 -1
- package/dist/chunks/{chunk-4TEDNCON.js → chunk-UFIT2UU3.js} +354 -56
- package/dist/chunks/{chunk-LUSPKZKY.js → chunk-UG5G54VL.js} +1 -0
- package/dist/chunks/{chunk-NIAJ5ZCG.js → chunk-UL5XUQ25.js} +5 -2
- package/dist/chunks/{chunk-FMPJJYYI.js → chunk-WRXSAVKO.js} +1 -1
- package/dist/chunks/{chunk-7U577Q7U.js → chunk-WSF4NNMR.js} +3 -3
- package/dist/chunks/chunk-XHK4MDR5.js +2497 -0
- package/dist/chunks/{chunk-LFMSDBZN.js → chunk-XNIK66I4.js} +326 -161
- package/dist/chunks/{chunk-3SO6QL6U.js → chunk-YWX377BY.js} +5 -2
- package/dist/chunks/{chunk-BYATLLEF.js → chunk-Z3GDFVJR.js} +1 -1
- package/dist/chunks/{chunk-I566ZYNF.js → chunk-Z7VYWPZV.js} +1 -1
- package/dist/chunks/{conflict-VR55AOOO.js → conflict-ARLSZJ6V.js} +4 -3
- package/dist/chunks/{continuation-2CKSBLA6.js → continuation-3S37AUSH.js} +4 -3
- package/dist/chunks/{continuation-RN6PZN2M.js → continuation-3XLYYTKV.js} +4 -3
- package/dist/chunks/{continuation-HZIZRZBX.js → continuation-HFW2YT5S.js} +4 -3
- package/dist/chunks/{continuation-NLECEJPX.js → continuation-KI7DRRZN.js} +4 -3
- package/dist/chunks/{contract-HI4FNPYE.js → contract-DNIIW5VJ.js} +13 -5
- package/dist/chunks/{cowork-HJLI353D.js → cowork-GMLRGVIW.js} +31 -14
- package/dist/chunks/create-flow-J22BO65E.js +56 -0
- package/dist/chunks/{ebuilder-form-HTGI63UU.js → ebuilder-form-ANV2FHYV.js} +12 -7
- package/dist/chunks/{ehr-GYXIYH3A.js → ehr-GSTGAIY3.js} +695 -1255
- package/dist/chunks/{employee-SAK2QYXX.js → employee-22BGJ3QS.js} +3 -3
- package/dist/chunks/{env-DW3G4HUO.js → env-BX3VRFS7.js} +4 -3
- package/dist/chunks/{esb-I5INCEFE.js → esb-ATAIASX2.js} +12 -7
- package/dist/chunks/{factory-TKXGXS6L.js → factory-PETTFME6.js} +3 -2
- package/dist/chunks/{fna-K2MHTQ24.js → fna-YEKBSFSX.js} +14 -8
- package/dist/chunks/{group-chat-VYBNMJLG.js → group-chat-BFVXAYFX.js} +7 -4
- package/dist/chunks/{host-D5SERMAJ.js → host-HRBXEPDQ.js} +5 -5
- package/dist/chunks/{host-JM4YVHFM.js → host-LR55CTHP.js} +5 -5
- package/dist/chunks/{host-L3VLITMT.js → host-SUOY6VYQ.js} +5 -5
- package/dist/chunks/{host-ZUQTJYYK.js → host-SZGV4UNT.js} +5 -5
- package/dist/chunks/{host-256GVCAH.js → host-WIKN2EJ5.js} +5 -5
- package/dist/chunks/{hrm-VLRBKTZB.js → hrm-NRDO4W5G.js} +11 -7
- package/dist/chunks/{im-QK3VTLXK.js → im-IQ2HN23S.js} +11 -10
- package/dist/chunks/{invoice-T5JTA32H.js → invoice-MNRW76PP.js} +636 -1768
- package/dist/chunks/{jiuchuanhui-P2FNEQVZ.js → jiuchuanhui-DTRBAX4N.js} +14 -6
- package/dist/chunks/{lazy-dispatch-XRRI46M6.js → lazy-dispatch-ZVWAI25B.js} +7 -6
- package/dist/chunks/{mail-3Y7MJ6PS.js → mail-ZVAUXOJA.js} +16 -14
- package/dist/chunks/{meeting-M7LTXGJE.js → meeting-FEVPZ67S.js} +21 -13
- package/dist/chunks/{okr-OBC6S67L.js → okr-SDH3E5RA.js} +12 -5
- package/dist/chunks/{operations-5QL3AECO.js → operations-62N6EP3C.js} +4 -3
- package/dist/chunks/{plan-5H6I53SK.js → plan-E35JFDI7.js} +12 -5
- package/dist/chunks/{project-L75QZV4S.js → project-73QXBAB2.js} +49 -25
- package/dist/chunks/reception-UWZVACBN.js +1899 -0
- package/dist/chunks/recruit-stage-4MAOCKFY.js +4770 -0
- package/dist/chunks/registry-IM5G23LS.js +24 -0
- package/dist/chunks/{registry-UGRBCBHO.js → registry-JDUS4E7D.js} +7 -6
- package/dist/chunks/{registry-RXPN6BBT.js → registry-KNKSCJNT.js} +7 -6
- package/dist/chunks/{registry-NYPYMZXG.js → registry-PO7SI256.js} +4 -4
- package/dist/chunks/{registry-QGHFNUWS.js → registry-PVUZQDDQ.js} +3 -3
- package/dist/chunks/{room-recommend-A3UDC3CA.js → room-recommend-H7KLXA5R.js} +6 -5
- package/dist/chunks/{schedule-5GCACCK7.js → schedule-ESZIBAUO.js} +6 -5
- package/dist/chunks/{workflow-M5ZJ7DWF.js → workflow-CWJFJLQU.js} +15 -10
- package/dist/cmd/action.js +6 -0
- package/dist/cmd/identity/index.js +45 -0
- package/dist/cmd/index.js +2 -0
- package/dist/core/continuation-ttl.js +18 -0
- package/dist/core/error-codes.js +85 -0
- package/dist/core/logger.js +11 -0
- package/dist/index.js +41 -30
- package/dist/internal/e10/auth/commands.js +164 -8
- package/dist/internal/e10/auth/error-log.js +182 -0
- package/dist/internal/e10/auth/messages.js +6 -0
- package/dist/internal/e10/auth/session.js +34 -3
- package/dist/internal/e10/auth/xiaoe.js +286 -44
- package/dist/internal/e10/auth-recovery.js +72 -14
- package/dist/internal/e10/context.js +72 -13
- package/dist/internal/e10/index.js +1 -1
- package/dist/internal/e10/network-error.js +93 -0
- package/dist/internal/e10/request-runtime.js +6 -0
- package/dist/internal/skills/install.js +9 -1
- package/dist/shortcuts/archive/continuation.js +2 -1
- package/dist/shortcuts/archive/index.js +3 -0
- package/dist/shortcuts/archive/operations/confirm.js +2 -1
- package/dist/shortcuts/archive-oa/continuation.js +2 -1
- package/dist/shortcuts/archive-oa/index.js +2 -0
- package/dist/shortcuts/archive-oa/operations/confirm.js +2 -1
- package/dist/shortcuts/asset/continuation.js +2 -1
- package/dist/shortcuts/asset/index.js +2 -0
- package/dist/shortcuts/asset-idle/index.js +2 -0
- package/dist/shortcuts/blog/continuation.js +2 -1
- package/dist/shortcuts/blog/index.js +2 -0
- package/dist/shortcuts/caizhilian/continuation.js +2 -1
- package/dist/shortcuts/caizhilian/index.js +2 -0
- package/dist/shortcuts/caizhilian/operations/confirm.js +3 -2
- package/dist/shortcuts/calendar/continuation.js +2 -1
- package/dist/shortcuts/calendar/index.js +2 -0
- package/dist/shortcuts/calendar/operations/read.js +31 -22
- package/dist/shortcuts/calendar/operations/write.js +46 -2
- package/dist/shortcuts/contract/continuation.js +2 -1
- package/dist/shortcuts/contract/index.js +2 -0
- package/dist/shortcuts/contract/operations/write.js +2 -1
- package/dist/shortcuts/cowork/continuation.js +2 -1
- package/dist/shortcuts/cowork/index.js +2 -0
- package/dist/shortcuts/cowork/operations/discuss-write.js +5 -1
- package/dist/shortcuts/cowork/operations/item-write.js +1 -7
- package/dist/shortcuts/cowork/operations/member-write.js +3 -1
- package/dist/shortcuts/cowork/operations/permission-write.js +5 -1
- package/dist/shortcuts/cowork/operations/shared.js +7 -0
- package/dist/shortcuts/ebuilder-form/continuation.js +2 -1
- package/dist/shortcuts/ebuilder-form/index.js +2 -0
- package/dist/shortcuts/ebuilder-form/operations/write.js +3 -2
- package/dist/shortcuts/ehr/continuation.js +2 -1
- package/dist/shortcuts/ehr/index.js +2 -0
- package/dist/shortcuts/ehr/operations/attend-write.js +44 -2
- package/dist/shortcuts/ehr/operations/hr-contact.js +7 -4
- package/dist/shortcuts/ehr/operations/hr-report.js +13 -7
- package/dist/shortcuts/ehr/operations/recruit-candidate-import.js +317 -63
- package/dist/shortcuts/ehr/operations/recruit-position.js +134 -2
- package/dist/shortcuts/ehr/operations/recruit-write.js +263 -18
- package/dist/shortcuts/ehr/operations/recruit.js +10 -4
- package/dist/shortcuts/ehr/operations/shared.js +47 -0
- package/dist/shortcuts/esb/continuation.js +2 -1
- package/dist/shortcuts/esb/index.js +2 -0
- package/dist/shortcuts/esb/operations/trigger.js +2 -1
- package/dist/shortcuts/fna/continuation.js +2 -1
- package/dist/shortcuts/fna/index.js +2 -0
- package/dist/shortcuts/fna/operations/invoice-writeoff.js +1 -1
- package/dist/shortcuts/fna/operations/loan.js +1 -1
- package/dist/shortcuts/hrm/index.js +2 -0
- package/dist/shortcuts/hrm/operations/org.js +118 -0
- package/dist/shortcuts/im/continuation.js +2 -1
- package/dist/shortcuts/index.js +10 -0
- package/dist/shortcuts/invoice/continuation.js +2 -1
- package/dist/shortcuts/invoice/index.js +14 -15
- package/dist/shortcuts/invoice/invoice-record.js +93 -0
- package/dist/shortcuts/invoice/manifest.js +190 -393
- package/dist/shortcuts/invoice/operations/add.js +2 -1
- package/dist/shortcuts/invoice/operations/delete.js +2 -1
- package/dist/shortcuts/invoice/operations/import.js +2 -1
- package/dist/shortcuts/invoice/operations/issuing-contract-detail.js +86 -0
- package/dist/shortcuts/invoice/operations/issuing-contracts.js +210 -0
- package/dist/shortcuts/invoice/operations/registry.js +17 -17
- package/dist/shortcuts/invoice/operations/reim-auto.js +4 -569
- package/dist/shortcuts/invoice/operations/reim.js +52 -341
- package/dist/shortcuts/invoice/operations/shared.js +21 -4
- package/dist/shortcuts/invoice/operations/update.js +2 -1
- package/dist/shortcuts/invoice/projection.js +10 -62
- package/dist/shortcuts/jiuchuanhui/continuation.js +2 -1
- package/dist/shortcuts/jiuchuanhui/index.js +2 -0
- package/dist/shortcuts/jiuchuanhui/operations/datajson.js +2 -1
- package/dist/shortcuts/jiuchuanhui/operations/esb.js +2 -1
- package/dist/shortcuts/mail/continuation.js +2 -1
- package/dist/shortcuts/mail/index.js +2 -0
- package/dist/shortcuts/mail/operations/mail-blacklist.js +1 -1
- package/dist/shortcuts/mail/operations/mail-contacts.js +1 -1
- package/dist/shortcuts/mail/operations/mail-send.js +1 -1
- package/dist/shortcuts/mail/operations/mail-sign.js +1 -1
- package/dist/shortcuts/mail/operations/mail-template.js +1 -1
- package/dist/shortcuts/meeting/continuation.js +2 -1
- package/dist/shortcuts/meeting/index.js +2 -0
- package/dist/shortcuts/meeting/operations/change.js +1 -1
- package/dist/shortcuts/meeting/operations/create.js +1 -1
- package/dist/shortcuts/meeting/operations/eb/catalog.js +4 -1
- package/dist/shortcuts/meeting/operations/eb/create-flow.js +101 -35
- package/dist/shortcuts/meeting/operations/eb/decision.js +1 -1
- package/dist/shortcuts/meeting/operations/eb/factory.js +34 -1
- package/dist/shortcuts/meeting/operations/eb/group-chat.js +25 -3
- package/dist/shortcuts/meeting/operations/eb/person-cache.js +96 -0
- package/dist/shortcuts/meeting/operations/eb/room-recommend.js +33 -11
- package/dist/shortcuts/meeting/operations/lifecycle.js +1 -1
- package/dist/shortcuts/meeting/operations/receipts.js +1 -1
- package/dist/shortcuts/meeting/operations/signs.js +1 -1
- package/dist/shortcuts/okr/continuation.js +2 -1
- package/dist/shortcuts/okr/index.js +2 -0
- package/dist/shortcuts/okr/operations/write.js +1 -1
- package/dist/shortcuts/plan/continuation.js +2 -1
- package/dist/shortcuts/plan/index.js +2 -0
- package/dist/shortcuts/plan/operations/write.js +1 -1
- package/dist/shortcuts/project/continuation.js +2 -1
- package/dist/shortcuts/project/index.js +2 -0
- package/dist/shortcuts/project/operations/read.js +6 -25
- package/dist/shortcuts/project/operations/shared.js +22 -0
- package/dist/shortcuts/project/operations/write.js +28 -2
- package/dist/shortcuts/reception/constants.js +53 -0
- package/dist/shortcuts/reception/errors.js +54 -0
- package/dist/shortcuts/reception/host.js +125 -0
- package/dist/shortcuts/reception/index.js +198 -0
- package/dist/shortcuts/reception/manifest.js +177 -0
- package/dist/shortcuts/reception/operations/ask.js +71 -0
- package/dist/shortcuts/reception/operations/browsertool.js +58 -0
- package/dist/shortcuts/reception/operations/compose.js +129 -0
- package/dist/shortcuts/reception/operations/customparams.js +74 -0
- package/dist/shortcuts/reception/operations/doc.js +238 -0
- package/dist/shortcuts/reception/operations/docrender.js +36 -0
- package/dist/shortcuts/reception/operations/panels.js +179 -0
- package/dist/shortcuts/reception/operations/registry.js +26 -0
- package/dist/shortcuts/reception/operations/render-assets.js +184 -0
- package/dist/shortcuts/reception/operations/render.js +123 -0
- package/dist/shortcuts/reception/operations/runs.js +38 -0
- package/dist/shortcuts/reception/operations/schedule.js +127 -0
- package/dist/shortcuts/reception/operations/shared.js +196 -0
- package/dist/shortcuts/reception/operations/snapshot.js +68 -0
- package/dist/shortcuts/reception/operations/types.js +1 -0
- package/dist/shortcuts/reception/operations.js +33 -0
- package/dist/shortcuts/reception/upload.js +218 -0
- package/dist/shortcuts/recruit-stage/context.js +231 -0
- package/dist/shortcuts/recruit-stage/continuation.js +74 -0
- package/dist/shortcuts/recruit-stage/errors.js +65 -0
- package/dist/shortcuts/recruit-stage/host.js +109 -0
- package/dist/shortcuts/recruit-stage/index.js +115 -0
- package/dist/shortcuts/recruit-stage/manifest.js +29 -0
- package/dist/shortcuts/recruit-stage/operations/interview-arrange.js +722 -0
- package/dist/shortcuts/recruit-stage/operations/interview-feedback.js +269 -0
- package/dist/shortcuts/recruit-stage/operations/jd-create.js +719 -0
- package/dist/shortcuts/recruit-stage/operations/list.js +431 -0
- package/dist/shortcuts/recruit-stage/operations/registry.js +38 -0
- package/dist/shortcuts/recruit-stage/operations/resume-import.js +1354 -0
- package/dist/shortcuts/recruit-stage/operations/search.js +158 -0
- package/dist/shortcuts/recruit-stage/operations/types.js +25 -0
- package/dist/shortcuts/recruit-stage/school-tiers.json +318 -0
- package/dist/shortcuts/recruit-stage/shared.js +608 -0
- package/dist/shortcuts/workflow/continuation.js +2 -1
- package/dist/shortcuts/workflow/index.js +2 -0
- package/dist/shortcuts/workflow/operations/form.js +32 -8
- package/dist/shortcuts/workflow/operations/todoSmartConvert/detailFieldRules.js +4 -2
- package/dist/shortcuts/workflow/operations/todoSmartConvert/summaryCache.js +13 -6
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailCache.js +17 -24
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailFetcher.js +14 -9
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.js +50 -8
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.core.js +2 -1
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.detail.js +17 -11
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.group.js +7 -39
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.js +3 -2
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.js +51 -15
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.pipeline.js +16 -1
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.smartGroup.js +151 -63
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.subGroup.js +56 -0
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.summary.js +39 -14
- package/dist/shortcuts/workflow/operations/write.js +1 -1
- package/docs/_catalog.md +3 -0
- package/docs/agent-invoice.md +1 -1
- package/docs/archive-oa.md +1 -1
- package/docs/caizhilian.md +1 -1
- package/docs/calendar.md +1 -1
- package/docs/contract.md +1 -1
- package/docs/e10-auth.md +23 -1
- package/docs/ehr.md +2 -2
- package/docs/esb.md +1 -1
- package/docs/im.md +1 -1
- package/docs/invoice.md +8 -12
- package/docs/okr.md +1 -1
- package/docs/operation-manual.md +8 -0
- package/docs/reception.md +119 -0
- package/package.json +1 -1
- package/scripts/clean.mjs +43 -2
- package/scripts/install-skill-to-xiaoe.mjs +105 -0
- package/scripts/package-skill.mjs +4 -2
- package/skill-template/business-info.json +42 -2
- package/skill-template/domains/caizhilian.md +1 -1
- package/skill-template/domains/reception-flow.md +18 -0
- package/skill-template/domains/recruit-stage.md +29 -0
- package/skill-template/domains/yepiaotong.md +4 -7
- package/skills/weaver-e10-archive-oa/references/source-manifest.json +14 -14
- package/skills/weaver-e10-blog/references/blog-publish.md +1 -1
- package/skills/weaver-e10-blog/references/source-manifest.json +7 -7
- package/skills/weaver-e10-caizhilian/references/source-manifest.json +21 -21
- package/skills/weaver-e10-caizhilian/references/write-protocol.md +2 -2
- package/skills/weaver-e10-calendar/SKILL.md +2 -1
- package/skills/weaver-e10-calendar/references/calendar-write.md +55 -1
- package/skills/weaver-e10-cowork/SKILL.md +1 -1
- package/skills/weaver-e10-cowork/references/cowork-write.md +3 -1
- package/skills/weaver-e10-ebuilder-form/SKILL.md +1 -1
- package/skills/weaver-e10-ebuilder-form/references/custom-api.md +1 -1
- package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +1 -1
- package/skills/weaver-e10-esb/SKILL.md +2 -2
- package/skills/weaver-e10-esb/references/source-manifest.json +22 -22
- package/skills/weaver-e10-esb/references/trigger.md +2 -2
- package/skills/weaver-e10-jinchengda/references/contract-clause-library-crud.md +1 -1
- package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +1 -1
- package/skills/weaver-e10-jinchengda/references/contract-request-write.md +1 -1
- package/skills/weaver-e10-jinchengda/references/source-manifest.json +29 -29
- package/skills/weaver-e10-jucailin/SKILL.md +1 -1
- package/skills/weaver-e10-jucailin/references/attend-write.md +10 -2
- package/skills/weaver-e10-jucailin/references/hr-contact.md +8 -0
- package/skills/weaver-e10-jucailin/references/hr-report.md +8 -0
- package/skills/weaver-e10-jucailin/references/recruit-create.md +14 -5
- package/skills/weaver-e10-jucailin/references/recruit-read.md +1 -1
- package/skills/weaver-e10-jucailin/references/recruit-write.md +5 -4
- package/skills/weaver-e10-mail/SKILL.md +1 -1
- package/skills/weaver-e10-meeting/SKILL.md +39 -7
- package/skills/weaver-e10-meeting/references/meeting-change.md +1 -1
- package/skills/weaver-e10-meeting/references/meeting-create.md +1 -1
- package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +1 -1
- package/skills/weaver-e10-meeting/references/meeting-verification.md +1 -1
- package/skills/weaver-e10-okr/references/okr-align.md +1 -1
- package/skills/weaver-e10-okr/references/okr-keyresult.md +1 -1
- package/skills/weaver-e10-okr/references/okr-write.md +1 -1
- package/skills/weaver-e10-okr/references/source-manifest.json +8 -8
- package/skills/weaver-e10-plan/references/plan-report-write.md +1 -1
- package/skills/weaver-e10-plan/references/source-manifest.json +20 -20
- package/skills/weaver-e10-qiyecheng/references/loan-management.md +1 -1
- package/skills/weaver-e10-qiyecheng/references/source-manifest.json +18 -18
- package/skills/weaver-e10-reception-flow/SKILL.md +173 -0
- package/skills/weaver-e10-reception-flow/assets//350/241/214/347/250/213/345/215/225/346/250/241/346/235/277-/346/263/233/345/276/256.docx +0 -0
- package/skills/weaver-e10-reception-flow/data/fields-snapshot.json +213 -0
- package/skills/weaver-e10-reception-flow/references/browsertool.md +68 -0
- package/skills/weaver-e10-reception-flow/references/env-pitfalls.md +51 -0
- package/skills/weaver-e10-reception-flow/references/fields-snapshot.md +227 -0
- package/skills/weaver-e10-reception-flow/references/guide.md +179 -0
- package/skills/weaver-e10-reception-flow/scripts/locate.sh +14 -0
- package/skills/weaver-e10-reception-flow/scripts/render.py +724 -0
- package/skills/weaver-e10-recruit-stage/SKILL.md +230 -0
- package/skills/weaver-e10-recruit-stage/agents/openai.yaml +119 -0
- package/skills/weaver-e10-recruit-stage/lib/recruit-xiaoe-file.mjs +188 -0
- package/skills/weaver-e10-recruit-stage/lib/xiaoe-session.mjs +66 -0
- package/skills/weaver-e10-recruit-stage/references/position-templates.md +202 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-arrange-interview.md +322 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-capability-check.md +127 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-check-install.md +65 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-detail-process.md +63 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-edit-interview-feedback.md +142 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-jd-create.md +95 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-jd-template.md +56 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-list-candidate.md +101 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-list-interview.md +148 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-match-candidates.md +77 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-output-links.md +59 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-resolve-creator.md +69 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-resolve-metadata.md +241 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-resume-import.md +451 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-resume-parse.md +128 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-search-candidate.md +146 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-urge-feedback.md +69 -0
- package/skills/weaver-e10-shared/SKILL.md +1 -1
- package/skills/weaver-e10-shared/references/e10-auth-and-session.md +10 -2
- package/skills/weaver-e10-shijingran/SKILL.md +7 -6
- package/skills/weaver-e10-shijingran/references/operations.md +3 -1
- package/skills/weaver-e10-shijingran/references/source-manifest.json +30 -28
- package/skills/weaver-e10-shijingran/references/write-operations.md +2 -0
- package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +2 -0
- package/skills/weaver-e10-wenshuding/references/source-manifest.json +3 -3
- package/skills/weaver-e10-workflow/SKILL.md +4 -2
- package/skills/weaver-e10-workflow/aigroup/default.json +11 -9
- package/skills/weaver-e10-workflow/references/source-manifest.json +32 -32
- package/skills/weaver-e10-workflow/references/todo-smart-convert.md +23 -13
- package/skills/weaver-e10-workflow/tools/todo-summary.cjs +62 -20
- package/skills/weaver-e10-yepiaotong/SKILL.md +28 -36
- package/skills/weaver-e10-yepiaotong/references/invoice-agent-entry.md +6 -3
- package/skills/weaver-e10-yepiaotong/references/invoice-detail.md +13 -10
- package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +2 -0
- package/skills/weaver-e10-yepiaotong/references/invoice-issuing-workflow.md +194 -155
- package/skills/weaver-e10-yepiaotong/references/invoice-output-view.md +28 -32
- package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +5 -1
- package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +8 -10
- package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +211 -616
- package/skills/weaver-e10-yepiaotong/references/reim-examples.md +149 -117
- package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +17 -20
- package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +20 -39
- package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +55 -22
- package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +7 -17
- package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +88 -92
- package/skills/weaver-e10-yepiaotong/references/source-manifest.json +144 -354
- package/skills/weaver-e10-yimiaoban/SKILL.md +1 -1
- package/skills/weaver-e10-yimiaoban/references/msg-write.md +1 -1
- package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +1 -1
- package/skills/weaver-e10-yimiaoban/references/source-manifest.json +7 -7
- package/dist/chunks/chunk-SPRHHSVC.js +0 -465
- package/dist/chunks/registry-KMHCPAAD.js +0 -22
- package/dist/shortcuts/invoice/markdown.js +0 -172
- package/dist/shortcuts/invoice/operations/issuing-qys.js +0 -424
- package/skills/weaver-e10-meeting.zip +0 -0
- package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +0 -131
- package/skills/weaver-e10-yepiaotong/references/invoice-issuing-form-fill-rules.md +0 -179
|
@@ -1,20 +1,64 @@
|
|
|
1
1
|
import { createRequire as __esbuildCreateRequire } from 'node:module';
|
|
2
2
|
const require = __esbuildCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
EHR_PAGES,
|
|
5
|
+
EhrCliError,
|
|
6
|
+
READ,
|
|
7
|
+
SCHEMA_DATE,
|
|
8
|
+
SCHEMA_ID,
|
|
9
|
+
SCHEMA_ID_LIST,
|
|
10
|
+
SCHEMA_MONTH,
|
|
11
|
+
SCHEMA_STRING_LIST,
|
|
12
|
+
WRITE,
|
|
13
|
+
addDays,
|
|
14
|
+
asObject,
|
|
15
|
+
assertDateRange,
|
|
16
|
+
assertEnum,
|
|
17
|
+
assertMonth,
|
|
18
|
+
assertNoForbiddenKeys,
|
|
19
|
+
buildListBody,
|
|
20
|
+
compact,
|
|
21
|
+
createRecruitContextLoader,
|
|
22
|
+
ehrAuthError,
|
|
23
|
+
ehrConfirmationError,
|
|
24
|
+
ehrNetworkError,
|
|
25
|
+
ehrPageUrl,
|
|
26
|
+
ehrPartialError,
|
|
27
|
+
ehrSuccess,
|
|
28
|
+
ehrValidationError,
|
|
29
|
+
fetchListRows,
|
|
30
|
+
normalizePaged,
|
|
31
|
+
pickDefined,
|
|
32
|
+
recruitOperations,
|
|
33
|
+
requireDateRange,
|
|
34
|
+
resolveSecondAuthToken,
|
|
35
|
+
schemaOf,
|
|
36
|
+
toIdList,
|
|
37
|
+
toNumber,
|
|
38
|
+
toPageQuery,
|
|
39
|
+
toPositiveInt
|
|
40
|
+
} from "./chunk-HIT4Y6OI.js";
|
|
41
|
+
import {
|
|
42
|
+
reportPlatformError
|
|
43
|
+
} from "./chunk-6N4JPNFL.js";
|
|
44
|
+
import {
|
|
45
|
+
CONTINUATION_TTL_MS,
|
|
46
|
+
CONTINUATION_TTL_SECONDS
|
|
47
|
+
} from "./chunk-7BDPM5ST.js";
|
|
3
48
|
import {
|
|
4
49
|
E10ApiError,
|
|
5
50
|
createE10RequestRuntime,
|
|
6
51
|
isE10SessionExpiredResponse,
|
|
7
52
|
requireE10Session
|
|
8
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-ETNJSKMM.js";
|
|
9
54
|
import {
|
|
10
55
|
E10_SESSION_EXPIRED_MESSAGE,
|
|
11
56
|
getActiveProfile
|
|
12
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-UFIT2UU3.js";
|
|
13
58
|
import {
|
|
14
|
-
CliError,
|
|
15
59
|
isCliError,
|
|
16
60
|
toErrorEnvelope
|
|
17
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-UG5G54VL.js";
|
|
18
62
|
import "./chunk-BUSC6UAE.js";
|
|
19
63
|
|
|
20
64
|
// src/shortcuts/ehr/index.ts
|
|
@@ -26,62 +70,6 @@ import { existsSync } from "node:fs";
|
|
|
26
70
|
import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
27
71
|
import { homedir } from "node:os";
|
|
28
72
|
import { resolve } from "node:path";
|
|
29
|
-
|
|
30
|
-
// src/shortcuts/ehr/errors.ts
|
|
31
|
-
var EhrCliError = class extends CliError {
|
|
32
|
-
type;
|
|
33
|
-
subtype;
|
|
34
|
-
code;
|
|
35
|
-
retryable;
|
|
36
|
-
stage;
|
|
37
|
-
details;
|
|
38
|
-
partialData;
|
|
39
|
-
constructor(type, subtype, message, options = {}) {
|
|
40
|
-
super(message, options.exitCode ?? 5 /* InternalError */);
|
|
41
|
-
this.name = "EhrCliError";
|
|
42
|
-
this.type = type;
|
|
43
|
-
this.subtype = subtype;
|
|
44
|
-
this.code = options.code;
|
|
45
|
-
this.retryable = options.retryable ?? false;
|
|
46
|
-
this.stage = options.stage;
|
|
47
|
-
this.details = options.details;
|
|
48
|
-
this.partialData = options.partialData;
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
function ehrValidationError(subtype, message, details) {
|
|
52
|
-
return new EhrCliError("validation", subtype, message, {
|
|
53
|
-
details,
|
|
54
|
-
exitCode: 2 /* UsageError */
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
function ehrAuthError(subtype, message, details) {
|
|
58
|
-
return new EhrCliError("authentication", subtype, message, {
|
|
59
|
-
details,
|
|
60
|
-
exitCode: 3 /* AuthError */
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
function ehrNetworkError(subtype, message, options = {}) {
|
|
64
|
-
return new EhrCliError("network", subtype, message, {
|
|
65
|
-
...options,
|
|
66
|
-
retryable: options.retryable ?? true,
|
|
67
|
-
exitCode: 4 /* NetworkError */
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
function ehrConfirmationError(action, details) {
|
|
71
|
-
return new EhrCliError("confirmation", "required", "\u8BE5\u64CD\u4F5C\u9700\u8981\u660E\u786E\u786E\u8BA4", {
|
|
72
|
-
details: { action, ...details },
|
|
73
|
-
exitCode: 10 /* ConfirmationRequired */
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
function ehrPartialError(message, partialData, details) {
|
|
77
|
-
return new EhrCliError("partial", "write_uncertain", message, {
|
|
78
|
-
details,
|
|
79
|
-
partialData,
|
|
80
|
-
exitCode: 11 /* Partial */
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// src/shortcuts/ehr/continuation.ts
|
|
85
73
|
function stateRoot(ctx) {
|
|
86
74
|
const configured = ctx?.config?.path();
|
|
87
75
|
if (configured) return resolve(configured, "..");
|
|
@@ -109,7 +97,7 @@ function signature(payload, key) {
|
|
|
109
97
|
}
|
|
110
98
|
function createEhrContinuationSigner(ctx) {
|
|
111
99
|
return {
|
|
112
|
-
async issue(payload, ttlMs =
|
|
100
|
+
async issue(payload, ttlMs = CONTINUATION_TTL_MS) {
|
|
113
101
|
const issuedAt = Date.now();
|
|
114
102
|
const body = encode({ ...payload, issuedAt, expiresAt: issuedAt + ttlMs });
|
|
115
103
|
const sig = signature(body, await loadKey(ctx));
|
|
@@ -325,184 +313,6 @@ function createEhrHost(ctx, dependencies = {}) {
|
|
|
325
313
|
return { request, getSession, buildCardSign };
|
|
326
314
|
}
|
|
327
315
|
|
|
328
|
-
// src/shortcuts/ehr/operations/types.ts
|
|
329
|
-
var READ = "read";
|
|
330
|
-
var WRITE = "write";
|
|
331
|
-
function ehrSuccess(action, data, meta) {
|
|
332
|
-
const payload = { ok: true, action, data };
|
|
333
|
-
if (meta && Object.keys(meta).length > 0) payload.meta = meta;
|
|
334
|
-
return payload;
|
|
335
|
-
}
|
|
336
|
-
function schemaOf(properties, options = {}) {
|
|
337
|
-
return {
|
|
338
|
-
type: "object",
|
|
339
|
-
additionalProperties: false,
|
|
340
|
-
properties,
|
|
341
|
-
...options.required?.length ? { required: options.required } : {},
|
|
342
|
-
...options.description ? { description: options.description } : {}
|
|
343
|
-
};
|
|
344
|
-
}
|
|
345
|
-
var SCHEMA_DATE = { type: "string", pattern: "^\\d{4}-\\d{2}-\\d{2}$" };
|
|
346
|
-
var SCHEMA_MONTH = { type: "string", pattern: "^\\d{4}-\\d{2}$" };
|
|
347
|
-
var SCHEMA_ID = { oneOf: [{ type: "integer" }, { type: "string", pattern: "^\\d+$" }] };
|
|
348
|
-
var SCHEMA_ID_LIST = { type: "array", items: SCHEMA_ID };
|
|
349
|
-
var SCHEMA_STRING_LIST = { type: "array", items: { type: "string" } };
|
|
350
|
-
|
|
351
|
-
// src/shortcuts/ehr/operations/shared.ts
|
|
352
|
-
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
353
|
-
function asObject(value) {
|
|
354
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
355
|
-
throw ehrValidationError("input_not_object", "\u8F93\u5165\u5FC5\u987B\u662F JSON \u5BF9\u8C61");
|
|
356
|
-
}
|
|
357
|
-
return value;
|
|
358
|
-
}
|
|
359
|
-
function assertNoForbiddenKeys(input) {
|
|
360
|
-
for (const key of Object.keys(input)) {
|
|
361
|
-
if (FORBIDDEN_KEYS.has(key)) {
|
|
362
|
-
throw ehrValidationError("forbidden_key", `\u8F93\u5165\u5305\u542B\u975E\u6CD5\u5B57\u6BB5\uFF1A${key}`);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
var DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
367
|
-
var MONTH_PATTERN = /^\d{4}-\d{2}$/;
|
|
368
|
-
function isDate(value) {
|
|
369
|
-
return typeof value === "string" && DATE_PATTERN.test(value);
|
|
370
|
-
}
|
|
371
|
-
function isMonth(value) {
|
|
372
|
-
return typeof value === "string" && MONTH_PATTERN.test(value);
|
|
373
|
-
}
|
|
374
|
-
function isRealDate(value) {
|
|
375
|
-
const [year, month, day] = value.split("-").map(Number);
|
|
376
|
-
if (month < 1 || month > 12) return false;
|
|
377
|
-
const daysInMonth = new Date(Date.UTC(year, month, 0)).getUTCDate();
|
|
378
|
-
return day >= 1 && day <= daysInMonth;
|
|
379
|
-
}
|
|
380
|
-
function assertDate(value, field) {
|
|
381
|
-
if (!isDate(value)) throw ehrValidationError("date_invalid", `${field} \u5FC5\u987B\u662F YYYY-MM-DD \u683C\u5F0F`);
|
|
382
|
-
const text = value;
|
|
383
|
-
if (!isRealDate(text)) {
|
|
384
|
-
throw ehrValidationError("date_invalid", `${field} \u4E0D\u662F\u5408\u6CD5\u65E5\u671F\uFF08\u6708\u4EFD\u9700 01-12\uFF0C\u65E5\u671F\u9700\u5728\u8BE5\u6708\u6709\u6548\u8303\u56F4\u5185\uFF09\uFF1A${text}`);
|
|
385
|
-
}
|
|
386
|
-
return text;
|
|
387
|
-
}
|
|
388
|
-
function assertMonth(value, field) {
|
|
389
|
-
if (!isMonth(value)) throw ehrValidationError("month_invalid", `${field} \u5FC5\u987B\u662F YYYY-MM \u683C\u5F0F`);
|
|
390
|
-
const text = value;
|
|
391
|
-
const month = Number(text.slice(5));
|
|
392
|
-
if (month < 1 || month > 12) {
|
|
393
|
-
throw ehrValidationError("month_invalid", `${field} \u7684\u6708\u4EFD\u5FC5\u987B\u5728 01-12\uFF1A${text}`);
|
|
394
|
-
}
|
|
395
|
-
return text;
|
|
396
|
-
}
|
|
397
|
-
function toNumber(value, field) {
|
|
398
|
-
if (value === void 0 || value === null || value === "") return void 0;
|
|
399
|
-
const numeric = Number(value);
|
|
400
|
-
if (!Number.isFinite(numeric)) {
|
|
401
|
-
throw ehrValidationError("number_invalid", `${field} \u5FC5\u987B\u662F\u6570\u5B57`);
|
|
402
|
-
}
|
|
403
|
-
return numeric;
|
|
404
|
-
}
|
|
405
|
-
function toPositiveInt(value, field) {
|
|
406
|
-
if (value === void 0 || value === null || value === "") return void 0;
|
|
407
|
-
const numeric = Number(value);
|
|
408
|
-
if (!Number.isFinite(numeric)) {
|
|
409
|
-
throw ehrValidationError("number_invalid", `${field} \u5FC5\u987B\u662F\u6570\u5B57`);
|
|
410
|
-
}
|
|
411
|
-
const truncated = Math.trunc(numeric);
|
|
412
|
-
if (truncated !== numeric || truncated <= 0) {
|
|
413
|
-
throw ehrValidationError("number_invalid", `${field} \u5FC5\u987B\u662F\u6B63\u6574\u6570`);
|
|
414
|
-
}
|
|
415
|
-
return truncated;
|
|
416
|
-
}
|
|
417
|
-
function toIdList(value, field) {
|
|
418
|
-
if (value === void 0 || value === null) return void 0;
|
|
419
|
-
if (!Array.isArray(value)) throw ehrValidationError("id_list_invalid", `${field} \u5FC5\u987B\u662F ID \u6570\u7EC4`);
|
|
420
|
-
return value.map((item, index) => {
|
|
421
|
-
if (item === void 0 || item === null || item === "") {
|
|
422
|
-
throw ehrValidationError("id_list_invalid", `${field}[${index}] \u4E0D\u80FD\u4E3A\u7A7A`);
|
|
423
|
-
}
|
|
424
|
-
const numeric = Number(item);
|
|
425
|
-
if (!Number.isFinite(numeric)) {
|
|
426
|
-
throw ehrValidationError("id_list_invalid", `${field}[${index}] \u5FC5\u987B\u662F\u6570\u5B57 ID`);
|
|
427
|
-
}
|
|
428
|
-
return numeric;
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
function pickDefined(value, keys) {
|
|
432
|
-
const result = {};
|
|
433
|
-
for (const key of keys) {
|
|
434
|
-
if (value[key] !== void 0) result[key] = value[key];
|
|
435
|
-
}
|
|
436
|
-
return result;
|
|
437
|
-
}
|
|
438
|
-
function compact(body) {
|
|
439
|
-
for (const key of Object.keys(body)) {
|
|
440
|
-
if (body[key] === void 0) delete body[key];
|
|
441
|
-
}
|
|
442
|
-
return body;
|
|
443
|
-
}
|
|
444
|
-
function assertDateRange(args, startField, endField) {
|
|
445
|
-
const start = args[startField];
|
|
446
|
-
const end = args[endField];
|
|
447
|
-
if ((start === void 0 || start === null) !== (end === void 0 || end === null)) {
|
|
448
|
-
throw ehrValidationError("date_range_incomplete", `${startField} \u4E0E ${endField} \u5FC5\u987B\u6210\u5BF9\u63D0\u4F9B`);
|
|
449
|
-
}
|
|
450
|
-
if (start === void 0 || start === null) return {};
|
|
451
|
-
const startDate = assertDate(start, startField);
|
|
452
|
-
const endDate = assertDate(end, endField);
|
|
453
|
-
if (startDate > endDate) {
|
|
454
|
-
throw ehrValidationError("date_range_invalid", `${startField} \u4E0D\u5F97\u665A\u4E8E ${endField}`);
|
|
455
|
-
}
|
|
456
|
-
return { start: startDate, end: endDate };
|
|
457
|
-
}
|
|
458
|
-
function requireDateRange(args, startField = "beginDate", endField = "endDate") {
|
|
459
|
-
const start = args[startField];
|
|
460
|
-
const end = args[endField];
|
|
461
|
-
if (start === void 0 || start === null || start === "" || end === void 0 || end === null || end === "") {
|
|
462
|
-
throw ehrValidationError("date_range_required", `${startField} \u4E0E ${endField} \u5FC5\u586B\uFF0C\u683C\u5F0F YYYY-MM-DD`);
|
|
463
|
-
}
|
|
464
|
-
const range = assertDateRange(args, startField, endField);
|
|
465
|
-
return { beginDate: range.start, endDate: range.end };
|
|
466
|
-
}
|
|
467
|
-
function unwrapData(response) {
|
|
468
|
-
if (!response || typeof response !== "object") return response;
|
|
469
|
-
return response.data;
|
|
470
|
-
}
|
|
471
|
-
function normalizePaged(response) {
|
|
472
|
-
const data = unwrapData(response);
|
|
473
|
-
const page = {};
|
|
474
|
-
const candidates = [data?.page, response?.page, data, response];
|
|
475
|
-
for (const source of candidates) {
|
|
476
|
-
if (!source || typeof source !== "object") continue;
|
|
477
|
-
for (const key of ["pageNo", "current", "pageSize", "total", "totalCount", "totalPage", "tableId"]) {
|
|
478
|
-
if (source[key] !== void 0 && page[key] === void 0) page[key] = source[key];
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
return { data, page };
|
|
482
|
-
}
|
|
483
|
-
function toPageQuery(args) {
|
|
484
|
-
const page = {};
|
|
485
|
-
const current = toPositiveInt(args?.current, "current");
|
|
486
|
-
const pageSize = toNumber(args?.pageSize, "pageSize");
|
|
487
|
-
const pageNo = toNumber(args?.pageNo, "pageNo");
|
|
488
|
-
if (current !== void 0) page.current = current;
|
|
489
|
-
if (pageSize !== void 0) page.pageSize = pageSize;
|
|
490
|
-
if (pageNo !== void 0) page.pageNo = pageNo;
|
|
491
|
-
return page;
|
|
492
|
-
}
|
|
493
|
-
var SECOND_AUTH_TOKEN_DEFAULT = "DONT_NEED";
|
|
494
|
-
function resolveSecondAuthToken(value) {
|
|
495
|
-
if (typeof value === "string" && value.trim()) return value.trim();
|
|
496
|
-
return SECOND_AUTH_TOKEN_DEFAULT;
|
|
497
|
-
}
|
|
498
|
-
function assertEnum(value, allowed, field) {
|
|
499
|
-
const text = typeof value === "string" ? value : String(value);
|
|
500
|
-
if (!allowed.includes(text)) {
|
|
501
|
-
throw ehrValidationError("enum_invalid", `${field} \u53D6\u503C\u5FC5\u987B\u662F ${allowed.join(" / ")} \u4E4B\u4E00`);
|
|
502
|
-
}
|
|
503
|
-
return text;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
316
|
// src/shortcuts/ehr/operations/attend-read.ts
|
|
507
317
|
var ATTEND_STATUS = [
|
|
508
318
|
"SIGN_IN_LATE",
|
|
@@ -905,7 +715,6 @@ var attendReadOperations = [
|
|
|
905
715
|
|
|
906
716
|
// src/shortcuts/ehr/operations/attend-write.ts
|
|
907
717
|
import { createHash as createHash2 } from "node:crypto";
|
|
908
|
-
var CONTINUATION_TTL_SECONDS = 600;
|
|
909
718
|
var CARD_TYPES = ["CHECKIN", "CHECKOUT", "LEAVE", "RETURN", "CHECKIN_AND_RETURN", "CHECKOUT_AND_LEAVE"];
|
|
910
719
|
var APPEAL_TYPES = [
|
|
911
720
|
"leave",
|
|
@@ -1229,9 +1038,39 @@ var ehrAttendAppealSaveApply = {
|
|
|
1229
1038
|
}
|
|
1230
1039
|
throw error;
|
|
1231
1040
|
}
|
|
1041
|
+
const session = await env.host.getSession();
|
|
1042
|
+
const appealListUrl = ehrPageUrl(session.baseUrl, EHR_PAGES.attendAbnormal);
|
|
1043
|
+
let appeal = null;
|
|
1044
|
+
let locateWarning;
|
|
1045
|
+
try {
|
|
1046
|
+
const listResp = await env.host.request({
|
|
1047
|
+
method: "POST",
|
|
1048
|
+
path: "/api/attend/web/appeal/getAppealList",
|
|
1049
|
+
body: {
|
|
1050
|
+
beginDate: addDays(String(args.attendDay), -1),
|
|
1051
|
+
endDate: addDays(String(args.attendDay), 1),
|
|
1052
|
+
current: 1,
|
|
1053
|
+
pageSize: 50
|
|
1054
|
+
}
|
|
1055
|
+
});
|
|
1056
|
+
const payload2 = listResp?.data;
|
|
1057
|
+
const rows = Array.isArray(payload2?.data) ? payload2.data : Array.isArray(payload2?.rows) ? payload2.rows : Array.isArray(payload2) ? payload2 : [];
|
|
1058
|
+
const day = String(args.attendDay);
|
|
1059
|
+
const desc = String(args.appealDesc ?? "");
|
|
1060
|
+
const pick = rows.find((r) => String(r?.attendDay ?? r?.attend_date ?? r?.attendDate ?? "").startsWith(day)) || (desc ? rows.find((r) => String(r?.appealDesc ?? r?.appeal_desc ?? "").includes(desc)) : null) || null;
|
|
1061
|
+
if (pick) appeal = pick;
|
|
1062
|
+
else locateWarning = "\u672A\u5728\u7533\u8BC9\u5217\u8868\u4E2D\u5B9A\u4F4D\u5230\u672C\u6B21\u8BB0\u5F55\uFF08\u53EF\u80FD\u521A\u63D0\u4EA4\u5C1A\u5728\u540C\u6B65\uFF09\uFF0C\u8BF7\u7A0D\u540E\u7528 ehr.attend.appeal.list \u590D\u6838";
|
|
1063
|
+
} catch (e) {
|
|
1064
|
+
locateWarning = "\u7533\u8BC9\u5217\u8868\u56DE\u67E5\u5931\u8D25\uFF1A" + (e?.message || "\u672A\u77E5\u539F\u56E0") + "\uFF1B\u8BF7\u7A0D\u540E\u7528 ehr.attend.appeal.list \u590D\u6838";
|
|
1065
|
+
}
|
|
1232
1066
|
return ehrSuccess("ehr.attend.appeal.save.apply", {
|
|
1233
1067
|
status: "COMPLETE",
|
|
1234
1068
|
result: response?.data,
|
|
1069
|
+
/** 定位到的新建申诉记录(含申诉 ID 等,处理申诉时用其 id) */
|
|
1070
|
+
appeal,
|
|
1071
|
+
/** 考勤异常/申诉页面地址(已取证路由,禁止改拼) */
|
|
1072
|
+
appealListUrl,
|
|
1073
|
+
...locateWarning ? { locateWarning } : {},
|
|
1235
1074
|
verifyHint: "\u53EF\u901A\u8FC7 ehr.attend.appeal.list \u56DE\u67E5\u7533\u8BC9\u662F\u5426\u5DF2\u751F\u6210"
|
|
1236
1075
|
});
|
|
1237
1076
|
}
|
|
@@ -1560,7 +1399,8 @@ var contactSearch = {
|
|
|
1560
1399
|
body: compact(body)
|
|
1561
1400
|
});
|
|
1562
1401
|
const { data, page } = normalizePaged(response);
|
|
1563
|
-
|
|
1402
|
+
const hrSession = await host.getSession();
|
|
1403
|
+
return ehrSuccess("ehr.hr.contact.search", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrEmployeeManager), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
1564
1404
|
}
|
|
1565
1405
|
};
|
|
1566
1406
|
var contactCount = {
|
|
@@ -1684,7 +1524,8 @@ var birthdayList = {
|
|
|
1684
1524
|
body
|
|
1685
1525
|
});
|
|
1686
1526
|
const { data, page } = normalizePaged(response);
|
|
1687
|
-
|
|
1527
|
+
const hrSession = await host.getSession();
|
|
1528
|
+
return ehrSuccess("ehr.hr.birthday.list", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrBirthdayList), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
1688
1529
|
}
|
|
1689
1530
|
};
|
|
1690
1531
|
var empchangeConditions = {
|
|
@@ -1758,7 +1599,8 @@ var empchangeList = {
|
|
|
1758
1599
|
body: compact(body)
|
|
1759
1600
|
});
|
|
1760
1601
|
const { data, page } = normalizePaged(response);
|
|
1761
|
-
|
|
1602
|
+
const hrSession = await host.getSession();
|
|
1603
|
+
return ehrSuccess("ehr.hr.empchange.list", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrPersonalStateChange), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
1762
1604
|
}
|
|
1763
1605
|
};
|
|
1764
1606
|
var hrContactOperations = [
|
|
@@ -2104,7 +1946,8 @@ var reportDeptTable = {
|
|
|
2104
1946
|
body: buildPersonReport(args, "departmentName")
|
|
2105
1947
|
});
|
|
2106
1948
|
const { data, page } = normalizePaged(response);
|
|
2107
|
-
|
|
1949
|
+
const hrSession = await host.getSession();
|
|
1950
|
+
return ehrSuccess("ehr.hr.report.dept.table", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrReportDeptPerson), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
2108
1951
|
}
|
|
2109
1952
|
};
|
|
2110
1953
|
var reportPosiTable = {
|
|
@@ -2123,7 +1966,8 @@ var reportPosiTable = {
|
|
|
2123
1966
|
body: buildPersonReport(args, "positionName")
|
|
2124
1967
|
});
|
|
2125
1968
|
const { data, page } = normalizePaged(response);
|
|
2126
|
-
|
|
1969
|
+
const hrSession = await host.getSession();
|
|
1970
|
+
return ehrSuccess("ehr.hr.report.posi.table", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrReportPosiPerson), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
2127
1971
|
}
|
|
2128
1972
|
};
|
|
2129
1973
|
var reportJobTable = {
|
|
@@ -2142,7 +1986,8 @@ var reportJobTable = {
|
|
|
2142
1986
|
body: buildPersonReport(args, "jobName")
|
|
2143
1987
|
});
|
|
2144
1988
|
const { data, page } = normalizePaged(response);
|
|
2145
|
-
|
|
1989
|
+
const hrSession = await host.getSession();
|
|
1990
|
+
return ehrSuccess("ehr.hr.report.job.table", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrReportJobPerson), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
2146
1991
|
}
|
|
2147
1992
|
};
|
|
2148
1993
|
var reportJobTypeTable = {
|
|
@@ -2249,7 +2094,8 @@ var estEmpTable = {
|
|
|
2249
2094
|
}
|
|
2250
2095
|
});
|
|
2251
2096
|
const { data, page } = normalizePaged(response);
|
|
2252
|
-
|
|
2097
|
+
const hrSession = await host.getSession();
|
|
2098
|
+
return ehrSuccess("ehr.hr.est.emp.table", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrTpReportTp), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
2253
2099
|
}
|
|
2254
2100
|
};
|
|
2255
2101
|
var estDcEmpTable = {
|
|
@@ -2295,7 +2141,8 @@ var estDcEmpTable = {
|
|
|
2295
2141
|
}
|
|
2296
2142
|
});
|
|
2297
2143
|
const { data, page } = normalizePaged(response);
|
|
2298
|
-
|
|
2144
|
+
const hrSession = await host.getSession();
|
|
2145
|
+
return ehrSuccess("ehr.hr.est.dc.emp.table", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrTpReportHw), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
2299
2146
|
}
|
|
2300
2147
|
};
|
|
2301
2148
|
var turnEmpTable = {
|
|
@@ -2342,7 +2189,8 @@ var turnEmpTable = {
|
|
|
2342
2189
|
body
|
|
2343
2190
|
});
|
|
2344
2191
|
const { data, page } = normalizePaged(response);
|
|
2345
|
-
|
|
2192
|
+
const hrSession = await host.getSession();
|
|
2193
|
+
return ehrSuccess("ehr.hr.turn.emp.table", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrTpReportTurn), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
2346
2194
|
}
|
|
2347
2195
|
};
|
|
2348
2196
|
var propsSa = {
|
|
@@ -2419,928 +2267,8 @@ var hrReportOperations = [
|
|
|
2419
2267
|
propsTable
|
|
2420
2268
|
];
|
|
2421
2269
|
|
|
2422
|
-
// src/shortcuts/ehr/operations/recruit.ts
|
|
2423
|
-
import { randomBytes as randomBytes2, randomUUID } from "node:crypto";
|
|
2424
|
-
import { existsSync as existsSync2, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
2425
|
-
import { homedir as homedir2 } from "node:os";
|
|
2426
|
-
import { join, resolve as resolve2 } from "node:path";
|
|
2427
|
-
var RECRUIT_APP_TAG = "weaver-recruit-service";
|
|
2428
|
-
var RECRUIT_TAGS = {
|
|
2429
|
-
talent_pool: "uf_rcrt_talent_pool",
|
|
2430
|
-
interview_plan: "uf_rcrt_interview_plan",
|
|
2431
|
-
interview_detail: "uf_rcrt_interview_detail",
|
|
2432
|
-
demand_manage: "uf_rcrt_demand_manage",
|
|
2433
|
-
position_manage: "uf_rcrt_position_manage",
|
|
2434
|
-
entry_manage: "uf_rcrt_entry_manage",
|
|
2435
|
-
offer: "uf_rcrt_offer",
|
|
2436
|
-
offer_sending: "uf_rcrt_offer_sending",
|
|
2437
|
-
candidate_manage: "uf_rcrt_candidate_manage",
|
|
2438
|
-
entry_transact: "uf_rcrt_entry_transact",
|
|
2439
|
-
entry_cancel: "uf_rcrt_entry_cancel",
|
|
2440
|
-
entry_change: "uf_rcrt_entry_change",
|
|
2441
|
-
dictionary: "uf_rcrt_dictionary",
|
|
2442
|
-
biz_config: "uf_rcrt_biz_config_mapper"
|
|
2443
|
-
};
|
|
2444
|
-
var LIST_KEYWORDS = {
|
|
2445
|
-
talent: ["\u4EBA\u624D\u5E93", "\u4EBA\u624D\u7BA1\u7406"],
|
|
2446
|
-
demand: ["\u62DB\u8058\u9700\u6C42", "\u9700\u6C42"],
|
|
2447
|
-
position: ["\u62DB\u8058\u804C\u4F4D", "\u804C\u4F4D\u5217\u8868", "\u804C\u4F4D\u7BA1\u7406"],
|
|
2448
|
-
entry: ["\u5165\u804C\u7BA1\u7406"],
|
|
2449
|
-
offer: ["\u5F55\u7528\u7BA1\u7406", "offer\u7BA1\u7406", "offer"],
|
|
2450
|
-
interview: ["\u9762\u8BD5\u7BA1\u7406"],
|
|
2451
|
-
biz_config: ["\u4E1A\u52A1\u914D\u7F6E\u6620\u5C04\u8868"]
|
|
2452
|
-
};
|
|
2453
|
-
var LIST_TYPES = {
|
|
2454
|
-
demand: { listKey: "demand", formType: "demand_manage", title: "\u62DB\u8058\u9700\u6C42" },
|
|
2455
|
-
position: { listKey: "position", formType: "position_manage", title: "\u62DB\u8058\u804C\u4F4D" },
|
|
2456
|
-
entry: { listKey: "entry", formType: "entry_manage", title: "\u5165\u804C\u7BA1\u7406" },
|
|
2457
|
-
offer: { listKey: "offer", formType: "offer", title: "\u5F55\u7528\u7BA1\u7406" }
|
|
2458
|
-
};
|
|
2459
|
-
var INTERNAL_KEYS = /* @__PURE__ */ new Set([
|
|
2460
|
-
"id",
|
|
2461
|
-
"form_data_id",
|
|
2462
|
-
"form_table_id",
|
|
2463
|
-
"rowKey",
|
|
2464
|
-
"ebrecord_rowkey",
|
|
2465
|
-
"isFollow",
|
|
2466
|
-
"is_flow",
|
|
2467
|
-
"data_status",
|
|
2468
|
-
"data_status_value",
|
|
2469
|
-
"update_time",
|
|
2470
|
-
"formDataId",
|
|
2471
|
-
"isFollowSearch",
|
|
2472
|
-
"isShareToMe"
|
|
2473
|
-
]);
|
|
2474
|
-
var DISPLAY_UI_KEYS = /* @__PURE__ */ new Set([
|
|
2475
|
-
...INTERNAL_KEYS,
|
|
2476
|
-
"operate",
|
|
2477
|
-
"isToDo",
|
|
2478
|
-
"todoPropSpan",
|
|
2479
|
-
"flow_status"
|
|
2480
|
-
]);
|
|
2481
|
-
function randHex32() {
|
|
2482
|
-
return randomUUID().replace(/-/g, "");
|
|
2483
|
-
}
|
|
2484
|
-
function randHex6() {
|
|
2485
|
-
return randomBytes2(3).toString("hex");
|
|
2486
|
-
}
|
|
2487
|
-
function cacheDirFor(baseUrl) {
|
|
2488
|
-
const url = new URL(baseUrl);
|
|
2489
|
-
const host = url.hostname + (url.port ? `_${url.port}` : "");
|
|
2490
|
-
const envRoot = process.env.E10_SKILL_CACHE_DIR;
|
|
2491
|
-
if (envRoot) return join(envRoot, host);
|
|
2492
|
-
const home = process.env.WEAVER_WORK_CLI_HOME || process.env.WORK_CLI_HOME || resolve2(homedir2(), ".weaver-work-cli");
|
|
2493
|
-
return join(home, "env-cache", "recruit-ops", host);
|
|
2494
|
-
}
|
|
2495
|
-
function namesOf(field) {
|
|
2496
|
-
if (!field) return null;
|
|
2497
|
-
let arr;
|
|
2498
|
-
if (Array.isArray(field)) arr = field;
|
|
2499
|
-
else if (typeof field === "object") arr = [field];
|
|
2500
|
-
else if (typeof field === "string") {
|
|
2501
|
-
const text = field.trim();
|
|
2502
|
-
if (!text.startsWith("[") && !text.startsWith("{")) return text || null;
|
|
2503
|
-
try {
|
|
2504
|
-
arr = JSON.parse(text);
|
|
2505
|
-
} catch {
|
|
2506
|
-
return text || null;
|
|
2507
|
-
}
|
|
2508
|
-
if (!Array.isArray(arr)) arr = [arr];
|
|
2509
|
-
} else return null;
|
|
2510
|
-
const names = arr.map((item) => item && typeof item === "object" ? item.name || item.username || item.text || item.title : null).filter(Boolean);
|
|
2511
|
-
return names.length ? names.join("\u3001") : null;
|
|
2512
|
-
}
|
|
2513
|
-
function isPlainId(value) {
|
|
2514
|
-
return value != null && /^\d+$/.test(String(value).trim());
|
|
2515
|
-
}
|
|
2516
|
-
var RecruitContextError = class extends Error {
|
|
2517
|
-
subtype;
|
|
2518
|
-
constructor(subtype, message) {
|
|
2519
|
-
super(message);
|
|
2520
|
-
this.subtype = subtype;
|
|
2521
|
-
}
|
|
2522
|
-
};
|
|
2523
|
-
async function fetchFormFields(host, appId, objId) {
|
|
2524
|
-
const form = new FormData();
|
|
2525
|
-
form.set("groupId", appId);
|
|
2526
|
-
form.set("sourceId", objId);
|
|
2527
|
-
form.set("sourceType", "FORM");
|
|
2528
|
-
form.set("detailFieldsGroup", "true");
|
|
2529
|
-
form.set("enableMerge", "true");
|
|
2530
|
-
form.set("customParam", '{"terminal":""}');
|
|
2531
|
-
form.set("params", "[]");
|
|
2532
|
-
const response = await host.request({
|
|
2533
|
-
method: "POST",
|
|
2534
|
-
path: "/api/ebuilder/common/ds/fields",
|
|
2535
|
-
multipart: form
|
|
2536
|
-
});
|
|
2537
|
-
const fmap = {};
|
|
2538
|
-
const omap = {};
|
|
2539
|
-
for (const group of response?.data || []) {
|
|
2540
|
-
for (const field of group?.fields || []) {
|
|
2541
|
-
const config = field?.config || {};
|
|
2542
|
-
const dataKey = config.dataKey || "";
|
|
2543
|
-
const fieldId = String(field?.id || "");
|
|
2544
|
-
if (dataKey && fieldId) fmap[dataKey] = fieldId;
|
|
2545
|
-
if (fieldId && Array.isArray(config.options) && config.options.length) {
|
|
2546
|
-
const map = {};
|
|
2547
|
-
for (const option of config.options) {
|
|
2548
|
-
if (!option || typeof option !== "object") continue;
|
|
2549
|
-
const name = option.name;
|
|
2550
|
-
let selectionId = option.selectionId;
|
|
2551
|
-
if (!selectionId && typeof option.extra === "string") {
|
|
2552
|
-
try {
|
|
2553
|
-
const extra = JSON.parse(option.extra);
|
|
2554
|
-
selectionId = extra.selectionId || extra.id;
|
|
2555
|
-
} catch {
|
|
2556
|
-
}
|
|
2557
|
-
}
|
|
2558
|
-
if (!selectionId) selectionId = option.value || option.valueKey || option.id;
|
|
2559
|
-
if (selectionId && name) map[String(selectionId)] = name;
|
|
2560
|
-
}
|
|
2561
|
-
if (Object.keys(map).length) omap[fieldId] = map;
|
|
2562
|
-
}
|
|
2563
|
-
}
|
|
2564
|
-
}
|
|
2565
|
-
return { fmap, omap };
|
|
2566
|
-
}
|
|
2567
|
-
async function resolveRecruitEnv(host, appId) {
|
|
2568
|
-
const forms = {};
|
|
2569
|
-
let tenantKey = "";
|
|
2570
|
-
for (const [logic, tag] of Object.entries(RECRUIT_TAGS)) {
|
|
2571
|
-
const response = await host.request({
|
|
2572
|
-
path: "/api/ebuilder/form/obj/getObjsByTag",
|
|
2573
|
-
query: { appId, tag }
|
|
2574
|
-
});
|
|
2575
|
-
const entry = Array.isArray(response?.data) && response.data.length ? response.data[0] : null;
|
|
2576
|
-
forms[logic] = {
|
|
2577
|
-
objId: String(entry?.id || ""),
|
|
2578
|
-
formId: String(entry?.formId || ""),
|
|
2579
|
-
objName: entry?.objName || ""
|
|
2580
|
-
};
|
|
2581
|
-
if (!tenantKey && entry?.tenantKey) tenantKey = String(entry.tenantKey);
|
|
2582
|
-
}
|
|
2583
|
-
const menuResponse = await host.request({
|
|
2584
|
-
path: "/api/cusapp/app/allMenus",
|
|
2585
|
-
query: { isFront: 1, appId, terminalType: "PC" }
|
|
2586
|
-
});
|
|
2587
|
-
const flat = [];
|
|
2588
|
-
const walk = (nodes) => {
|
|
2589
|
-
for (const node of nodes || []) {
|
|
2590
|
-
if (node && typeof node === "object") {
|
|
2591
|
-
flat.push(node);
|
|
2592
|
-
walk(node.children || node.childs);
|
|
2593
|
-
}
|
|
2594
|
-
}
|
|
2595
|
-
};
|
|
2596
|
-
const menuData = menuResponse?.data;
|
|
2597
|
-
walk(typeof menuData === "object" && menuData ? menuData.cusAppMenus || menuData : menuData);
|
|
2598
|
-
const searchMenus = [];
|
|
2599
|
-
const pages = [];
|
|
2600
|
-
for (const node of flat) {
|
|
2601
|
-
if (node.pageType === "SEARCH") {
|
|
2602
|
-
searchMenus.push({ menuName: node.menuName, listId: String(node.pageId || ""), cusMenuId: String(node.id || "") });
|
|
2603
|
-
} else if (node.pageType === "PAGE") {
|
|
2604
|
-
pages.push({ menuName: node.menuName, pageId: String(node.pageId || "") });
|
|
2605
|
-
}
|
|
2606
|
-
}
|
|
2607
|
-
const fields = {};
|
|
2608
|
-
const fieldOptions = {};
|
|
2609
|
-
const resolvedForms = Object.entries(forms).filter(([, v]) => v.objId);
|
|
2610
|
-
await Promise.all(resolvedForms.map(async ([logic, entry]) => {
|
|
2611
|
-
const { fmap, omap } = await fetchFormFields(host, appId, entry.objId);
|
|
2612
|
-
if (Object.keys(fmap).length) fields[entry.objId] = fmap;
|
|
2613
|
-
if (Object.keys(omap).length) fieldOptions[entry.objId] = omap;
|
|
2614
|
-
void logic;
|
|
2615
|
-
}));
|
|
2616
|
-
const dictByName = {};
|
|
2617
|
-
const dictRaw = [];
|
|
2618
|
-
const dictMenu = searchMenus.find((m) => (m.menuName || "").trim() === "\u6570\u636E\u5B57\u5178") || null;
|
|
2619
|
-
const dictObjId = forms.dictionary?.objId || "";
|
|
2620
|
-
if (dictObjId && dictMenu) {
|
|
2621
|
-
const size = 500;
|
|
2622
|
-
let current = 1;
|
|
2623
|
-
for (; ; ) {
|
|
2624
|
-
const response = await host.request({
|
|
2625
|
-
path: `/api/ebuilder/form/list/getListDatas?passid=${dictObjId}&cid=${dictObjId}`,
|
|
2626
|
-
body: {
|
|
2627
|
-
current,
|
|
2628
|
-
pageSize: size,
|
|
2629
|
-
tableuid: randHex32(),
|
|
2630
|
-
listId: dictMenu.listId,
|
|
2631
|
-
searchParamData: { searchType: "3", type: "and" },
|
|
2632
|
-
terminal: "PC",
|
|
2633
|
-
browser: "Chrome",
|
|
2634
|
-
requiredMatch: 1,
|
|
2635
|
-
mapResult: 1,
|
|
2636
|
-
recheckQuery: 1,
|
|
2637
|
-
isFollow: 0,
|
|
2638
|
-
isShareToMe: 0,
|
|
2639
|
-
filterCondition: {},
|
|
2640
|
-
cusMenuId: dictMenu.cusMenuId,
|
|
2641
|
-
urlPageTitle: "\u6570\u636E\u5B57\u5178",
|
|
2642
|
-
menuName: "\u6570\u636E\u5B57\u5178"
|
|
2643
|
-
},
|
|
2644
|
-
headers: { ebBusinessId: dictMenu.listId }
|
|
2645
|
-
});
|
|
2646
|
-
const rows = response?.data?.data || [];
|
|
2647
|
-
for (const row of rows) {
|
|
2648
|
-
const name = row.selection_name;
|
|
2649
|
-
const optionId = row.form_data_id;
|
|
2650
|
-
if (name && optionId) {
|
|
2651
|
-
(dictByName[String(name)] ||= []).push(String(optionId));
|
|
2652
|
-
dictRaw.push({ selection_name: String(name), option_id: String(optionId), dict_type: row.dict_type, browser_key: row.browser_key });
|
|
2653
|
-
}
|
|
2654
|
-
}
|
|
2655
|
-
if (rows.length < size) break;
|
|
2656
|
-
current += 1;
|
|
2657
|
-
}
|
|
2658
|
-
}
|
|
2659
|
-
let ebdDetailPageId = "";
|
|
2660
|
-
let selfUse = "0";
|
|
2661
|
-
const bizConfig = forms.biz_config || { objId: "", formId: "", objName: "" };
|
|
2662
|
-
const bizConfigMenu = searchMenus.find((m) => (m.menuName || "").trim() === "\u4E1A\u52A1\u914D\u7F6E\u6620\u5C04\u8868") || null;
|
|
2663
|
-
if (bizConfig.objId && bizConfigMenu) {
|
|
2664
|
-
try {
|
|
2665
|
-
const { fmap } = await fetchFormFields(host, appId, bizConfig.objId);
|
|
2666
|
-
const keyField = fmap.config_key || "";
|
|
2667
|
-
const valueField = fmap.config || "";
|
|
2668
|
-
if (keyField && valueField) {
|
|
2669
|
-
let current = 1;
|
|
2670
|
-
for (; ; ) {
|
|
2671
|
-
const response = await host.request({
|
|
2672
|
-
path: `/api/ebuilder/form/list/getListDatas?passid=${bizConfig.objId}&cid=${bizConfig.objId}`,
|
|
2673
|
-
body: {
|
|
2674
|
-
current,
|
|
2675
|
-
pageSize: 100,
|
|
2676
|
-
tableuid: randHex32(),
|
|
2677
|
-
listId: bizConfigMenu.listId,
|
|
2678
|
-
searchParamData: { searchType: "3", type: "and" },
|
|
2679
|
-
terminal: "PC",
|
|
2680
|
-
browser: "Chrome",
|
|
2681
|
-
requiredMatch: 1,
|
|
2682
|
-
mapResult: 1,
|
|
2683
|
-
recheckQuery: 1,
|
|
2684
|
-
isFollow: 0,
|
|
2685
|
-
isShareToMe: 0,
|
|
2686
|
-
filterCondition: {},
|
|
2687
|
-
cusMenuId: bizConfigMenu.cusMenuId,
|
|
2688
|
-
urlPageTitle: "\u4E1A\u52A1\u914D\u7F6E\u6620\u5C04\u8868",
|
|
2689
|
-
menuName: "\u4E1A\u52A1\u914D\u7F6E\u6620\u5C04\u8868"
|
|
2690
|
-
},
|
|
2691
|
-
headers: { ebBusinessId: bizConfigMenu.listId }
|
|
2692
|
-
});
|
|
2693
|
-
const rows = response?.data?.data || [];
|
|
2694
|
-
if (!rows.length) break;
|
|
2695
|
-
for (const row of rows) {
|
|
2696
|
-
if (String(row.config_key || "") === "28" && row.config) {
|
|
2697
|
-
const match = String(row.config).match(/\/sp\/ebdpage\/view\/(\d+)/);
|
|
2698
|
-
if (match) ebdDetailPageId = match[1];
|
|
2699
|
-
}
|
|
2700
|
-
if (String(row.config_key || "") === "-9999" && String(row.config) === "1") selfUse = "1";
|
|
2701
|
-
}
|
|
2702
|
-
if (rows.length < 100) break;
|
|
2703
|
-
current += 1;
|
|
2704
|
-
}
|
|
2705
|
-
}
|
|
2706
|
-
} catch {
|
|
2707
|
-
}
|
|
2708
|
-
}
|
|
2709
|
-
if (!ebdDetailPageId) {
|
|
2710
|
-
try {
|
|
2711
|
-
const response = await host.request({
|
|
2712
|
-
path: "/api/bs/ebuilder/page/list",
|
|
2713
|
-
query: { appid: appId }
|
|
2714
|
-
});
|
|
2715
|
-
for (const page of Array.isArray(response?.data) ? response.data : []) {
|
|
2716
|
-
if ((page?.name || "") === "\u4EBA\u624D\u5361\u7247" && page?.type === "PAGE" && page?.id) {
|
|
2717
|
-
ebdDetailPageId = String(page.id);
|
|
2718
|
-
break;
|
|
2719
|
-
}
|
|
2720
|
-
}
|
|
2721
|
-
} catch {
|
|
2722
|
-
}
|
|
2723
|
-
}
|
|
2724
|
-
const options = {};
|
|
2725
|
-
for (const [dataKey, logic] of [["recruit_status", "talent_pool"], ["channel", "talent_pool"]]) {
|
|
2726
|
-
const entry = forms[logic] || { objId: "", formId: "", objName: "" };
|
|
2727
|
-
const fieldId = (fields[entry.objId] || {})[dataKey] || "";
|
|
2728
|
-
if (fieldId && entry.objId) {
|
|
2729
|
-
const response = await host.request({
|
|
2730
|
-
path: "/api/ebuilder/common/ds/options",
|
|
2731
|
-
query: { fieldName: fieldId, objId: entry.objId, sourceType: "FORM", groupId: appId }
|
|
2732
|
-
});
|
|
2733
|
-
if (Array.isArray(response?.data)) {
|
|
2734
|
-
options[dataKey] = {};
|
|
2735
|
-
for (const option of response.data) {
|
|
2736
|
-
if (option?.id) options[dataKey][String(option.id)] = option.name;
|
|
2737
|
-
}
|
|
2738
|
-
}
|
|
2739
|
-
}
|
|
2740
|
-
}
|
|
2741
|
-
const lists = {
|
|
2742
|
-
talent: null,
|
|
2743
|
-
demand: null,
|
|
2744
|
-
position: null,
|
|
2745
|
-
entry: null,
|
|
2746
|
-
offer: null,
|
|
2747
|
-
interview: null,
|
|
2748
|
-
dict: dictMenu,
|
|
2749
|
-
biz_config: bizConfigMenu,
|
|
2750
|
-
all_search: searchMenus,
|
|
2751
|
-
pages
|
|
2752
|
-
};
|
|
2753
|
-
for (const [biz, keywords] of Object.entries(LIST_KEYWORDS)) {
|
|
2754
|
-
for (const menu of searchMenus) {
|
|
2755
|
-
if (keywords.some((keyword) => (menu.menuName || "").includes(keyword))) {
|
|
2756
|
-
lists[biz] = menu;
|
|
2757
|
-
break;
|
|
2758
|
-
}
|
|
2759
|
-
}
|
|
2760
|
-
}
|
|
2761
|
-
return {
|
|
2762
|
-
appId,
|
|
2763
|
-
tenantKey,
|
|
2764
|
-
forms,
|
|
2765
|
-
lists,
|
|
2766
|
-
fields,
|
|
2767
|
-
field_options: fieldOptions,
|
|
2768
|
-
options,
|
|
2769
|
-
dict: { by_name: dictByName, raw: dictRaw },
|
|
2770
|
-
ebdDetailPageId,
|
|
2771
|
-
selfUse
|
|
2772
|
-
};
|
|
2773
|
-
}
|
|
2774
|
-
function createRecruitContextLoader() {
|
|
2775
|
-
const memo = /* @__PURE__ */ new Map();
|
|
2776
|
-
async function load(host) {
|
|
2777
|
-
const session = await host.getSession();
|
|
2778
|
-
const baseUrl = session.baseUrl.replace(/\/+$/, "");
|
|
2779
|
-
const memoKey = baseUrl;
|
|
2780
|
-
let cached = memo.get(memoKey);
|
|
2781
|
-
if (cached) return cached;
|
|
2782
|
-
let appId = "";
|
|
2783
|
-
let diskCache = null;
|
|
2784
|
-
try {
|
|
2785
|
-
const dir = cacheDirFor(baseUrl);
|
|
2786
|
-
if (existsSync2(dir)) {
|
|
2787
|
-
const files = readdirSync(dir).filter((file) => file.endsWith(".json"));
|
|
2788
|
-
if (files.length === 1) {
|
|
2789
|
-
appId = files[0].replace(/\.json$/, "");
|
|
2790
|
-
diskCache = JSON.parse(readFileSync(join(dir, files[0]), "utf8"));
|
|
2791
|
-
}
|
|
2792
|
-
}
|
|
2793
|
-
} catch {
|
|
2794
|
-
}
|
|
2795
|
-
if (diskCache) {
|
|
2796
|
-
memo.set(memoKey, diskCache);
|
|
2797
|
-
return diskCache;
|
|
2798
|
-
}
|
|
2799
|
-
const gate = await host.request({
|
|
2800
|
-
path: "/api/bs/ebuilder/app/tags/getAppIds",
|
|
2801
|
-
query: { tag: RECRUIT_APP_TAG }
|
|
2802
|
-
});
|
|
2803
|
-
const appIds = gate?.data;
|
|
2804
|
-
if (!Array.isArray(appIds) || !appIds.length) {
|
|
2805
|
-
throw new RecruitContextError(
|
|
2806
|
-
"recruit_service_not_installed",
|
|
2807
|
-
"\u5F53\u524D\u79DF\u6237\u672A\u5B89\u88C5\u62DB\u8058\u670D\u52A1\uFF08weaver-recruit-service\uFF09\uFF0C\u65E0\u6CD5\u4F7F\u7528\u62DB\u8058\u80FD\u529B\u3002\u8BF7\u5148\u5728 E10 \u5E94\u7528\u5E02\u573A\u5B89\u88C5\u300C\u62DB\u8058\u300D\u5E94\u7528\u3002"
|
|
2808
|
-
);
|
|
2809
|
-
}
|
|
2810
|
-
appId = String(appIds[0]);
|
|
2811
|
-
const resolved = await resolveRecruitEnv(host, appId);
|
|
2812
|
-
try {
|
|
2813
|
-
const dir = cacheDirFor(baseUrl);
|
|
2814
|
-
mkdirSync(dir, { recursive: true });
|
|
2815
|
-
writeFileSync(
|
|
2816
|
-
join(dir, `${appId}.json`),
|
|
2817
|
-
JSON.stringify({
|
|
2818
|
-
__meta__: {
|
|
2819
|
-
capturedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").substring(0, 19),
|
|
2820
|
-
note: "recruit-ops \u73AF\u5883\u53C2\u6570\u7F13\u5B58\uFF08weaver-work-cli \u8FD0\u884C\u65F6\u89E3\u6790\u4EA7\u7269\uFF0C\u4E0D\u542B\u8BA4\u8BC1\u5B57\u6BB5\uFF09"
|
|
2821
|
-
},
|
|
2822
|
-
envKey: `${dir.split(/[\\/]/).pop()}|${appId}`,
|
|
2823
|
-
...resolved
|
|
2824
|
-
}, null, 2),
|
|
2825
|
-
"utf8"
|
|
2826
|
-
);
|
|
2827
|
-
} catch {
|
|
2828
|
-
}
|
|
2829
|
-
memo.set(memoKey, resolved);
|
|
2830
|
-
return resolved;
|
|
2831
|
-
}
|
|
2832
|
-
return { load };
|
|
2833
|
-
}
|
|
2834
|
-
function buildListBody(params) {
|
|
2835
|
-
return {
|
|
2836
|
-
current: params.current ?? 1,
|
|
2837
|
-
pageSize: params.pageSize ?? 10,
|
|
2838
|
-
tableuid: randHex32(),
|
|
2839
|
-
listId: params.listId,
|
|
2840
|
-
searchParamData: {
|
|
2841
|
-
searchType: "3",
|
|
2842
|
-
type: "and",
|
|
2843
|
-
...params.conditions && Object.keys(params.conditions).length ? { commonSearchFields: params.conditions } : {}
|
|
2844
|
-
},
|
|
2845
|
-
terminal: "PC",
|
|
2846
|
-
browser: "Chrome",
|
|
2847
|
-
requiredMatch: 1,
|
|
2848
|
-
mapResult: 1,
|
|
2849
|
-
recheckQuery: 1,
|
|
2850
|
-
isFollow: 0,
|
|
2851
|
-
isShareToMe: 0,
|
|
2852
|
-
filterCondition: {},
|
|
2853
|
-
cusMenuId: params.cusMenuId,
|
|
2854
|
-
urlPageTitle: params.title,
|
|
2855
|
-
menuName: params.menuName
|
|
2856
|
-
};
|
|
2857
|
-
}
|
|
2858
|
-
async function fetchListRows(host, objId, listId, body) {
|
|
2859
|
-
const countBody = { ...body };
|
|
2860
|
-
delete countBody.current;
|
|
2861
|
-
delete countBody.pageSize;
|
|
2862
|
-
const [listResponse, countResponse] = await Promise.all([
|
|
2863
|
-
host.request({
|
|
2864
|
-
path: `/api/ebuilder/form/list/getListDatas?passid=${objId}&cid=${objId}`,
|
|
2865
|
-
body,
|
|
2866
|
-
headers: { ebBusinessId: listId }
|
|
2867
|
-
}),
|
|
2868
|
-
host.request({
|
|
2869
|
-
path: `/api/ebuilder/form/list/getListDataCount?passid=${objId}&cid=${objId}`,
|
|
2870
|
-
body: countBody,
|
|
2871
|
-
headers: { ebBusinessId: listId }
|
|
2872
|
-
}).catch(() => null)
|
|
2873
|
-
]);
|
|
2874
|
-
const data = normalizePaged(listResponse).data;
|
|
2875
|
-
const rawRows = data?.data || [];
|
|
2876
|
-
const displayRows = data?.displayData;
|
|
2877
|
-
const hasDisplay = Array.isArray(displayRows) && displayRows.length > 0;
|
|
2878
|
-
const rows = hasDisplay ? displayRows : rawRows;
|
|
2879
|
-
const countData = countResponse ? normalizePaged(countResponse).data : null;
|
|
2880
|
-
const pageSize = typeof body.pageSize === "number" ? body.pageSize : typeof body.pageSize === "string" ? Number(body.pageSize) || rows.length : rows.length;
|
|
2881
|
-
const countUsable = countData !== null && typeof countData.total === "number";
|
|
2882
|
-
let total;
|
|
2883
|
-
let totalExact;
|
|
2884
|
-
let totalNote;
|
|
2885
|
-
if (countUsable) {
|
|
2886
|
-
total = countData.total;
|
|
2887
|
-
totalExact = true;
|
|
2888
|
-
} else if (rows.length < pageSize) {
|
|
2889
|
-
total = rows.length;
|
|
2890
|
-
totalExact = true;
|
|
2891
|
-
totalNote = "\u8BA1\u6570\u63A5\u53E3\u4E0D\u53EF\u7528\uFF0C\u672C\u9875\u672A\u6EE1\uFF08\u5DF2\u5230\u672B\u9875\uFF09\uFF0C\u603B\u6570\u6309\u5DF2\u53D6\u56DE\u884C\u6570\u5F97\u51FA";
|
|
2892
|
-
} else {
|
|
2893
|
-
total = null;
|
|
2894
|
-
totalExact = false;
|
|
2895
|
-
totalNote = "\u8BA1\u6570\u63A5\u53E3\u4E0D\u53EF\u7528\u4E14\u672C\u9875\u5DF2\u6EE1\uFF0C\u603B\u6570\u4E0D\u53EF\u77E5\uFF08\u53EF\u8C03\u5927 pageSize \u53D6\u56DE\u5168\u90E8\u884C\u6570\uFF09";
|
|
2896
|
-
}
|
|
2897
|
-
return { rows, displayRows: hasDisplay ? displayRows : null, total, totalExact, totalNote };
|
|
2898
|
-
}
|
|
2899
|
-
var contextResolve = {
|
|
2900
|
-
name: "ehr.recruit.context.resolve",
|
|
2901
|
-
resource: "recruit",
|
|
2902
|
-
method: "context.resolve",
|
|
2903
|
-
action: "ehr.recruit.context.resolve",
|
|
2904
|
-
summary: "\u89E3\u6790\u62DB\u8058\u6A21\u5757\u8FD0\u884C\u65F6\u53C2\u6570\uFF08appId/\u8868\u5355 objId/\u5217\u8868 listId+cusMenuId/\u5B57\u6BB5\u6620\u5C04\uFF09\uFF0C\u4E3B\u8981\u4F9B\u8C03\u8BD5\u4E0E\u515C\u5E95\uFF1B\u4E1A\u52A1 operation \u4F1A\u9690\u5F0F\u81EA\u52A8\u89E3\u6790",
|
|
2905
|
-
capability: "recruit",
|
|
2906
|
-
risk: READ,
|
|
2907
|
-
inputSchema: schemaOf({}),
|
|
2908
|
-
handler: async (_args, env) => {
|
|
2909
|
-
if (!env.recruitContext) {
|
|
2910
|
-
throw ehrValidationError("recruit_context_unavailable", "\u62DB\u8058\u4E0A\u4E0B\u6587\u52A0\u8F7D\u5668\u672A\u521D\u59CB\u5316");
|
|
2911
|
-
}
|
|
2912
|
-
const cache = await env.recruitContext.load(env.host);
|
|
2913
|
-
return ehrSuccess("ehr.recruit.context.resolve", {
|
|
2914
|
-
appId: cache.appId,
|
|
2915
|
-
tenantKey: cache.tenantKey || null,
|
|
2916
|
-
forms: cache.forms,
|
|
2917
|
-
lists: cache.lists,
|
|
2918
|
-
ebdDetailPageId: cache.ebdDetailPageId || null,
|
|
2919
|
-
selfUse: cache.selfUse
|
|
2920
|
-
});
|
|
2921
|
-
}
|
|
2922
|
-
};
|
|
2923
|
-
var candidateSearch = {
|
|
2924
|
-
name: "ehr.recruit.candidate.search",
|
|
2925
|
-
resource: "recruit",
|
|
2926
|
-
method: "candidate.search",
|
|
2927
|
-
action: "ehr.recruit.candidate.search",
|
|
2928
|
-
summary: "\u6309\u59D3\u540D/\u624B\u673A\u53F7\u6A21\u7CCA\u641C\u7D22\u4EBA\u624D\u5E93\u4EBA\u624D\uFF1B\u65E0\u7B5B\u9009\u6761\u4EF6\u65F6\u5217\u51FA\u5168\u90E8\u4EBA\u624D\u7528\u4E8E\u6D4F\u89C8\u3002\u8FD4\u56DE\u767D\u540D\u5355\u5C55\u793A\u5B57\u6BB5",
|
|
2929
|
-
capability: "recruit",
|
|
2930
|
-
risk: READ,
|
|
2931
|
-
inputSchema: schemaOf({
|
|
2932
|
-
name: { type: "string", description: "\u59D3\u540D\u6A21\u7CCA\u5339\u914D" },
|
|
2933
|
-
mobile: { type: "string", description: "\u624B\u673A\u53F7\u6A21\u7CCA\u5339\u914D" },
|
|
2934
|
-
current: SCHEMA_ID,
|
|
2935
|
-
pageSize: SCHEMA_ID
|
|
2936
|
-
}),
|
|
2937
|
-
handler: async (args, env) => {
|
|
2938
|
-
if (!env.recruitContext) {
|
|
2939
|
-
throw ehrValidationError("recruit_context_unavailable", "\u62DB\u8058\u4E0A\u4E0B\u6587\u52A0\u8F7D\u5668\u672A\u521D\u59CB\u5316");
|
|
2940
|
-
}
|
|
2941
|
-
const cache = await env.recruitContext.load(env.host);
|
|
2942
|
-
const talentList = cache.lists.talent;
|
|
2943
|
-
const talentObjId = cache.forms.talent_pool?.objId;
|
|
2944
|
-
if (!talentList?.listId || !talentObjId) {
|
|
2945
|
-
throw new RecruitContextError("recruit_context_missing", "\u5F53\u524D\u73AF\u5883\u672A\u89E3\u6790\u5230\u300C\u4EBA\u624D\u5E93\u300D\u83DC\u5355\u6216\u4EBA\u624D\u5E93\u8868\u5355\uFF0C\u65E0\u6CD5\u641C\u7D22\u4EBA\u624D\u3002\u8BF7\u5148\u8FD0\u884C ehr.recruit.context.resolve \u68C0\u67E5\u73AF\u5883\u3002");
|
|
2946
|
-
}
|
|
2947
|
-
const fields = cache.fields[talentObjId] || {};
|
|
2948
|
-
const nameField = "field_" + (fields.candidate_name || fields.name);
|
|
2949
|
-
const mobileField = "field_" + fields.telephone;
|
|
2950
|
-
const conditions = {};
|
|
2951
|
-
if (args.name) conditions[nameField] = [{ [nameField]: args.name, [`${nameField}_condition_type`]: "like" }];
|
|
2952
|
-
if (args.mobile) conditions[mobileField] = [{ [mobileField]: args.mobile, [`${mobileField}_condition_type`]: "like" }];
|
|
2953
|
-
const body = buildListBody({
|
|
2954
|
-
listId: talentList.listId,
|
|
2955
|
-
cusMenuId: talentList.cusMenuId,
|
|
2956
|
-
menuName: talentList.menuName || "\u4EBA\u624D\u7BA1\u7406",
|
|
2957
|
-
title: "\u4EBA\u624D\u5E93",
|
|
2958
|
-
current: toPositiveInt(args.current, "current") ?? 1,
|
|
2959
|
-
pageSize: toNumber(args.pageSize, "pageSize") ?? 10,
|
|
2960
|
-
conditions
|
|
2961
|
-
});
|
|
2962
|
-
const { rows, displayRows, total, totalExact, totalNote } = await fetchListRows(env.host, talentObjId, talentList.listId, body);
|
|
2963
|
-
let creatorNameMap = {};
|
|
2964
|
-
if (!displayRows) {
|
|
2965
|
-
const pureIds = [...new Set(rows.map((row) => row?.creator).filter(isPlainId).map((value) => String(value).trim()))];
|
|
2966
|
-
if (pureIds.length) {
|
|
2967
|
-
creatorNameMap = {};
|
|
2968
|
-
for (let index = 0; index < pureIds.length; index += 100) {
|
|
2969
|
-
const batch = pureIds.slice(index, index + 100);
|
|
2970
|
-
try {
|
|
2971
|
-
const response = await env.host.request({
|
|
2972
|
-
path: "/api/hrm/common/getEmployeeByIds",
|
|
2973
|
-
body: { userIdList: batch, externalIdList: [] },
|
|
2974
|
-
headers: { devtype: "5" }
|
|
2975
|
-
});
|
|
2976
|
-
for (const user of response?.data?.userList || []) {
|
|
2977
|
-
if (user?.id != null) creatorNameMap[String(user.id)] = user.name || null;
|
|
2978
|
-
}
|
|
2979
|
-
} catch {
|
|
2980
|
-
}
|
|
2981
|
-
}
|
|
2982
|
-
}
|
|
2983
|
-
}
|
|
2984
|
-
const statusMap = cache.options?.recruit_status || {};
|
|
2985
|
-
const dictNameMap = {};
|
|
2986
|
-
for (const item of cache.dict?.raw || []) {
|
|
2987
|
-
if (item.option_id && item.selection_name) dictNameMap[item.option_id] = item.selection_name;
|
|
2988
|
-
}
|
|
2989
|
-
const dataRows = rows.map((row) => {
|
|
2990
|
-
let creator = null;
|
|
2991
|
-
if (displayRows) {
|
|
2992
|
-
creator = namesOf(row?.creator);
|
|
2993
|
-
} else if (row?.creator != null) {
|
|
2994
|
-
const raw = String(row.creator).trim();
|
|
2995
|
-
creator = isPlainId(raw) ? creatorNameMap[raw] || raw : namesOf(raw) || raw;
|
|
2996
|
-
}
|
|
2997
|
-
return {
|
|
2998
|
-
talentId: row?.form_data_id || row?.id || null,
|
|
2999
|
-
name: row?.candidate_name || row?.name || null,
|
|
3000
|
-
mobile: row?.telephone || null,
|
|
3001
|
-
channel: dictNameMap[row?.channel] || row?.channel || null,
|
|
3002
|
-
status: statusMap[row?.recruit_status] || row?.recruit_status || null,
|
|
3003
|
-
creator,
|
|
3004
|
-
createTime: row?.create_time || null
|
|
3005
|
-
};
|
|
3006
|
-
});
|
|
3007
|
-
return ehrSuccess("ehr.recruit.candidate.search", { total, totalExact, ...totalNote ? { totalNote } : {}, rows: dataRows });
|
|
3008
|
-
}
|
|
3009
|
-
};
|
|
3010
|
-
var candidateList = {
|
|
3011
|
-
name: "ehr.recruit.candidate.list",
|
|
3012
|
-
resource: "recruit",
|
|
3013
|
-
method: "candidate.list",
|
|
3014
|
-
action: "ehr.recruit.candidate.list",
|
|
3015
|
-
summary: "\u67E5\u8BE2\u62DB\u8058\u4E1A\u52A1\u5217\u8868\uFF08demand \u62DB\u8058\u9700\u6C42 / position \u62DB\u8058\u804C\u4F4D / entry \u5165\u804C\u7BA1\u7406 / offer \u5F55\u7528\u7BA1\u7406\uFF09\uFF0CdisplayData \u663E\u793A\u5C42\u96F6\u7FFB\u8BD1\u8F93\u51FA",
|
|
3016
|
-
capability: "recruit",
|
|
3017
|
-
risk: READ,
|
|
3018
|
-
inputSchema: schemaOf({
|
|
3019
|
-
type: { type: "string", enum: ["demand", "position", "entry", "offer"], description: "\u5217\u8868\u7C7B\u578B" },
|
|
3020
|
-
current: SCHEMA_ID,
|
|
3021
|
-
pageSize: SCHEMA_ID
|
|
3022
|
-
}, { required: ["type"] }),
|
|
3023
|
-
handler: async (args, env) => {
|
|
3024
|
-
const type = typeof args.type === "string" ? args.type : "";
|
|
3025
|
-
const listType = LIST_TYPES[type];
|
|
3026
|
-
if (!listType) {
|
|
3027
|
-
throw ehrValidationError("enum_invalid", `type \u53D6\u503C\u5FC5\u987B\u662F ${Object.keys(LIST_TYPES).join(" / ")} \u4E4B\u4E00`);
|
|
3028
|
-
}
|
|
3029
|
-
if (!env.recruitContext) {
|
|
3030
|
-
throw ehrValidationError("recruit_context_unavailable", "\u62DB\u8058\u4E0A\u4E0B\u6587\u52A0\u8F7D\u5668\u672A\u521D\u59CB\u5316");
|
|
3031
|
-
}
|
|
3032
|
-
const cache = await env.recruitContext.load(env.host);
|
|
3033
|
-
const listParam = cache.lists[listType.listKey];
|
|
3034
|
-
if (!listParam?.listId) {
|
|
3035
|
-
throw new RecruitContextError(
|
|
3036
|
-
"recruit_list_unavailable",
|
|
3037
|
-
`\u5F53\u524D\u73AF\u5883\u672A\u542F\u7528\u300C${listType.title}\u300D\u529F\u80FD\uFF08\u672A\u627E\u5230\u5BF9\u5E94\u83DC\u5355/\u5217\u8868\u53C2\u6570\uFF0C\u6309\u80FD\u529B\u63A2\u6D4B\u62E6\u622A\uFF09\u3002`
|
|
3038
|
-
);
|
|
3039
|
-
}
|
|
3040
|
-
const formObjId = cache.forms[listType.formType]?.objId;
|
|
3041
|
-
if (!formObjId) {
|
|
3042
|
-
throw new RecruitContextError("recruit_context_missing", `\u672A\u89E3\u6790\u5230\u300C${listType.title}\u300D\u5BF9\u5E94\u8868\u5355\uFF0C\u65E0\u6CD5\u67E5\u8BE2\u3002`);
|
|
3043
|
-
}
|
|
3044
|
-
const body = buildListBody({
|
|
3045
|
-
listId: listParam.listId,
|
|
3046
|
-
cusMenuId: listParam.cusMenuId,
|
|
3047
|
-
menuName: listParam.menuName || listType.title,
|
|
3048
|
-
title: listType.title,
|
|
3049
|
-
current: toPositiveInt(args.current, "current") ?? 1,
|
|
3050
|
-
pageSize: toNumber(args.pageSize, "pageSize") ?? 10
|
|
3051
|
-
});
|
|
3052
|
-
const { rows, displayRows, total, totalExact, totalNote } = await fetchListRows(env.host, formObjId, listParam.listId, body);
|
|
3053
|
-
const outRows = rows.map((row) => {
|
|
3054
|
-
const cleaned = { form_data_id: row?.form_data_id || row?.id };
|
|
3055
|
-
for (const [key, value] of Object.entries(row || {})) {
|
|
3056
|
-
if (displayRows) {
|
|
3057
|
-
if (DISPLAY_UI_KEYS.has(key) || key === "form_data_id") continue;
|
|
3058
|
-
if (key.endsWith("Span") || key.endsWith("Action")) continue;
|
|
3059
|
-
const text2 = String(value ?? "");
|
|
3060
|
-
if (!text2) continue;
|
|
3061
|
-
if (typeof value === "object" || typeof value === "string" && text2.trimStart().startsWith("[")) {
|
|
3062
|
-
const names2 = namesOf(value);
|
|
3063
|
-
cleaned[key] = names2 != null ? names2 : text2;
|
|
3064
|
-
continue;
|
|
3065
|
-
}
|
|
3066
|
-
cleaned[key] = text2;
|
|
3067
|
-
continue;
|
|
3068
|
-
}
|
|
3069
|
-
if (INTERNAL_KEYS.has(key)) continue;
|
|
3070
|
-
const text = String(value ?? "");
|
|
3071
|
-
if (!text) continue;
|
|
3072
|
-
if (/^\d{16,}$/.test(text)) continue;
|
|
3073
|
-
const names = typeof value === "object" || typeof value === "string" && text.trimStart().startsWith("[") ? namesOf(value) : null;
|
|
3074
|
-
cleaned[key] = names != null ? names : text;
|
|
3075
|
-
}
|
|
3076
|
-
return cleaned;
|
|
3077
|
-
});
|
|
3078
|
-
return ehrSuccess("ehr.recruit.candidate.list", {
|
|
3079
|
-
type,
|
|
3080
|
-
total,
|
|
3081
|
-
totalExact,
|
|
3082
|
-
...totalNote ? { totalNote } : {},
|
|
3083
|
-
current: body.current,
|
|
3084
|
-
pageSize: body.pageSize,
|
|
3085
|
-
rows: outRows
|
|
3086
|
-
});
|
|
3087
|
-
}
|
|
3088
|
-
};
|
|
3089
|
-
function personNames(value) {
|
|
3090
|
-
const text = String(value ?? "").trim();
|
|
3091
|
-
if (!text) return "";
|
|
3092
|
-
if (text.startsWith("[")) {
|
|
3093
|
-
try {
|
|
3094
|
-
const arr = JSON.parse(text);
|
|
3095
|
-
if (Array.isArray(arr)) {
|
|
3096
|
-
const names = arr.map((item) => typeof item === "string" ? item : item?.name ?? item?.username ?? "").filter(Boolean);
|
|
3097
|
-
if (names.length) return names.join("\u3001");
|
|
3098
|
-
}
|
|
3099
|
-
} catch {
|
|
3100
|
-
}
|
|
3101
|
-
}
|
|
3102
|
-
return text;
|
|
3103
|
-
}
|
|
3104
|
-
function nameLike(value) {
|
|
3105
|
-
const text = String(value ?? "").trim();
|
|
3106
|
-
if (!text || /^\d{16,}$/.test(text)) return null;
|
|
3107
|
-
return text;
|
|
3108
|
-
}
|
|
3109
|
-
async function resolveCurrentUserName(host) {
|
|
3110
|
-
try {
|
|
3111
|
-
const session = await host.getSession();
|
|
3112
|
-
const baseUrl = String(session?.baseUrl || "");
|
|
3113
|
-
if (!baseUrl) return "";
|
|
3114
|
-
const resp = await fetch(
|
|
3115
|
-
`${baseUrl}/api/baseserver/layout/teamsCheck?clientType=not_xinchuang&client=WEB&domainName=${encodeURIComponent(baseUrl)}`,
|
|
3116
|
-
{
|
|
3117
|
-
method: "POST",
|
|
3118
|
-
headers: {
|
|
3119
|
-
accept: "application/json",
|
|
3120
|
-
"content-type": "application/json",
|
|
3121
|
-
eteamsid: String(session?.eteamsId || ""),
|
|
3122
|
-
cookie: typeof session?.cookieHeader === "function" ? session.cookieHeader() : "",
|
|
3123
|
-
"user-agent": typeof session?.uaHeader === "function" ? session.uaHeader() : "weaver-work-cli",
|
|
3124
|
-
origin: baseUrl
|
|
3125
|
-
},
|
|
3126
|
-
redirect: "manual"
|
|
3127
|
-
}
|
|
3128
|
-
);
|
|
3129
|
-
const data = await resp.json().catch(() => ({}));
|
|
3130
|
-
const cu = data.currentUser ?? data.data?.currentUser ?? null;
|
|
3131
|
-
return cu ? String(cu.username ?? cu.id ?? "") : "";
|
|
3132
|
-
} catch {
|
|
3133
|
-
return "";
|
|
3134
|
-
}
|
|
3135
|
-
}
|
|
3136
|
-
var interviewFeedbackTodo = {
|
|
3137
|
-
name: "ehr.recruit.interview.feedbackTodo",
|
|
3138
|
-
resource: "recruit",
|
|
3139
|
-
method: "interview.feedbackTodo",
|
|
3140
|
-
action: "ehr.recruit.interview.feedbackTodo",
|
|
3141
|
-
summary: "\u9762\u8BD5\u5F85\u529E\uFF1A**\u53EA\u8FD4\u56DE\u6211\u4F5C\u4E3A\u9762\u8BD5\u5B98\u7684 AI \u9762\u8BD5\u5F85\u53CD\u9988\u6E05\u5355**\uFF08\u5019\u9009\u4EBA\u5DF2\u7B54\u5B8C\u3001\u5DF2\u6709\u5F55\u50CF\u3001\u6211\u8FD8\u6CA1\u586B\u610F\u89C1\uFF09\uFF1B\u6309\u9700\u7FFB\u9875 + \u5BA2\u6237\u7AEF\u7B5B\u9009\uFF0C\u4E0D\u8FD4\u56DE\u5168\u91CF\u9762\u8BD5",
|
|
3142
|
-
capability: "recruit",
|
|
3143
|
-
risk: READ,
|
|
3144
|
-
inputSchema: schemaOf({
|
|
3145
|
-
maxPages: { type: "integer", minimum: 1, maximum: 50, description: "\u6700\u591A\u7FFB\u9875\u6570\uFF08\u9ED8\u8BA4 5\uFF09" },
|
|
3146
|
-
pageSize: { type: "integer", minimum: 1, maximum: 200, description: "\u5355\u9875\u6761\u6570\uFF08\u9ED8\u8BA4 200\uFF0C\u5B9E\u6D4B\u670D\u52A1\u7AEF\u4E0A\u9650 200\uFF09" }
|
|
3147
|
-
}),
|
|
3148
|
-
handler: async (args, env) => {
|
|
3149
|
-
if (!env.recruitContext) throw ehrValidationError("recruit_context_unavailable", "\u62DB\u8058\u4E0A\u4E0B\u6587\u52A0\u8F7D\u5668\u672A\u521D\u59CB\u5316");
|
|
3150
|
-
const cache = await env.recruitContext.load(env.host);
|
|
3151
|
-
const listParam = cache.lists.interview;
|
|
3152
|
-
const form = cache.forms.interview_plan;
|
|
3153
|
-
if (!listParam?.listId || !form?.objId) {
|
|
3154
|
-
throw new RecruitContextError(
|
|
3155
|
-
"recruit_list_unavailable",
|
|
3156
|
-
"\u5F53\u524D\u73AF\u5883\u672A\u542F\u7528\u300C\u9762\u8BD5\u7BA1\u7406\u300D\u529F\u80FD\uFF08\u672A\u627E\u5230\u9762\u8BD5\u5217\u8868/\u8868\u5355\u53C2\u6570\uFF0C\u6309\u80FD\u529B\u63A2\u6D4B\u62E6\u622A\uFF09\u3002"
|
|
3157
|
-
);
|
|
3158
|
-
}
|
|
3159
|
-
const pageSize = toNumber(args.pageSize, "pageSize") ?? 200;
|
|
3160
|
-
const maxPages = toNumber(args.maxPages, "maxPages") ?? 5;
|
|
3161
|
-
const me = await resolveCurrentUserName(env.host);
|
|
3162
|
-
const fields = cache.fields[form.objId] || {};
|
|
3163
|
-
const fieldOpts = cache.field_options[form.objId] || {};
|
|
3164
|
-
const statusOpts = fieldOpts[fields.union_status] || {};
|
|
3165
|
-
const typeOpts = fieldOpts[fields.interview_type] || {};
|
|
3166
|
-
const toCn = (map, raw) => {
|
|
3167
|
-
const text = String(raw ?? "");
|
|
3168
|
-
return map[text] ?? text;
|
|
3169
|
-
};
|
|
3170
|
-
const statusOf = (row) => toCn(statusOpts, row?.union_status_key ?? row?.union_status);
|
|
3171
|
-
const typeOf = (row) => toCn(typeOpts, row?.interview_type_key ?? row?.interview_type);
|
|
3172
|
-
const interviewerOf = (row) => personNames(row?.interviewer);
|
|
3173
|
-
const scanned = [];
|
|
3174
|
-
let lastPageCount = 0;
|
|
3175
|
-
for (let i = 0; i < maxPages; i++) {
|
|
3176
|
-
const body = buildListBody({
|
|
3177
|
-
listId: listParam.listId,
|
|
3178
|
-
cusMenuId: listParam.cusMenuId,
|
|
3179
|
-
menuName: listParam.menuName || "\u9762\u8BD5\u7BA1\u7406",
|
|
3180
|
-
title: "\u9762\u8BD5\u7BA1\u7406",
|
|
3181
|
-
current: i + 1,
|
|
3182
|
-
pageSize
|
|
3183
|
-
});
|
|
3184
|
-
const page = await fetchListRows(env.host, form.objId, listParam.listId, body);
|
|
3185
|
-
const use = page.displayRows && page.displayRows.length ? page.displayRows : page.rows;
|
|
3186
|
-
scanned.push(...use);
|
|
3187
|
-
lastPageCount = use.length;
|
|
3188
|
-
if (use.length < pageSize) break;
|
|
3189
|
-
}
|
|
3190
|
-
const pending = scanned.filter((row) => /待反馈/.test(statusOf(row)));
|
|
3191
|
-
const mineAll = me ? pending.filter((row) => interviewerOf(row).includes(me)) : [];
|
|
3192
|
-
const mineAi = mineAll.filter((row) => /AI\s*面试/i.test(typeOf(row)));
|
|
3193
|
-
const slim = (row) => ({
|
|
3194
|
-
form_data_id: row?.form_data_id ?? row?.id ?? null,
|
|
3195
|
-
candidate_name: nameLike(row?.candidate_name) ?? nameLike(row?.talent_id) ?? nameLike(row?.name),
|
|
3196
|
-
position_name: nameLike(row?.position_name) ?? nameLike(row?.position_manage_id),
|
|
3197
|
-
start_time: row?.start_time ?? null,
|
|
3198
|
-
interview_type_key: typeOf(row) || null,
|
|
3199
|
-
interview_session: row?.interview_session ?? null,
|
|
3200
|
-
interviewer: interviewerOf(row) || null,
|
|
3201
|
-
union_status_key: statusOf(row) || null,
|
|
3202
|
-
subject: row?.subject ?? null,
|
|
3203
|
-
talent_id: row?.talent_id ?? null,
|
|
3204
|
-
position_manage_id: row?.position_manage_id ?? null
|
|
3205
|
-
});
|
|
3206
|
-
const notes = [];
|
|
3207
|
-
if (!me) notes.push("\u672A\u80FD\u89E3\u6790\u5F53\u524D\u767B\u5F55\u4EBA\u59D3\u540D\uFF08teamsCheck \u5931\u8D25\uFF09\uFF0C\u65E0\u6CD5\u6309\u9762\u8BD5\u5B98\u8FC7\u6EE4");
|
|
3208
|
-
if (lastPageCount >= pageSize && scanned.length >= pageSize * maxPages) {
|
|
3209
|
-
notes.push(`\u5DF2\u626B\u63CF ${scanned.length} \u6761\uFF08\u8FBE maxPages=${maxPages} \u4E0A\u9650\uFF09\uFF0C\u5982\u6000\u7591\u9057\u6F0F\u53EF\u52A0\u5927 maxPages`);
|
|
3210
|
-
}
|
|
3211
|
-
return ehrSuccess("ehr.recruit.interview.feedbackTodo", {
|
|
3212
|
-
currentUser: me || null,
|
|
3213
|
-
scanned: scanned.length,
|
|
3214
|
-
myAiPendingFeedback: { count: mineAi.length, rows: mineAi.map(slim) },
|
|
3215
|
-
myOtherPendingFeedback: {
|
|
3216
|
-
count: mineAll.length - mineAi.length,
|
|
3217
|
-
rows: mineAll.filter((row) => !/AI\s*面试/i.test(typeOf(row))).map(slim)
|
|
3218
|
-
},
|
|
3219
|
-
...notes.length ? { note: notes.join("\uFF1B") } : {}
|
|
3220
|
-
});
|
|
3221
|
-
}
|
|
3222
|
-
};
|
|
3223
|
-
var candidateCard = {
|
|
3224
|
-
name: "ehr.recruit.candidate.card",
|
|
3225
|
-
resource: "recruit",
|
|
3226
|
-
method: "candidate.card",
|
|
3227
|
-
action: "ehr.recruit.candidate.card",
|
|
3228
|
-
summary: "\u67E5\u770B\u4EBA\u624D\u8BE6\u60C5\u5361\u7247\uFF1A\u6743\u9650\u6821\u9A8C + \u56DB\u5F20\u5361\u7247\uFF08\u57FA\u672C\u4FE1\u606F/\u5E94\u8058\u8FDB\u5C55/\u9762\u8BD5\u5B89\u6392/\u6C9F\u901A\u5907\u6CE8\uFF09\u5E76\u884C\u62C9\u53D6\uFF0C\u59D3\u540D\u4E0E\u5B57\u5178\u5168\u90E8\u5185\u8054\u89E3\u6790",
|
|
3229
|
-
capability: "recruit",
|
|
3230
|
-
risk: READ,
|
|
3231
|
-
inputSchema: schemaOf(
|
|
3232
|
-
{ talentId: { oneOf: [{ type: "integer" }, { type: "string", pattern: "^\\d+$" }], description: "\u4EBA\u624D ID\uFF0C\u6765\u81EA candidate.search \u7684 talentId" } },
|
|
3233
|
-
{ required: ["talentId"] }
|
|
3234
|
-
),
|
|
3235
|
-
handler: async (args, env) => {
|
|
3236
|
-
const talentId = args.talentId;
|
|
3237
|
-
if (talentId === void 0 || talentId === null || talentId === "") {
|
|
3238
|
-
throw ehrValidationError("talent_id_required", "talentId \u5FC5\u586B");
|
|
3239
|
-
}
|
|
3240
|
-
if (!/^\d+$/.test(String(talentId).trim())) {
|
|
3241
|
-
throw ehrValidationError("talent_id_invalid", "talentId \u5FC5\u987B\u662F\u6570\u5B57 ID");
|
|
3242
|
-
}
|
|
3243
|
-
const id = String(talentId).trim();
|
|
3244
|
-
if (!env.recruitContext) {
|
|
3245
|
-
throw ehrValidationError("recruit_context_unavailable", "\u62DB\u8058\u4E0A\u4E0B\u6587\u52A0\u8F7D\u5668\u672A\u521D\u59CB\u5316");
|
|
3246
|
-
}
|
|
3247
|
-
const cache = await env.recruitContext.load(env.host);
|
|
3248
|
-
const talentListId = cache.lists.talent?.listId || "";
|
|
3249
|
-
const extra = talentListId ? { ebBusinessId: talentListId } : {};
|
|
3250
|
-
const rk1 = randHex6();
|
|
3251
|
-
const [rightsResponse, prepareResponse] = await Promise.all([
|
|
3252
|
-
env.host.request({
|
|
3253
|
-
path: `/api/recruit/talent/hasRights?formDataId=${id}`,
|
|
3254
|
-
method: "POST",
|
|
3255
|
-
headers: extra
|
|
3256
|
-
}),
|
|
3257
|
-
env.host.request({
|
|
3258
|
-
path: `/api/recruit/candidate/getCandidateCardPrepareQuery?talentId=${id}&randomkey_${rk1}=${rk1}`,
|
|
3259
|
-
headers: extra
|
|
3260
|
-
})
|
|
3261
|
-
]);
|
|
3262
|
-
const rights = rightsResponse?.data || [];
|
|
3263
|
-
if (!rights.includes("READ")) {
|
|
3264
|
-
throw ehrValidationError("recruit_rights_denied", "\u5F53\u524D\u8D26\u53F7\u65E0\u8BE5\u4EBA\u624D\u8BE6\u60C5\u7684 READ \u6743\u9650\uFF0C\u65E0\u6CD5\u67E5\u770B\u3002");
|
|
3265
|
-
}
|
|
3266
|
-
const batchId = prepareResponse?.data?.batchId;
|
|
3267
|
-
if (!batchId) {
|
|
3268
|
-
throw new RecruitContextError("recruit_batch_id_missing", "\u672A\u53D6\u5230 batchId\uFF08prepareQuery \u8FD4\u56DE\u5F02\u5E38\uFF09\uFF0C\u65E0\u6CD5\u67E5\u770B\u8BE6\u60C5\u5361\u7247\u3002");
|
|
3269
|
-
}
|
|
3270
|
-
const rk2 = randHex6();
|
|
3271
|
-
const v = randHex6();
|
|
3272
|
-
const query = `talentId=${id}&batchId=${batchId}&v=${v}&randomkey_${rk2}=${rk2}`;
|
|
3273
|
-
const cardBody = { talentId: id, batchId, current: 1, pageSize: 100 };
|
|
3274
|
-
const [base, other, interview, remark] = await Promise.all([
|
|
3275
|
-
env.host.request({ path: `/api/recruit/candidate/getCandidateCardBaseInfo?${query}`, headers: extra }),
|
|
3276
|
-
env.host.request({ path: `/api/recruit/candidate/getCandidateCardOtherInfo?${query}`, headers: extra }),
|
|
3277
|
-
env.host.request({ path: "/api/recruit/candidate/getCandidateCardInterviewInfo", body: cardBody, headers: extra }),
|
|
3278
|
-
env.host.request({ path: "/api/recruit/candidate/getCandidateCardRemark", body: cardBody, headers: extra })
|
|
3279
|
-
]);
|
|
3280
|
-
const statusMap = cache.options?.recruit_status || {};
|
|
3281
|
-
const talent = base?.data?.talent || {};
|
|
3282
|
-
const currentBatch = other?.data?.currentCandidateBatch || {};
|
|
3283
|
-
const interviewList = interview?.data?.list || [];
|
|
3284
|
-
const remarkList = remark?.data?.list || [];
|
|
3285
|
-
const baseUrl = (await env.host.getSession()).baseUrl.replace(/\/+$/, "");
|
|
3286
|
-
return ehrSuccess("ehr.recruit.candidate.card", {
|
|
3287
|
-
talentId: id,
|
|
3288
|
-
cardLink: cache.ebdDetailPageId ? `${baseUrl}/sp/ebdpage/view/${cache.ebdDetailPageId}?talentId=${id}${String(cache.selfUse ?? "") === "1" ? "&recruitType=useSelf" : ""}` : null,
|
|
3289
|
-
baseInfo: {
|
|
3290
|
-
name: talent?.hrm?.name,
|
|
3291
|
-
mobile: talent?.telephone,
|
|
3292
|
-
channel: talent?.channel,
|
|
3293
|
-
status: statusMap[base?.data?.recruitStatus] || base?.data?.recruitStatus || null,
|
|
3294
|
-
createTime: talent?.createTime
|
|
3295
|
-
},
|
|
3296
|
-
position: {
|
|
3297
|
-
position: currentBatch?.position?.name,
|
|
3298
|
-
stage: currentBatch?.currentStageName,
|
|
3299
|
-
stages: (currentBatch?.allStage || []).map((stage) => stage?.stageName).filter(Boolean),
|
|
3300
|
-
archiveStatus: currentBatch?.archiveStatus?.name,
|
|
3301
|
-
employManager: namesOf(currentBatch?.employManager),
|
|
3302
|
-
channel: currentBatch?.channel,
|
|
3303
|
-
candidateManageId: currentBatch?.id || currentBatch?.candidateManageId || null,
|
|
3304
|
-
batchId: currentBatch?.batchId || batchId,
|
|
3305
|
-
positionId: currentBatch?.position?.id || null
|
|
3306
|
-
},
|
|
3307
|
-
interviews: interviewList.map((item) => ({
|
|
3308
|
-
subject: item?.subject,
|
|
3309
|
-
startTime: item?.startTime || null,
|
|
3310
|
-
endTime: item?.endTime || null,
|
|
3311
|
-
status: namesOf(item?.unionStatus),
|
|
3312
|
-
type: namesOf(item?.interviewType),
|
|
3313
|
-
round: namesOf(item?.interviewSession),
|
|
3314
|
-
interviewer: namesOf(item?.interviewer),
|
|
3315
|
-
arranger: namesOf(item?.creator),
|
|
3316
|
-
updater: namesOf(item?.updater),
|
|
3317
|
-
position: namesOf(item?.positionManageId),
|
|
3318
|
-
feedbacks: (item?.interviewFeedBack || []).map((feedback) => ({
|
|
3319
|
-
result: feedback?.result?.[0]?.name || null,
|
|
3320
|
-
comment: feedback?.judgement ? feedback.judgement.replace(/<[^>]+>/g, "").trim() : null,
|
|
3321
|
-
feedbacker: namesOf(feedback?.updater),
|
|
3322
|
-
createTime: feedback?.createTime
|
|
3323
|
-
}))
|
|
3324
|
-
})),
|
|
3325
|
-
remarks: remarkList.map((item) => ({
|
|
3326
|
-
time: item?.contactTime || item?.createTime,
|
|
3327
|
-
creator: item?.creator?.username || item?.creator?.name || null,
|
|
3328
|
-
content: item?.remark
|
|
3329
|
-
}))
|
|
3330
|
-
});
|
|
3331
|
-
}
|
|
3332
|
-
};
|
|
3333
|
-
var recruitOperations = [
|
|
3334
|
-
contextResolve,
|
|
3335
|
-
candidateSearch,
|
|
3336
|
-
candidateList,
|
|
3337
|
-
candidateCard,
|
|
3338
|
-
interviewFeedbackTodo
|
|
3339
|
-
];
|
|
3340
|
-
|
|
3341
2270
|
// src/shortcuts/ehr/operations/recruit-write.ts
|
|
3342
2271
|
import { createHash as createHash3 } from "node:crypto";
|
|
3343
|
-
var CONTINUATION_TTL_SECONDS2 = 600;
|
|
3344
2272
|
function fingerprint2(value) {
|
|
3345
2273
|
return createHash3("sha256").update(JSON.stringify(value ?? null)).digest("hex").slice(0, 32);
|
|
3346
2274
|
}
|
|
@@ -3631,21 +2559,25 @@ async function resolveCandidateForWrite(host, cache, talentId) {
|
|
|
3631
2559
|
throw ehrValidationError("recruit_batch_id_missing", "\u672A\u53D6\u5230 batchId\uFF08prepareQuery \u8FD4\u56DE\u5F02\u5E38\uFF09\uFF0C\u65E0\u6CD5\u5B9A\u4F4D\u5019\u9009\u4EBA\u5E94\u8058\u6279\u6B21");
|
|
3632
2560
|
}
|
|
3633
2561
|
const v = randomHex6();
|
|
3634
|
-
const otherResponse = await
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
if (!name) {
|
|
3641
|
-
const baseResponse = await host.request({
|
|
2562
|
+
const [otherResponse, baseResponse] = await Promise.all([
|
|
2563
|
+
host.request({
|
|
2564
|
+
path: `/api/recruit/candidate/getCandidateCardOtherInfo?talentId=${talentId}&batchId=${batchId}&v=${v}&randomkey_ab=ab`,
|
|
2565
|
+
headers: extra
|
|
2566
|
+
}),
|
|
2567
|
+
host.request({
|
|
3642
2568
|
path: `/api/recruit/candidate/getCandidateCardBaseInfo?talentId=${talentId}&batchId=${batchId}&v=${v}&randomkey_cd=cd`,
|
|
3643
2569
|
headers: extra
|
|
3644
|
-
})
|
|
3645
|
-
|
|
3646
|
-
}
|
|
2570
|
+
}).catch(() => null)
|
|
2571
|
+
]);
|
|
2572
|
+
const batch = otherResponse?.data?.currentCandidateBatch || {};
|
|
2573
|
+
const talentBase = baseResponse?.data?.talent || {};
|
|
2574
|
+
const name = batch?.talent?.name || talentBase?.hrm?.name || talentBase?.name || "";
|
|
2575
|
+
const email = String(talentBase.email || talentBase.hrm?.email || "").trim();
|
|
2576
|
+
const mobile = String(talentBase.telephone || talentBase.mobile || "").trim();
|
|
3647
2577
|
return {
|
|
3648
2578
|
name,
|
|
2579
|
+
email,
|
|
2580
|
+
mobile,
|
|
3649
2581
|
candidateManageId: batch?.id || batch?.candidateManageId || null,
|
|
3650
2582
|
positionId: batch?.position?.id || null,
|
|
3651
2583
|
positionName: batch?.position?.name || null,
|
|
@@ -3733,14 +2665,14 @@ var candidateCreatePrepare = {
|
|
|
3733
2665
|
payload: { name, mobile, channel: channelName, formId: talentObj?.formId || talentObj?.objId, objId: talentObj?.objId, dataDetails },
|
|
3734
2666
|
fingerprint: fingerprint2({ name, mobile, channel: channelName, dataDetails })
|
|
3735
2667
|
},
|
|
3736
|
-
|
|
2668
|
+
CONTINUATION_TTL_SECONDS * 1e3
|
|
3737
2669
|
);
|
|
3738
2670
|
return ehrSuccess("ehr.recruit.candidate.create.prepare", {
|
|
3739
2671
|
status: "AWAITING_CONFIRMATION",
|
|
3740
2672
|
preview,
|
|
3741
2673
|
willSubmit: { formId: talentObj?.formId || talentObj?.objId, objId: talentObj?.objId, dataDetails },
|
|
3742
2674
|
continuation: token,
|
|
3743
|
-
expiresInSeconds:
|
|
2675
|
+
expiresInSeconds: CONTINUATION_TTL_SECONDS
|
|
3744
2676
|
});
|
|
3745
2677
|
}
|
|
3746
2678
|
};
|
|
@@ -3855,6 +2787,7 @@ var candidateCreateApply = {
|
|
|
3855
2787
|
}
|
|
3856
2788
|
};
|
|
3857
2789
|
var INTERVIEW_TYPES = ["\u73B0\u573A\u9762\u8BD5", "\u89C6\u9891\u9762\u8BD5", "\u7535\u8BDD\u9762\u8BD5", "AI\u9762\u8BD5"];
|
|
2790
|
+
var AI_DEFAULT_PLAN_NAME = "\u5927\u6A21\u578B\u9762\u8BD5";
|
|
3858
2791
|
var INTERVIEW_DATAKEYS = [
|
|
3859
2792
|
"subject",
|
|
3860
2793
|
"start_time",
|
|
@@ -3877,15 +2810,150 @@ function defaultInterviewWindow() {
|
|
|
3877
2810
|
const end = new Date(now.getTime() + 60 * 60 * 1e3);
|
|
3878
2811
|
return { start: fmt(now), end: fmt(end) };
|
|
3879
2812
|
}
|
|
2813
|
+
async function resolveCurrentUserForWrite(host) {
|
|
2814
|
+
try {
|
|
2815
|
+
const session = await host.getSession();
|
|
2816
|
+
const baseUrl = String(session?.baseUrl || "");
|
|
2817
|
+
if (!baseUrl) return null;
|
|
2818
|
+
const resp = await fetch(
|
|
2819
|
+
`${baseUrl}/api/baseserver/layout/teamsCheck?clientType=not_xinchuang&client=WEB&domainName=${encodeURIComponent(baseUrl)}`,
|
|
2820
|
+
{
|
|
2821
|
+
method: "POST",
|
|
2822
|
+
headers: {
|
|
2823
|
+
accept: "application/json",
|
|
2824
|
+
"content-type": "application/json",
|
|
2825
|
+
eteamsid: String(session?.eteamsId || ""),
|
|
2826
|
+
cookie: typeof session?.cookieHeader === "function" ? session.cookieHeader() : "",
|
|
2827
|
+
"user-agent": typeof session?.uaHeader === "function" ? session.uaHeader() : "weaver-work-cli",
|
|
2828
|
+
origin: baseUrl
|
|
2829
|
+
},
|
|
2830
|
+
redirect: "manual"
|
|
2831
|
+
}
|
|
2832
|
+
);
|
|
2833
|
+
const data = await resp.json().catch(() => ({}));
|
|
2834
|
+
const cu = data?.currentUser ?? data?.data?.currentUser ?? null;
|
|
2835
|
+
if (!cu?.id) return null;
|
|
2836
|
+
return { id: String(cu.id), name: String(cu.username || cu.id) };
|
|
2837
|
+
} catch {
|
|
2838
|
+
return null;
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2841
|
+
async function fetchLayoutIdForForm(host, formId) {
|
|
2842
|
+
try {
|
|
2843
|
+
const r = await host.request({
|
|
2844
|
+
path: `/api/ebuilder/form/form/core/getFormLayout?formId=${encodeURIComponent(formId)}`,
|
|
2845
|
+
method: "GET"
|
|
2846
|
+
});
|
|
2847
|
+
const id = r?.data?.formLayout?.id;
|
|
2848
|
+
if (id) return String(id);
|
|
2849
|
+
} catch {
|
|
2850
|
+
}
|
|
2851
|
+
try {
|
|
2852
|
+
const r = await host.request({
|
|
2853
|
+
path: "/api/ebuilder/form/form/core/getFormLayout",
|
|
2854
|
+
method: "POST",
|
|
2855
|
+
body: { module: "ebuilderform", formId, terminalType: "PC" }
|
|
2856
|
+
});
|
|
2857
|
+
const id = r?.data?.formLayout?.id;
|
|
2858
|
+
if (id) return String(id);
|
|
2859
|
+
} catch {
|
|
2860
|
+
}
|
|
2861
|
+
return formId;
|
|
2862
|
+
}
|
|
2863
|
+
var DIGITAL_PLAN_NAME_KEYS = ["msfa_name", "digital_name", "plan_name", "scheme_name"];
|
|
2864
|
+
async function listDigitalPlansForWrite(host, cache, formId, layoutId, fieldId) {
|
|
2865
|
+
try {
|
|
2866
|
+
const r = await host.request({
|
|
2867
|
+
path: "/api/ebuilder/form/common/browser/complete/ebuilder",
|
|
2868
|
+
body: {
|
|
2869
|
+
browserMultiple: false,
|
|
2870
|
+
newly: 1,
|
|
2871
|
+
searchValue: "",
|
|
2872
|
+
formParam: JSON.stringify({ formId, layoutId, fieldId, filterItems: [], module: "ebuilderform", dataDetails: [] }),
|
|
2873
|
+
openScroll: true,
|
|
2874
|
+
controlId: fieldId,
|
|
2875
|
+
businessId: formId,
|
|
2876
|
+
variableMap: {}
|
|
2877
|
+
}
|
|
2878
|
+
});
|
|
2879
|
+
if (r?.status !== false && r?.data) {
|
|
2880
|
+
const list = r.data.data || [];
|
|
2881
|
+
const items2 = list.filter((x) => x && x.id).map((x) => ({ id: String(x.id), name: String(x.name || "").trim() }));
|
|
2882
|
+
if (items2.length) return { available: true, items: items2 };
|
|
2883
|
+
}
|
|
2884
|
+
} catch {
|
|
2885
|
+
}
|
|
2886
|
+
const menus = cache.lists?.all_search || [];
|
|
2887
|
+
const menu = menus.find((m) => (m.menuName || "").includes("\u9762\u8BD5\u6570\u5B57\u4EBA")) || menus.find((m) => (m.menuName || "").includes("\u6570\u5B57\u4EBA\u914D\u7F6E"));
|
|
2888
|
+
if (!menu?.listId) {
|
|
2889
|
+
return { available: false, items: [], reason: "\u5173\u8054\u5B57\u6BB5\u5019\u9009\u63A5\u53E3\u4E0D\u53EF\u7528\uFF0C\u4E14\u5F53\u524D\u73AF\u5883\u672A\u914D\u7F6E\u300C\u9762\u8BD5\u6570\u5B57\u4EBA\u914D\u7F6E\u300D\u5217\u8868\u83DC\u5355" };
|
|
2890
|
+
}
|
|
2891
|
+
let objId = "";
|
|
2892
|
+
try {
|
|
2893
|
+
const r = await host.request({
|
|
2894
|
+
path: `/api/ebuilder/form/obj/getObjsByTag?appId=${encodeURIComponent(String(cache.appId || ""))}&tag=uf_rcrt_digital_human`,
|
|
2895
|
+
method: "GET"
|
|
2896
|
+
});
|
|
2897
|
+
const d = r?.data;
|
|
2898
|
+
if (Array.isArray(d) && d.length) objId = String(d[0]?.id || "");
|
|
2899
|
+
} catch {
|
|
2900
|
+
}
|
|
2901
|
+
if (!objId) return { available: false, items: [], reason: "\u672A\u80FD\u89E3\u6790\u300C\u9762\u8BD5\u6570\u5B57\u4EBA\u914D\u7F6E\u300D\u5BF9\u8C61 id" };
|
|
2902
|
+
const rows = [];
|
|
2903
|
+
for (let cur = 1; cur <= 20; cur++) {
|
|
2904
|
+
const r = await host.request({
|
|
2905
|
+
path: `/api/ebuilder/form/list/getListDatas?passid=${objId}&cid=${objId}`,
|
|
2906
|
+
body: {
|
|
2907
|
+
current: cur,
|
|
2908
|
+
pageSize: 100,
|
|
2909
|
+
tableuid: randomHex32(),
|
|
2910
|
+
listId: menu.listId,
|
|
2911
|
+
searchParamData: { searchType: "3", type: "and" },
|
|
2912
|
+
terminal: "PC",
|
|
2913
|
+
browser: "Chrome",
|
|
2914
|
+
requiredMatch: 1,
|
|
2915
|
+
mapResult: 1,
|
|
2916
|
+
recheckQuery: 1,
|
|
2917
|
+
isFollow: 0,
|
|
2918
|
+
isShareToMe: 0,
|
|
2919
|
+
filterCondition: {},
|
|
2920
|
+
cusMenuId: menu.cusMenuId,
|
|
2921
|
+
urlPageTitle: menu.menuName,
|
|
2922
|
+
menuName: menu.menuName
|
|
2923
|
+
},
|
|
2924
|
+
headers: { ebBusinessId: String(menu.listId) }
|
|
2925
|
+
});
|
|
2926
|
+
const page = r?.data?.data || [];
|
|
2927
|
+
rows.push(...page);
|
|
2928
|
+
if (page.length < 100) break;
|
|
2929
|
+
}
|
|
2930
|
+
const items = rows.map((x) => {
|
|
2931
|
+
const nk = DIGITAL_PLAN_NAME_KEYS.find((k) => String(x[k] || "").trim());
|
|
2932
|
+
return { id: String(x.form_data_id || x.id || ""), name: String(nk ? x[nk] : "").trim() };
|
|
2933
|
+
}).filter((x) => x.id);
|
|
2934
|
+
if (!items.length) return { available: false, items: [], reason: "\u300C\u9762\u8BD5\u6570\u5B57\u4EBA\u914D\u7F6E\u300D\u6682\u65E0\u53EF\u9009\u65B9\u6848" };
|
|
2935
|
+
return { available: true, items };
|
|
2936
|
+
}
|
|
2937
|
+
function pickDigitalPlanForWrite(items, key) {
|
|
2938
|
+
const k = String(key || "").trim();
|
|
2939
|
+
if (!k) return { plan: null, ambiguous: [] };
|
|
2940
|
+
const byId = items.filter((x) => x.id === k);
|
|
2941
|
+
if (byId.length === 1) return { plan: byId[0], ambiguous: [] };
|
|
2942
|
+
const byExact = items.filter((x) => x.name === k);
|
|
2943
|
+
if (byExact.length === 1) return { plan: byExact[0], ambiguous: [] };
|
|
2944
|
+
const byLike = items.filter((x) => x.name.includes(k));
|
|
2945
|
+
if (byLike.length === 1) return { plan: byLike[0], ambiguous: [] };
|
|
2946
|
+
return { plan: null, ambiguous: byLike };
|
|
2947
|
+
}
|
|
3880
2948
|
async function buildInterviewPlan(env, cache, args) {
|
|
3881
2949
|
const host = env.host;
|
|
3882
2950
|
const talentId = requiredString(args, "talentId", "talent_id_required", "\u4EBA\u624D ID");
|
|
3883
2951
|
if (!/^\d+$/.test(talentId)) throw ehrValidationError("talent_id_invalid", "talentId \u5FC5\u987B\u662F\u6570\u5B57 ID");
|
|
3884
|
-
const interviewer = requiredString(args, "interviewer", "interviewer_required", "\u9762\u8BD5\u5B98\u59D3\u540D");
|
|
3885
2952
|
const type = typeof args.type === "string" && args.type.trim() ? args.type.trim() : "\u73B0\u573A\u9762\u8BD5";
|
|
3886
2953
|
if (!INTERVIEW_TYPES.includes(type)) {
|
|
3887
2954
|
throw ehrValidationError("enum_invalid", `type\uFF08\u9762\u8BD5\u65B9\u5F0F\uFF09\u53D6\u503C\u5FC5\u987B\u662F ${INTERVIEW_TYPES.join(" / ")} \u4E4B\u4E00`);
|
|
3888
2955
|
}
|
|
2956
|
+
const isAI = type === "AI\u9762\u8BD5";
|
|
3889
2957
|
const session = typeof args.session === "string" && args.session.trim() ? args.session.trim() : "\u521D\u8BD5";
|
|
3890
2958
|
const candidate = await resolveCandidateForWrite(host, cache, talentId);
|
|
3891
2959
|
const positionId = args.positionId ? String(args.positionId) : candidate.positionId;
|
|
@@ -3914,9 +2982,69 @@ async function buildInterviewPlan(env, cache, args) {
|
|
|
3914
2982
|
if (!sessionOptionId) {
|
|
3915
2983
|
throw ehrValidationError("enum_invalid", `\u9762\u8BD5\u8F6E\u6B21\u300C${session}\u300D\u4E0D\u5728\u679A\u4E3E\u4E2D\uFF08${Object.keys(sessionMap).join(" / ")}\uFF09`);
|
|
3916
2984
|
}
|
|
3917
|
-
const
|
|
3918
|
-
|
|
3919
|
-
|
|
2985
|
+
const interviewerInput = typeof args.interviewer === "string" ? args.interviewer.trim() : "";
|
|
2986
|
+
let interviewerId = null;
|
|
2987
|
+
let interviewer = interviewerInput;
|
|
2988
|
+
if (interviewerInput) {
|
|
2989
|
+
interviewerId = await resolvePersonId(host, fieldIdOf("interviewer"), interviewerInput);
|
|
2990
|
+
if (!interviewerId) {
|
|
2991
|
+
throw ehrValidationError("interviewer_not_found", `\u9762\u8BD5\u5B98\u300C${interviewerInput}\u300D\u89E3\u6790\u4E0D\u5230 userId\uFF08browser/complete/resource \u65E0\u5339\u914D\uFF09`);
|
|
2992
|
+
}
|
|
2993
|
+
} else {
|
|
2994
|
+
const me = await resolveCurrentUserForWrite(host);
|
|
2995
|
+
if (!me) {
|
|
2996
|
+
throw ehrValidationError("interviewer_unresolved", "\u672A\u6307\u5B9A\u9762\u8BD5\u5B98\uFF0C\u4E14\u65E0\u6CD5\u89E3\u6790\u5F53\u524D\u767B\u5F55\u4EBA\uFF08teamsCheck \u5931\u8D25\uFF09\uFF1B\u8BF7\u7528 interviewer \u53C2\u6570\u6307\u5B9A");
|
|
2997
|
+
}
|
|
2998
|
+
interviewerId = await resolvePersonId(host, fieldIdOf("interviewer"), me.name);
|
|
2999
|
+
if (!interviewerId) {
|
|
3000
|
+
throw ehrValidationError(
|
|
3001
|
+
"interviewer_unresolved",
|
|
3002
|
+
`\u672A\u6307\u5B9A\u9762\u8BD5\u5B98\uFF0C\u5F53\u524D\u767B\u5F55\u4EBA\u300C${me.name}\u300D\u5728\u4EBA\u5458\u5B57\u6BB5\u4E2D\u89E3\u6790\u4E0D\u5230\uFF1B\u8BF7\u7528 interviewer \u53C2\u6570\u6307\u5B9A`
|
|
3003
|
+
);
|
|
3004
|
+
}
|
|
3005
|
+
interviewer = me.name;
|
|
3006
|
+
}
|
|
3007
|
+
let aiPlan = null;
|
|
3008
|
+
let aiPlans = [];
|
|
3009
|
+
let email = String(args.email || "").trim() || candidate.email;
|
|
3010
|
+
const mobile = candidate.mobile;
|
|
3011
|
+
if (isAI) {
|
|
3012
|
+
const digitalFid = fieldIdOf("digital_id");
|
|
3013
|
+
if (!digitalFid) {
|
|
3014
|
+
throw ehrValidationError("recruit_field_missing", "\u9762\u8BD5\u8BA1\u5212\u8868\u5355\u7F3A\u5C11\u300CAI\u9762\u8BD5\u65B9\u6848\u300D\u5B57\u6BB5\uFF08digital_id\uFF09\uFF0C\u65E0\u6CD5\u5B89\u6392 AI \u9762\u8BD5");
|
|
3015
|
+
}
|
|
3016
|
+
const layoutId = await fetchLayoutIdForForm(host, formId);
|
|
3017
|
+
const plans = await listDigitalPlansForWrite(host, cache, formId, layoutId, digitalFid);
|
|
3018
|
+
aiPlans = plans.items;
|
|
3019
|
+
if (!plans.available) {
|
|
3020
|
+
throw ehrValidationError(
|
|
3021
|
+
"ai_plan_unavailable",
|
|
3022
|
+
`AI \u9762\u8BD5\u5FC5\u987B\u9009\u62E9\u300CAI\u9762\u8BD5\u65B9\u6848\u300D\uFF0C\u4F46${plans.reason || "\u6682\u65E0\u53EF\u9009\u65B9\u6848"}\uFF1B\u8BF7\u5148\u5728\u8BE5\u73AF\u5883\u7EF4\u62A4\u300C\u9762\u8BD5\u6570\u5B57\u4EBA\u914D\u7F6E\u300D`
|
|
3023
|
+
);
|
|
3024
|
+
}
|
|
3025
|
+
const wanted = typeof args.aiPlan === "string" && args.aiPlan.trim() ? args.aiPlan.trim() : AI_DEFAULT_PLAN_NAME;
|
|
3026
|
+
const picked = pickDigitalPlanForWrite(aiPlans, wanted);
|
|
3027
|
+
if (picked.plan) {
|
|
3028
|
+
aiPlan = picked.plan;
|
|
3029
|
+
} else if (picked.ambiguous.length > 1) {
|
|
3030
|
+
throw ehrValidationError(
|
|
3031
|
+
"ai_plan_ambiguous",
|
|
3032
|
+
`AI\u9762\u8BD5\u65B9\u6848\u300C${wanted}\u300D\u547D\u4E2D\u591A\u4E2A\uFF1A${picked.ambiguous.map((x) => x.name).join("\u3001")}\uFF0C\u8BF7\u7528 aiPlan \u6307\u660E\u5177\u4F53\u65B9\u6848`,
|
|
3033
|
+
{ candidates: picked.ambiguous }
|
|
3034
|
+
);
|
|
3035
|
+
} else {
|
|
3036
|
+
throw ehrValidationError(
|
|
3037
|
+
"ai_plan_not_found",
|
|
3038
|
+
`\u672A\u627E\u5230 AI\u9762\u8BD5\u65B9\u6848\u300C${wanted}\u300D\uFF0C\u8BF7\u7528 aiPlan \u4ECE\u5019\u9009\u4E2D\u6307\u5B9A\uFF08\u5019\u9009\uFF1A${aiPlans.map((x) => x.name).join("\u3001")}\uFF09`,
|
|
3039
|
+
{ candidates: aiPlans }
|
|
3040
|
+
);
|
|
3041
|
+
}
|
|
3042
|
+
if (!email) {
|
|
3043
|
+
throw ehrValidationError("email_required", "AI \u9762\u8BD5\u8981\u6C42\u586B\u5199\u5019\u9009\u4EBA\u90AE\u7BB1\uFF1A\u4EBA\u624D\u8D44\u6599\u91CC\u6CA1\u6709\u90AE\u7BB1\uFF0C\u8BF7\u7528 email \u53C2\u6570\u63D0\u4F9B");
|
|
3044
|
+
}
|
|
3045
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
|
3046
|
+
throw ehrValidationError("email_invalid", `\u5019\u9009\u4EBA\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E\uFF1A${email}`);
|
|
3047
|
+
}
|
|
3920
3048
|
}
|
|
3921
3049
|
const window = defaultInterviewWindow();
|
|
3922
3050
|
const start = typeof args.startTime === "string" && args.startTime.trim() ? args.startTime.trim() : window.start;
|
|
@@ -3934,7 +3062,10 @@ async function buildInterviewPlan(env, cache, args) {
|
|
|
3934
3062
|
{ formField: { id: fieldIdOf("interviewer") }, dataOptions: [{ optionId: interviewerId, content: interviewer }] },
|
|
3935
3063
|
{ formField: { id: fieldIdOf("position_manage_id") }, dataOptions: [{ optionId: positionId, content: candidate.positionName }] },
|
|
3936
3064
|
{ formField: { id: fieldIdOf("talent_id") }, dataOptions: [{ optionId: talentId, content: candidate.name }] },
|
|
3937
|
-
{ formField: { id: fieldIdOf("candidate_manage_id") }, dataOptions: [{ optionId: candidate.candidateManageId, content: candidate.candidateManageId }] }
|
|
3065
|
+
{ formField: { id: fieldIdOf("candidate_manage_id") }, dataOptions: [{ optionId: candidate.candidateManageId, content: candidate.candidateManageId }] },
|
|
3066
|
+
...mobile ? [{ formField: { id: fieldIdOf("mobile") }, content: mobile }] : [],
|
|
3067
|
+
...email ? [{ formField: { id: fieldIdOf("email") }, content: email }] : [],
|
|
3068
|
+
...aiPlan ? [{ formField: { id: fieldIdOf("digital_id") }, dataOptions: [{ optionId: aiPlan.id, content: aiPlan.name }] }] : []
|
|
3938
3069
|
];
|
|
3939
3070
|
return {
|
|
3940
3071
|
formId,
|
|
@@ -3943,13 +3074,20 @@ async function buildInterviewPlan(env, cache, args) {
|
|
|
3943
3074
|
candidateName: candidate.name,
|
|
3944
3075
|
positionName: candidate.positionName,
|
|
3945
3076
|
interviewTime: `${start} ~ ${end}`,
|
|
3946
|
-
interviewer
|
|
3077
|
+
interviewer,
|
|
3078
|
+
email: email || void 0,
|
|
3079
|
+
mobile: mobile || void 0,
|
|
3080
|
+
isAIInterview: isAI,
|
|
3081
|
+
aiPlan,
|
|
3082
|
+
aiPlans: isAI ? aiPlans : void 0
|
|
3947
3083
|
};
|
|
3948
3084
|
}
|
|
3949
3085
|
var interviewArrangeSchema = {
|
|
3950
3086
|
talentId: { type: "string", pattern: "^\\d+$", description: "\u4EBA\u624D ID\uFF08candidate.search \u8FD4\u56DE\u7684 talentId\uFF09" },
|
|
3951
|
-
interviewer: { type: "string", description: "\u9762\u8BD5\u5B98\u59D3\u540D\uFF08\
|
|
3087
|
+
interviewer: { type: "string", description: "\u9762\u8BD5\u5B98\u59D3\u540D\uFF08\u53EF\u9009\uFF1B\u4E0D\u586B\u9ED8\u8BA4\u5F53\u524D\u767B\u5F55\u4EBA\uFF09" },
|
|
3952
3088
|
type: { type: "string", enum: [...INTERVIEW_TYPES], description: "\u9762\u8BD5\u65B9\u5F0F\uFF0C\u9ED8\u8BA4\u73B0\u573A\u9762\u8BD5" },
|
|
3089
|
+
aiPlan: { type: "string", description: "AI \u9762\u8BD5\u65B9\u6848\uFF08\u65B9\u6848\u540D\u6216 id\uFF1Btype=AI\u9762\u8BD5 \u65F6\u751F\u6548\uFF0C\u9ED8\u8BA4\u300C\u5927\u6A21\u578B\u9762\u8BD5\u300D\uFF09" },
|
|
3090
|
+
email: { type: "string", description: "\u5019\u9009\u4EBA\u90AE\u7BB1\uFF08AI \u9762\u8BD5\u5FC5\u586B\uFF1B\u4E0D\u586B\u5219\u53D6\u4EBA\u624D\u8D44\u6599\u91CC\u7684\u90AE\u7BB1\uFF09" },
|
|
3953
3091
|
session: { type: "string", description: "\u9762\u8BD5\u8F6E\u6B21\uFF08\u5982 \u521D\u8BD5/\u590D\u8BD5\uFF09\uFF0C\u9ED8\u8BA4\u521D\u8BD5\uFF1B\u987B\u5728\u679A\u4E3E\u5185" },
|
|
3954
3092
|
positionId: { type: "string", description: "\u5E94\u8058\u804C\u4F4D ID\uFF1B\u4E0D\u586B\u65F6\u4ECE\u4EBA\u624D\u5F53\u524D\u5E94\u8058\u6279\u6B21\u7EE7\u627F" },
|
|
3955
3093
|
startTime: { type: "string", pattern: "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}$", description: "\u5F00\u59CB\u65F6\u95F4 YYYY-MM-DD HH:mm\uFF0C\u9ED8\u8BA4\u5F53\u524D\u65F6\u95F4" },
|
|
@@ -3965,7 +3103,7 @@ var interviewArrangePrepare = {
|
|
|
3965
3103
|
capability: "recruit",
|
|
3966
3104
|
risk: WRITE,
|
|
3967
3105
|
requiresConfirmation: true,
|
|
3968
|
-
inputSchema: schemaOf({ ...interviewArrangeSchema }, { required: ["talentId"
|
|
3106
|
+
inputSchema: schemaOf({ ...interviewArrangeSchema }, { required: ["talentId"] }),
|
|
3969
3107
|
handler: async (args, env) => {
|
|
3970
3108
|
const cache = await requireRecruitCache(env);
|
|
3971
3109
|
const plan = await buildInterviewPlan(env, cache, args);
|
|
@@ -3981,7 +3119,7 @@ var interviewArrangePrepare = {
|
|
|
3981
3119
|
payload,
|
|
3982
3120
|
fingerprint: fingerprint2({ dataDetails: plan.dataDetails, notify })
|
|
3983
3121
|
},
|
|
3984
|
-
|
|
3122
|
+
CONTINUATION_TTL_SECONDS * 1e3
|
|
3985
3123
|
);
|
|
3986
3124
|
return ehrSuccess("ehr.recruit.candidate.interview.arrange.prepare", {
|
|
3987
3125
|
status: "AWAITING_CONFIRMATION",
|
|
@@ -3993,11 +3131,16 @@ var interviewArrangePrepare = {
|
|
|
3993
3131
|
session: args.session || "\u521D\u8BD5",
|
|
3994
3132
|
time: plan.interviewTime,
|
|
3995
3133
|
interviewer: plan.interviewer,
|
|
3134
|
+
...plan.isAIInterview ? {
|
|
3135
|
+
aiPlan: plan.aiPlan ? `${plan.aiPlan.name}\uFF08id=${plan.aiPlan.id}\uFF09` : "(\u672A\u6307\u5B9A)",
|
|
3136
|
+
email: plan.email || "(\u7F3A\u5931)",
|
|
3137
|
+
mobile: plan.mobile || "(\u4EBA\u624D\u8D44\u6599\u65E0\u624B\u673A\u53F7)"
|
|
3138
|
+
} : {},
|
|
3996
3139
|
notify: notify ? "\u5C06\u89E6\u53D1\u300C\u65B0\u5EFA\u65E5\u7A0B\u300D\u9762\u8BD5\u901A\u77E5\u52A8\u4F5C\u6D41\uFF08\u5916\u90E8\u901A\u77E5\uFF09" : "\u9762\u8BD5\u901A\u77E5\u9ED8\u8BA4\u4E0D\u89E6\u53D1"
|
|
3997
3140
|
},
|
|
3998
3141
|
willSubmit: { formId: plan.formId, objId: plan.objId, dataDetails: plan.dataDetails },
|
|
3999
3142
|
continuation: token,
|
|
4000
|
-
expiresInSeconds:
|
|
3143
|
+
expiresInSeconds: CONTINUATION_TTL_SECONDS
|
|
4001
3144
|
});
|
|
4002
3145
|
}
|
|
4003
3146
|
};
|
|
@@ -4228,7 +3371,7 @@ var offerSendPrepare = {
|
|
|
4228
3371
|
payload: { ...args, fbObjId: plan.fbObjId, fbFormId: plan.fbFormId, dataDetails: plan.dataDetails, offerId: plan.offerId },
|
|
4229
3372
|
fingerprint: fingerprint2({ dataDetails: plan.dataDetails, offerId: plan.offerId })
|
|
4230
3373
|
},
|
|
4231
|
-
|
|
3374
|
+
CONTINUATION_TTL_SECONDS * 1e3
|
|
4232
3375
|
);
|
|
4233
3376
|
return ehrSuccess("ehr.recruit.offer.send.prepare", {
|
|
4234
3377
|
status: "AWAITING_CONFIRMATION",
|
|
@@ -4244,7 +3387,7 @@ var offerSendPrepare = {
|
|
|
4244
3387
|
},
|
|
4245
3388
|
willSubmit: { formId: plan.fbFormId, objId: plan.fbObjId, dataDetails: plan.dataDetails },
|
|
4246
3389
|
continuation: token,
|
|
4247
|
-
expiresInSeconds:
|
|
3390
|
+
expiresInSeconds: CONTINUATION_TTL_SECONDS
|
|
4248
3391
|
});
|
|
4249
3392
|
}
|
|
4250
3393
|
};
|
|
@@ -4498,7 +3641,7 @@ var entryProcessPrepare = {
|
|
|
4498
3641
|
},
|
|
4499
3642
|
fingerprint: fingerprint2({ entryId: plan.entryId, dataDetails: plan.dataDetails })
|
|
4500
3643
|
},
|
|
4501
|
-
|
|
3644
|
+
CONTINUATION_TTL_SECONDS * 1e3
|
|
4502
3645
|
);
|
|
4503
3646
|
return ehrSuccess("ehr.recruit.entry.process.prepare", {
|
|
4504
3647
|
status: "AWAITING_CONFIRMATION",
|
|
@@ -4516,7 +3659,7 @@ var entryProcessPrepare = {
|
|
|
4516
3659
|
},
|
|
4517
3660
|
willSubmit: { formId: plan.emFormId, objId: plan.emObjId, updateTimeStamp: plan.updateTimeStamp, dataDetails: plan.dataDetails },
|
|
4518
3661
|
continuation: token,
|
|
4519
|
-
expiresInSeconds:
|
|
3662
|
+
expiresInSeconds: CONTINUATION_TTL_SECONDS
|
|
4520
3663
|
});
|
|
4521
3664
|
}
|
|
4522
3665
|
};
|
|
@@ -4748,7 +3891,7 @@ var feedbackEditPrepare = {
|
|
|
4748
3891
|
comment: plan.newComment
|
|
4749
3892
|
})
|
|
4750
3893
|
},
|
|
4751
|
-
|
|
3894
|
+
CONTINUATION_TTL_SECONDS * 1e3
|
|
4752
3895
|
);
|
|
4753
3896
|
return ehrSuccess("ehr.recruit.candidate.interview.feedback.edit.prepare", {
|
|
4754
3897
|
status: "AWAITING_CONFIRMATION",
|
|
@@ -4764,7 +3907,7 @@ var feedbackEditPrepare = {
|
|
|
4764
3907
|
note: "apply \u5C06\u4FDD\u5B58\u53CD\u9988\u8868\u5355\uFF08\u5168\u5B57\u6BB5\u96C6 + \u4E50\u89C2\u9501\uFF09\u5E76\u56DE\u67E5\u6821\u9A8C"
|
|
4765
3908
|
},
|
|
4766
3909
|
continuation: token,
|
|
4767
|
-
expiresInSeconds:
|
|
3910
|
+
expiresInSeconds: CONTINUATION_TTL_SECONDS
|
|
4768
3911
|
});
|
|
4769
3912
|
}
|
|
4770
3913
|
};
|
|
@@ -4924,7 +4067,7 @@ var feedbackUrgePrepare = {
|
|
|
4924
4067
|
},
|
|
4925
4068
|
fingerprint: fingerprint2({ talentId: plan.talentId, feedbackRecordId: plan.feedbackRecordId })
|
|
4926
4069
|
},
|
|
4927
|
-
|
|
4070
|
+
CONTINUATION_TTL_SECONDS * 1e3
|
|
4928
4071
|
);
|
|
4929
4072
|
return ehrSuccess("ehr.recruit.candidate.interview.feedback.urge.prepare", {
|
|
4930
4073
|
status: "AWAITING_CONFIRMATION",
|
|
@@ -4937,7 +4080,7 @@ var feedbackUrgePrepare = {
|
|
|
4937
4080
|
note: "\u786E\u8BA4\u540E\u5C06\u5411\u9762\u8BD5\u5B98\u53D1\u9001\u300C\u8BF7\u586B\u5199\u8BC4\u4EF7\u300D\u7CFB\u7EDF\u901A\u77E5\uFF08\u4F1A\u6253\u6270\u771F\u4EBA\uFF0C\u8BF7\u786E\u4FDD\u5DF2\u7ECF\u7528\u6237\u540C\u610F\uFF09"
|
|
4938
4081
|
},
|
|
4939
4082
|
continuation: token,
|
|
4940
|
-
expiresInSeconds:
|
|
4083
|
+
expiresInSeconds: CONTINUATION_TTL_SECONDS
|
|
4941
4084
|
});
|
|
4942
4085
|
}
|
|
4943
4086
|
};
|
|
@@ -5132,6 +4275,7 @@ var OPTION_DEFAULTS = { salary_type: "\u6708\u85AA", recruit_type: "\u793E\u4F1A
|
|
|
5132
4275
|
var SET_FIELDS = [
|
|
5133
4276
|
{ arg: "education", key: "education", kind: "dict", label: "\u5B66\u5386\u8981\u6C42\uFF08\u6309\u6570\u636E\u5B57\u5178\u540D\u79F0\uFF09" },
|
|
5134
4277
|
{ arg: "workYears", key: "work_years", kind: "dict", label: "\u5DE5\u4F5C\u5E74\u9650\uFF08\u6309\u6570\u636E\u5B57\u5178\u540D\u79F0\uFF09" },
|
|
4278
|
+
{ arg: "workLocation", key: "work_location", kind: "assoc", label: "\u5DE5\u4F5C\u5730\u70B9\uFF08\u529E\u516C\u5730\u70B9\u540D\u79F0/\u8BE6\u7EC6\u5730\u5740\uFF0C\u5982\u300C\u4E0A\u6D77\u300D\u6216\u5B8C\u6574\u5730\u5740\uFF09" },
|
|
5135
4279
|
{ arg: "jobCategory", key: "job_category", kind: "dict", label: "\u804C\u4F4D\u7C7B\u522B\uFF08\u6309\u6570\u636E\u5B57\u5178\u540D\u79F0\uFF09" },
|
|
5136
4280
|
{ arg: "positionNature", key: "position_nature", kind: "dict", label: "\u804C\u4F4D\u5C5E\u6027\uFF08\u6309\u6570\u636E\u5B57\u5178\u540D\u79F0\uFF09" },
|
|
5137
4281
|
{ arg: "salaryType", key: "salary_type", kind: "option", label: "\u85AA\u916C\u7C7B\u578B\uFF08\u6708\u85AA/\u5E74\u85AA\u7B49\uFF09" },
|
|
@@ -5181,6 +4325,85 @@ async function fetchReferenceDetails(env, cache, objId, formId) {
|
|
|
5181
4325
|
return [];
|
|
5182
4326
|
}
|
|
5183
4327
|
}
|
|
4328
|
+
var WORK_PLACE_NAMES = ["\u529E\u516C\u5730\u70B9", "\u5DE5\u4F5C\u5730\u70B9"];
|
|
4329
|
+
async function findWorkPlaceMenu(env, cache) {
|
|
4330
|
+
const ok = (m) => !!(m && m.listId);
|
|
4331
|
+
const pick = (list) => {
|
|
4332
|
+
const hit = list.find((m) => ok(m) && WORK_PLACE_NAMES.some((n) => String(m.menuName || "").includes(n)));
|
|
4333
|
+
return hit ? hit : null;
|
|
4334
|
+
};
|
|
4335
|
+
const hit1 = pick(cache.lists?.all_search || []);
|
|
4336
|
+
if (hit1) return hit1;
|
|
4337
|
+
const hit2 = pick(cache.menus || []);
|
|
4338
|
+
if (hit2) return hit2;
|
|
4339
|
+
try {
|
|
4340
|
+
const r = await env.host.request({
|
|
4341
|
+
path: "/api/cusapp/app/allMenus",
|
|
4342
|
+
query: { isFront: 1, appId: String(cache.appId || ""), terminalType: "PC" }
|
|
4343
|
+
});
|
|
4344
|
+
const flat = [];
|
|
4345
|
+
(function walk(nodes) {
|
|
4346
|
+
for (const n of nodes || []) {
|
|
4347
|
+
if (n && typeof n === "object") {
|
|
4348
|
+
flat.push(n);
|
|
4349
|
+
walk(n.children || n.childs);
|
|
4350
|
+
}
|
|
4351
|
+
}
|
|
4352
|
+
})(r?.data?.cusAppMenus || r?.data);
|
|
4353
|
+
return pick(flat);
|
|
4354
|
+
} catch {
|
|
4355
|
+
return null;
|
|
4356
|
+
}
|
|
4357
|
+
}
|
|
4358
|
+
async function resolveWorkLocation(env, cache, value) {
|
|
4359
|
+
const v = String(value).trim();
|
|
4360
|
+
if (!v) return null;
|
|
4361
|
+
const menu = await findWorkPlaceMenu(env, cache);
|
|
4362
|
+
if (!menu?.listId) return null;
|
|
4363
|
+
let pObj = "";
|
|
4364
|
+
try {
|
|
4365
|
+
const t = await env.host.request({
|
|
4366
|
+
path: "/api/ebuilder/form/obj/getObjsByTag",
|
|
4367
|
+
query: { appId: String(cache.appId || ""), tag: "uf_rcrt_work_place" }
|
|
4368
|
+
});
|
|
4369
|
+
const d = t?.data;
|
|
4370
|
+
if (Array.isArray(d) && d[0]) pObj = String(d[0].id || "");
|
|
4371
|
+
} catch {
|
|
4372
|
+
}
|
|
4373
|
+
if (!pObj) pObj = String(menu.objId || "");
|
|
4374
|
+
if (!pObj) return null;
|
|
4375
|
+
const body = buildListBody({
|
|
4376
|
+
listId: menu.listId,
|
|
4377
|
+
cusMenuId: menu.cusMenuId,
|
|
4378
|
+
menuName: menu.menuName || "\u529E\u516C\u5730\u70B9",
|
|
4379
|
+
title: menu.menuName || "\u529E\u516C\u5730\u70B9",
|
|
4380
|
+
pageSize: 200
|
|
4381
|
+
});
|
|
4382
|
+
const r = await env.host.request({
|
|
4383
|
+
path: `/api/ebuilder/form/list/getListDatas?passid=${pObj}&cid=${pObj}`,
|
|
4384
|
+
body,
|
|
4385
|
+
headers: { ebBusinessId: menu.listId }
|
|
4386
|
+
});
|
|
4387
|
+
const rows = r?.data?.data || r?.data?.displayData || [];
|
|
4388
|
+
const hit = rows.find((x) => {
|
|
4389
|
+
const name = String(x?.name || "");
|
|
4390
|
+
const detail = String(x?.detail_location || "");
|
|
4391
|
+
const area = String(x?.area_text || "");
|
|
4392
|
+
return name.includes(v) || detail.includes(v) || area.includes(v) || !!detail && v.includes(detail);
|
|
4393
|
+
});
|
|
4394
|
+
return hit ? { id: String(hit.form_data_id || hit.id), name: String(hit.detail_location || hit.name || v) } : null;
|
|
4395
|
+
}
|
|
4396
|
+
function detailDisplayValue(detail) {
|
|
4397
|
+
if (!detail) return "";
|
|
4398
|
+
const d = detail;
|
|
4399
|
+
if (d.content !== void 0 && d.content !== null) return String(d.content);
|
|
4400
|
+
if (Array.isArray(d.dataOptions) && d.dataOptions[0]) {
|
|
4401
|
+
const o = d.dataOptions[0];
|
|
4402
|
+
return String(o.content ?? o.optionId ?? "");
|
|
4403
|
+
}
|
|
4404
|
+
if (d.dataText?.content !== void 0) return String(d.dataText.content).replace(/<[^>]+>/g, "").slice(0, 60);
|
|
4405
|
+
return "";
|
|
4406
|
+
}
|
|
5184
4407
|
async function buildPositionPlan(env, cache, args) {
|
|
5185
4408
|
const form = cache.forms.position_manage;
|
|
5186
4409
|
const objId = form?.objId;
|
|
@@ -5246,6 +4469,14 @@ async function buildPositionPlan(env, cache, args) {
|
|
|
5246
4469
|
}
|
|
5247
4470
|
put({ formField: { id: fieldId }, dataOptions: [{ optionId: String(optionId), content: value }] });
|
|
5248
4471
|
applied.push(`${field.key}=${value}`);
|
|
4472
|
+
} else if (field.kind === "assoc") {
|
|
4473
|
+
const loc = await resolveWorkLocation(env, cache, value);
|
|
4474
|
+
if (!loc) {
|
|
4475
|
+
skipped.push(`${field.key}=${value}\uFF08\u672A\u5339\u914D\u5230\u300C\u529E\u516C\u5730\u70B9\u300D\u8BB0\u5F55\uFF0C\u5DF2\u8DF3\u8FC7\uFF09`);
|
|
4476
|
+
continue;
|
|
4477
|
+
}
|
|
4478
|
+
put({ formField: { id: fieldId }, dataOptions: [{ optionId: loc.id, content: loc.name }] });
|
|
4479
|
+
applied.push(`${field.key}=${value}`);
|
|
5249
4480
|
} else if (field.kind === "dict") {
|
|
5250
4481
|
const ids = cache.dict.by_name[value] || [];
|
|
5251
4482
|
const unique = [...new Set(ids.map(String))];
|
|
@@ -5304,6 +4535,15 @@ async function buildPositionPlan(env, cache, args) {
|
|
|
5304
4535
|
}
|
|
5305
4536
|
const inverse = {};
|
|
5306
4537
|
for (const [dataKey, fieldId] of Object.entries(fields)) inverse[String(fieldId)] = dataKey;
|
|
4538
|
+
const inheritedSalaryWarnings = [];
|
|
4539
|
+
for (const key of ["salary_min", "salary_max"]) {
|
|
4540
|
+
if (!inherited.includes(key)) continue;
|
|
4541
|
+
const raw = detailDisplayValue(refMap.get(String(fid(key))));
|
|
4542
|
+
const num = Number(String(raw).replace(/[^\d.]/g, ""));
|
|
4543
|
+
if (raw && Number.isFinite(num) && num > 0 && num < 1e3) {
|
|
4544
|
+
inheritedSalaryWarnings.push(`${key} \u7EE7\u627F\u503C\u300C${raw}\u300D\u660E\u663E\u504F\u4F4E\uFF08\u7591\u5386\u53F2\u810F\u6570\u636E\uFF09\uFF0C\u8BF7\u4EBA\u5DE5\u6838\u5BF9\u540E\u518D\u63D0\u4EA4`);
|
|
4545
|
+
}
|
|
4546
|
+
}
|
|
5307
4547
|
return {
|
|
5308
4548
|
objId,
|
|
5309
4549
|
formId,
|
|
@@ -5317,6 +4557,10 @@ async function buildPositionPlan(env, cache, args) {
|
|
|
5317
4557
|
explicitApplied: applied,
|
|
5318
4558
|
explicitSkipped: skipped,
|
|
5319
4559
|
inheritedFromExistingPosition: inherited,
|
|
4560
|
+
// 带值的继承清单:Agent 必须在确认摘要里逐项点名(尤其 work_location),
|
|
4561
|
+
// 不得因为它是默认值就略过——历史上这里曾静默带出过重复地点等脏数据。
|
|
4562
|
+
inheritedFromRef: inherited.length ? inherited.map((k) => ({ field: k, value: detailDisplayValue(refMap.get(String(fid(k)))) })) : void 0,
|
|
4563
|
+
inheritedSalaryWarnings: inheritedSalaryWarnings.length ? inheritedSalaryWarnings : void 0,
|
|
5320
4564
|
noReferenceValue: missingRef,
|
|
5321
4565
|
principalDefault: session.userId ? "\u5F53\u524D\u767B\u5F55\u7528\u6237" : "\u672A\u89E3\u6790\u5230\u5F53\u524D\u7528\u6237"
|
|
5322
4566
|
}
|
|
@@ -5355,14 +4599,14 @@ var positionCreatePrepare = {
|
|
|
5355
4599
|
payload: { objId: plan.objId, formId: plan.formId, positionName: String(args.positionName).trim(), dataDetails: plan.dataDetails },
|
|
5356
4600
|
fingerprint: fingerprint3({ objId: plan.objId, dataDetails: plan.dataDetails })
|
|
5357
4601
|
},
|
|
5358
|
-
|
|
4602
|
+
CONTINUATION_TTL_MS
|
|
5359
4603
|
);
|
|
5360
4604
|
return ehrSuccess("ehr.recruit.position.create.prepare", {
|
|
5361
4605
|
status: "AWAITING_CONFIRMATION",
|
|
5362
4606
|
preview: { action: "\u751F\u6210\u804C\u4F4DJD\u5E76\u5EFA\u804C\u4F4D\uFF08saveFormData \u2192 addPosition\uFF09", ...plan.summary },
|
|
5363
4607
|
willSubmit: { objId: plan.objId, formId: plan.formId, dataDetails: plan.dataDetails },
|
|
5364
4608
|
continuation,
|
|
5365
|
-
expiresInSeconds:
|
|
4609
|
+
expiresInSeconds: CONTINUATION_TTL_SECONDS
|
|
5366
4610
|
});
|
|
5367
4611
|
}
|
|
5368
4612
|
};
|
|
@@ -5531,6 +4775,93 @@ function joinRange(start, end) {
|
|
|
5531
4775
|
if (!s && !e) return void 0;
|
|
5532
4776
|
return `${s},${e}`;
|
|
5533
4777
|
}
|
|
4778
|
+
var DATE_ONLY_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
4779
|
+
var ONGOING_RE = /至今|现在|今|now|present/i;
|
|
4780
|
+
var RE_RANGE_FULL = /^\s*(\d{4}[.\-/年]\d{1,2}[.\-/月]\d{1,2}\s*日?)\s*[-–—~至,,]\s*(\d{4}[.\-/年]\d{1,2}[.\-/月]\d{1,2}\s*日?|至今|现在|今)\s*$/;
|
|
4781
|
+
var RE_RANGE_YM = /^\s*(\d{4}[.\-/年]\d{1,2})\s*[-–—~至,,]\s*(\d{4}[.\-/年]\d{1,2}|至今|现在|今)\s*$/;
|
|
4782
|
+
function normDatePart(raw, isEnd) {
|
|
4783
|
+
const s = String(raw ?? "").trim();
|
|
4784
|
+
if (!s) return "";
|
|
4785
|
+
if (ONGOING_RE.test(s)) return "";
|
|
4786
|
+
if (DATE_ONLY_RE.test(s)) return s;
|
|
4787
|
+
const m = s.match(/^(\d{4})\s*[.\-/年]?\s*(\d{1,2})?\s*[.\-/月]?\s*(\d{1,2})?\s*日?$/);
|
|
4788
|
+
if (!m) return "";
|
|
4789
|
+
const y = Number(m[1]);
|
|
4790
|
+
const mo = m[2] ? Number(m[2]) : 1;
|
|
4791
|
+
if (!y || mo < 1 || mo > 12) return "";
|
|
4792
|
+
const lastDay = new Date(y, mo, 0).getDate();
|
|
4793
|
+
let d;
|
|
4794
|
+
if (m[3]) {
|
|
4795
|
+
d = Number(m[3]);
|
|
4796
|
+
if (d < 1 || d > lastDay) return "";
|
|
4797
|
+
} else {
|
|
4798
|
+
d = isEnd ? lastDay : 1;
|
|
4799
|
+
}
|
|
4800
|
+
return `${y}-${String(mo).padStart(2, "0")}-${String(d).padStart(2, "0")}`;
|
|
4801
|
+
}
|
|
4802
|
+
function normDateRange(raw) {
|
|
4803
|
+
const s = Array.isArray(raw) ? raw.map((x) => String(x ?? "").trim()).filter(Boolean).join(",") : String(raw ?? "").trim();
|
|
4804
|
+
if (!s) return "";
|
|
4805
|
+
const m = s.match(RE_RANGE_FULL) || s.match(RE_RANGE_YM);
|
|
4806
|
+
if (m) {
|
|
4807
|
+
const a = normDatePart(m[1], false);
|
|
4808
|
+
if (!a) return "";
|
|
4809
|
+
const b = normDatePart(m[2], true);
|
|
4810
|
+
return b ? `${a},${b}` : a;
|
|
4811
|
+
}
|
|
4812
|
+
return normDatePart(s, false);
|
|
4813
|
+
}
|
|
4814
|
+
function normalizeImportDates(input, warnings) {
|
|
4815
|
+
if (!input || typeof input !== "object") return;
|
|
4816
|
+
const one = (label, val, isEnd = false) => {
|
|
4817
|
+
const before = String(val ?? "").trim();
|
|
4818
|
+
if (!before) return "";
|
|
4819
|
+
if (ONGOING_RE.test(before)) return "";
|
|
4820
|
+
const after = normDatePart(before, isEnd);
|
|
4821
|
+
if (!after) {
|
|
4822
|
+
warnings.push(`\u65E5\u671F\u65E0\u6CD5\u8BC6\u522B\uFF0C\u5DF2\u8DF3\u8FC7\u8BE5\u5B57\u6BB5\uFF08\u907F\u514D\u63A5\u53E3\u6574\u6279\u6821\u9A8C\u5931\u8D25\uFF09\uFF1A${label} = \u300C${before}\u300D`);
|
|
4823
|
+
return "";
|
|
4824
|
+
}
|
|
4825
|
+
if (after !== before) warnings.push(`\u65E5\u671F\u5DF2\u89C4\u8303\u5316\uFF1A${label} \u300C${before}\u300D\u2192\u300C${after}\u300D`);
|
|
4826
|
+
return after;
|
|
4827
|
+
};
|
|
4828
|
+
for (const k of ["joinworkdate", "graduate_date", "birthday"]) {
|
|
4829
|
+
if (input[k] === void 0 || input[k] === null) continue;
|
|
4830
|
+
input[k] = one(k, input[k], false);
|
|
4831
|
+
}
|
|
4832
|
+
if (Array.isArray(input.academicInformations)) {
|
|
4833
|
+
input.academicInformations.forEach((r, i) => {
|
|
4834
|
+
if (!r || typeof r !== "object" || r.study_date === void 0) return;
|
|
4835
|
+
const before = String(r.study_date ?? "").trim();
|
|
4836
|
+
if (!before) return;
|
|
4837
|
+
const after = normDateRange(before);
|
|
4838
|
+
if (!after) {
|
|
4839
|
+
warnings.push(`\u65E5\u671F\u533A\u95F4\u65E0\u6CD5\u8BC6\u522B\uFF0C\u5DF2\u8DF3\u8FC7\uFF1AacademicInformations[${i}].study_date = \u300C${before}\u300D`);
|
|
4840
|
+
r.study_date = "";
|
|
4841
|
+
} else {
|
|
4842
|
+
if (after !== before) warnings.push(`\u65E5\u671F\u5DF2\u89C4\u8303\u5316\uFF1AacademicInformations[${i}].study_date \u300C${before}\u300D\u2192\u300C${after}\u300D`);
|
|
4843
|
+
r.study_date = after;
|
|
4844
|
+
}
|
|
4845
|
+
});
|
|
4846
|
+
}
|
|
4847
|
+
for (const key of ["jobInformations", "workExperiences", "projectExperiences"]) {
|
|
4848
|
+
const arr = input[key];
|
|
4849
|
+
if (!Array.isArray(arr)) continue;
|
|
4850
|
+
arr.forEach((r, i) => {
|
|
4851
|
+
if (!r || typeof r !== "object") return;
|
|
4852
|
+
if (r.start_date !== void 0 && r.start_date !== null) r.start_date = one(`${key}[${i}].start_date`, r.start_date, false);
|
|
4853
|
+
if (r.end_date !== void 0 && r.end_date !== null) r.end_date = one(`${key}[${i}].end_date`, r.end_date, true);
|
|
4854
|
+
});
|
|
4855
|
+
}
|
|
4856
|
+
for (const [key, field] of [["internshipExperiences", "entry_time"], ["awardExperiences", "award_date"]]) {
|
|
4857
|
+
const arr = input[key];
|
|
4858
|
+
if (!Array.isArray(arr)) continue;
|
|
4859
|
+
arr.forEach((r, i) => {
|
|
4860
|
+
if (!r || typeof r !== "object") return;
|
|
4861
|
+
if (r[field] !== void 0 && r[field] !== null) r[field] = one(`${key}[${i}].${field}`, r[field], false);
|
|
4862
|
+
});
|
|
4863
|
+
}
|
|
4864
|
+
}
|
|
5534
4865
|
async function resolveSubTableMeta(env, formId) {
|
|
5535
4866
|
let data = null;
|
|
5536
4867
|
try {
|
|
@@ -5747,42 +5078,106 @@ async function uploadResumeFile(env, filePath, fieldId, formId) {
|
|
|
5747
5078
|
}
|
|
5748
5079
|
return { fileid: String(fileid), name, size };
|
|
5749
5080
|
}
|
|
5750
|
-
async function
|
|
5751
|
-
|
|
5752
|
-
const
|
|
5081
|
+
async function queryTagByName(env, name) {
|
|
5082
|
+
const pageSize = 100;
|
|
5083
|
+
const bodyOf = (type) => ({ type, name, order: 8, pageSize, pageNo: 1, search: 1, tagGroup: 0, tagModules: ["ebuilderform"] });
|
|
5084
|
+
const rs = await Promise.all(
|
|
5085
|
+
[0, 1].map(
|
|
5086
|
+
(type) => env.host.request({
|
|
5087
|
+
path: "/api/my/tag/query",
|
|
5088
|
+
method: "POST",
|
|
5089
|
+
body: bodyOf(type),
|
|
5090
|
+
operation: "ehr.recruit.candidate.import.apply"
|
|
5091
|
+
}).catch(() => null)
|
|
5092
|
+
)
|
|
5093
|
+
);
|
|
5094
|
+
const items = [];
|
|
5095
|
+
let filtered = true;
|
|
5096
|
+
for (const r of rs) {
|
|
5097
|
+
const d = r?.data || {};
|
|
5098
|
+
const list = Array.isArray(d.data) ? d.data : [];
|
|
5099
|
+
const total = Number(d.total || 0);
|
|
5100
|
+
if (list.length >= pageSize && total >= pageSize) filtered = false;
|
|
5101
|
+
items.push(...list);
|
|
5102
|
+
}
|
|
5103
|
+
return { items, filtered };
|
|
5104
|
+
}
|
|
5105
|
+
async function fetchTagsOfType(env, type) {
|
|
5106
|
+
const pageSize = 100;
|
|
5107
|
+
const bodyOf = (pageNo) => ({ type, name: "", order: 8, pageSize, pageNo, search: 1, tagGroup: 0, tagModules: ["ebuilderform"] });
|
|
5108
|
+
const requestPage = (pageNo) => env.host.request({
|
|
5753
5109
|
path: "/api/my/tag/query",
|
|
5754
5110
|
method: "POST",
|
|
5755
|
-
body:
|
|
5111
|
+
body: bodyOf(pageNo),
|
|
5756
5112
|
operation: "ehr.recruit.candidate.import.apply"
|
|
5757
|
-
});
|
|
5758
|
-
const
|
|
5113
|
+
}).catch(() => null);
|
|
5114
|
+
const first = await requestPage(1);
|
|
5115
|
+
const d = first?.data || {};
|
|
5116
|
+
const rows = Array.isArray(d.data) ? [...d.data] : [];
|
|
5117
|
+
const total = Number(d.total || 0);
|
|
5118
|
+
const pages = Math.min(40, Math.max(1, Math.ceil(total / pageSize)));
|
|
5119
|
+
if (pages > 1 && rows.length) {
|
|
5120
|
+
const rest = Array.from({ length: pages - 1 }, (_, i) => i + 2);
|
|
5121
|
+
for (let i = 0; i < rest.length; i += 5) {
|
|
5122
|
+
const batch = rest.slice(i, i + 5);
|
|
5123
|
+
const rs = await Promise.all(batch.map((p) => requestPage(p)));
|
|
5124
|
+
for (const r of rs) {
|
|
5125
|
+
const list = r?.data?.data;
|
|
5126
|
+
if (Array.isArray(list)) rows.push(...list);
|
|
5127
|
+
}
|
|
5128
|
+
}
|
|
5129
|
+
}
|
|
5130
|
+
return rows;
|
|
5131
|
+
}
|
|
5132
|
+
async function resolveTagIds(env, tagNames) {
|
|
5133
|
+
const norm = (s) => String(s == null ? "" : s).trim().toLowerCase();
|
|
5134
|
+
const uniqNames = [...new Set(tagNames.map((n) => String(n)).filter(Boolean))];
|
|
5759
5135
|
const byName = /* @__PURE__ */ new Map();
|
|
5760
|
-
|
|
5761
|
-
const name = String(row
|
|
5762
|
-
const id = row
|
|
5763
|
-
if (name
|
|
5136
|
+
const absorb = (row) => {
|
|
5137
|
+
const name = String(row?.name ?? row?.tagName ?? "").trim();
|
|
5138
|
+
const id = row?.tagId ?? row?.id;
|
|
5139
|
+
if (!name || id === void 0) return;
|
|
5140
|
+
const key = norm(name);
|
|
5141
|
+
const prev = byName.get(key);
|
|
5142
|
+
if (!prev) byName.set(key, { id: String(id), name });
|
|
5143
|
+
else if ((row?.type ?? 0) === 0) byName.set(key, { id: String(id), name });
|
|
5144
|
+
};
|
|
5145
|
+
const probes = await Promise.all(uniqNames.map((n) => queryTagByName(env, n)));
|
|
5146
|
+
const nameQueryUsable = probes.every((p) => p.filtered);
|
|
5147
|
+
if (nameQueryUsable) {
|
|
5148
|
+
for (const p of probes) for (const item of p.items) absorb(item);
|
|
5149
|
+
} else {
|
|
5150
|
+
for (const type of [0, 1]) {
|
|
5151
|
+
const rows = await fetchTagsOfType(env, type).catch(() => []);
|
|
5152
|
+
for (const item of rows) absorb(item);
|
|
5153
|
+
}
|
|
5764
5154
|
}
|
|
5765
|
-
const
|
|
5766
|
-
const
|
|
5155
|
+
const resolved = [];
|
|
5156
|
+
const found = [];
|
|
5767
5157
|
const skipped = [];
|
|
5768
5158
|
for (const name of tagNames) {
|
|
5769
|
-
const hit = byName.get(name);
|
|
5159
|
+
const hit = byName.get(norm(name));
|
|
5770
5160
|
if (!hit) {
|
|
5771
5161
|
skipped.push(name);
|
|
5772
5162
|
continue;
|
|
5773
5163
|
}
|
|
5774
|
-
|
|
5775
|
-
|
|
5164
|
+
resolved.push({ id: hit.id, name: hit.name, type: 0 });
|
|
5165
|
+
found.push(name);
|
|
5776
5166
|
}
|
|
5777
|
-
|
|
5167
|
+
return { resolved, found, skipped };
|
|
5168
|
+
}
|
|
5169
|
+
async function applyPlatformTags(env, talentId, tagNames) {
|
|
5170
|
+
if (!tagNames.length) return { applied: [], skipped: [] };
|
|
5171
|
+
const r = await resolveTagIds(env, tagNames);
|
|
5172
|
+
if (r.resolved.length) {
|
|
5778
5173
|
await env.host.request({
|
|
5779
5174
|
path: "/api/my/tag/common/batchAddEntityTag",
|
|
5780
5175
|
method: "POST",
|
|
5781
|
-
body: { tags, batchDatas: [{ entityId: talentId, module: "ebuilderform" }] },
|
|
5176
|
+
body: { tags: r.resolved, batchDatas: [{ entityId: talentId, module: "ebuilderform" }] },
|
|
5782
5177
|
operation: "ehr.recruit.candidate.import.apply"
|
|
5783
5178
|
});
|
|
5784
5179
|
}
|
|
5785
|
-
return { applied, skipped };
|
|
5180
|
+
return { applied: r.found, skipped: r.skipped };
|
|
5786
5181
|
}
|
|
5787
5182
|
async function requireCache2(env) {
|
|
5788
5183
|
if (!env.recruitContext) throw ehrValidationError("recruit_context_unavailable", "\u62DB\u8058\u4E0A\u4E0B\u6587\u52A0\u8F7D\u5668\u672A\u521D\u59CB\u5316");
|
|
@@ -5794,6 +5189,7 @@ function str(value) {
|
|
|
5794
5189
|
}
|
|
5795
5190
|
async function buildImportPlan(env, cache, args) {
|
|
5796
5191
|
const warnings = [];
|
|
5192
|
+
normalizeImportDates(args, warnings);
|
|
5797
5193
|
const talent = cache.forms.talent_pool;
|
|
5798
5194
|
const objId = talent?.objId;
|
|
5799
5195
|
const formId = talent?.formId || objId;
|
|
@@ -5972,7 +5368,11 @@ var candidateImportPrepare = {
|
|
|
5972
5368
|
handler: async (args, env) => {
|
|
5973
5369
|
const cache = await requireCache2(env);
|
|
5974
5370
|
const plan = await buildImportPlan(env, cache, args);
|
|
5975
|
-
const
|
|
5371
|
+
const tagNames = Array.isArray(args.tags) ? args.tags.map(String).filter(Boolean) : [];
|
|
5372
|
+
const [dup, tagCheck] = await Promise.all([
|
|
5373
|
+
checkDuplicateByMobile(env, cache, plan.mobile),
|
|
5374
|
+
tagNames.length ? resolveTagIds(env, tagNames).then((rt) => ({ requested: tagNames, found: rt.found, missing: rt.skipped })).catch((error) => ({ requested: tagNames, missing: [], error: error?.message || "\u6807\u7B7E\u9884\u68C0\u5931\u8D25" })) : Promise.resolve(null)
|
|
5375
|
+
]);
|
|
5976
5376
|
if (dup.length > 1) {
|
|
5977
5377
|
throw ehrValidationError("duplicate_ambiguous", `\u624B\u673A\u53F7 ${plan.mobile} \u5B58\u5728\u591A\u6761\u5019\u9009\uFF08\u6570\u636E\u5F02\u5E38\uFF09\uFF0C\u8BF7\u4EBA\u5DE5\u6838\u5BF9\u540E\u518D\u51B3\u5B9A\uFF0C\u4E0D\u81EA\u52A8\u65B0\u5EFA`);
|
|
5978
5378
|
}
|
|
@@ -5997,7 +5397,7 @@ var candidateImportPrepare = {
|
|
|
5997
5397
|
telephone: plan.mobile
|
|
5998
5398
|
}
|
|
5999
5399
|
},
|
|
6000
|
-
|
|
5400
|
+
CONTINUATION_TTL_MS
|
|
6001
5401
|
);
|
|
6002
5402
|
return ehrSuccess("ehr.recruit.candidate.import.prepare", {
|
|
6003
5403
|
status: "AWAITING_CONFIRMATION",
|
|
@@ -6012,8 +5412,9 @@ var candidateImportPrepare = {
|
|
|
6012
5412
|
details: plan.details,
|
|
6013
5413
|
tags: Array.isArray(args.tags) ? args.tags : []
|
|
6014
5414
|
},
|
|
5415
|
+
...tagCheck ? { tagCheck } : {},
|
|
6015
5416
|
continuation,
|
|
6016
|
-
expiresInSeconds:
|
|
5417
|
+
expiresInSeconds: CONTINUATION_TTL_SECONDS
|
|
6017
5418
|
});
|
|
6018
5419
|
}
|
|
6019
5420
|
};
|
|
@@ -6077,37 +5478,28 @@ var candidateImportApply = {
|
|
|
6077
5478
|
{ candidateName: payload.candidateName, telephone: payload.telephone }
|
|
6078
5479
|
);
|
|
6079
5480
|
}
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
} catch {
|
|
6103
|
-
labelMatch = "FAILED\uFF08\u4E0D\u5F71\u54CD\u5EFA\u6863\uFF0C\u53EF\u7A0D\u540E\u5728\u4EBA\u624D\u5361\u7247\u624B\u52A8\u89E6\u53D1\uFF09";
|
|
6104
|
-
}
|
|
6105
|
-
let tagResult = { applied: [], skipped: [] };
|
|
6106
|
-
try {
|
|
6107
|
-
tagResult = await applyPlatformTags(env, talentId, Array.isArray(payload.tags) ? payload.tags.map(String) : []);
|
|
6108
|
-
} catch (error) {
|
|
6109
|
-
tagResult = { applied: [], skipped: Array.isArray(payload.tags) ? payload.tags.map(String) : [] };
|
|
6110
|
-
}
|
|
5481
|
+
const batchTask = env.host.request({
|
|
5482
|
+
path: `/api/recruit/candidate/initTalentBatch?formDataId=${encodeURIComponent(talentId)}`,
|
|
5483
|
+
method: "POST",
|
|
5484
|
+
operation: "ehr.recruit.candidate.import.apply"
|
|
5485
|
+
}).then(() => ({ ok: true, note: void 0 })).catch((error) => ({
|
|
5486
|
+
ok: false,
|
|
5487
|
+
note: `\u4EBA\u624D\u5DF2\u5EFA\u6863\uFF0C\u4F46\u521D\u59CB\u5316\u4EBA\u624D\u6279\u6B21\u5931\u8D25\uFF1A${error?.message || "\u672A\u77E5\u9519\u8BEF"}\uFF08\u53EF\u5728\u4EBA\u624D\u5361\u7247\u624B\u52A8\u5904\u7406\uFF09`
|
|
5488
|
+
}));
|
|
5489
|
+
const labelTask = env.host.request({
|
|
5490
|
+
path: `/api/recruit/label/matchTalentLabel?talentId=${encodeURIComponent(talentId)}`,
|
|
5491
|
+
method: "POST",
|
|
5492
|
+
body: {},
|
|
5493
|
+
operation: "ehr.recruit.candidate.import.apply"
|
|
5494
|
+
}).then((r) => r?.data === void 0 ? "TRIGGERED" : String(r.data)).catch(() => "FAILED\uFF08\u4E0D\u5F71\u54CD\u5EFA\u6863\uFF0C\u53EF\u7A0D\u540E\u5728\u4EBA\u624D\u5361\u7247\u624B\u52A8\u89E6\u53D1\uFF09");
|
|
5495
|
+
const tagTask = applyPlatformTags(
|
|
5496
|
+
env,
|
|
5497
|
+
talentId,
|
|
5498
|
+
Array.isArray(payload.tags) ? payload.tags.map(String) : []
|
|
5499
|
+
).catch(() => ({ applied: [], skipped: Array.isArray(payload.tags) ? payload.tags.map(String) : [] }));
|
|
5500
|
+
const [batchOutcome, labelMatch, tagResult] = await Promise.all([batchTask, labelTask, tagTask]);
|
|
5501
|
+
const batchOk = batchOutcome.ok;
|
|
5502
|
+
const batchNote = batchOutcome.note;
|
|
6111
5503
|
const baseUrl = session.baseUrl.replace(/\/+$/, "");
|
|
6112
5504
|
const extra = String(cache.selfUse) === "1" ? "&recruitType=useSelf" : "";
|
|
6113
5505
|
const talentCardUrl = cache.ebdDetailPageId ? `${baseUrl}/sp/ebdpage/view/${cache.ebdDetailPageId}?talentId=${talentId}${extra}` : null;
|
|
@@ -6115,13 +5507,60 @@ var candidateImportApply = {
|
|
|
6115
5507
|
const talentListLocateUrl = talentListId ? `${baseUrl}/sp/ebdfpage/list/${talentListId}?talentId=${talentId}${extra}` : null;
|
|
6116
5508
|
const warnings = [...payload.warnings || []];
|
|
6117
5509
|
if (batchNote) warnings.push(batchNote);
|
|
5510
|
+
let detailsState = "complete";
|
|
5511
|
+
const expectedDetailRows = Object.values(payload.subStats || {}).reduce(
|
|
5512
|
+
(sum, n) => sum + Number(n || 0),
|
|
5513
|
+
0
|
|
5514
|
+
);
|
|
5515
|
+
if (expectedDetailRows > 0) {
|
|
5516
|
+
try {
|
|
5517
|
+
const snapshot = await env.host.request({
|
|
5518
|
+
path: "/api/ebuilder/form/form/core/getFormDataAndLayout",
|
|
5519
|
+
method: "POST",
|
|
5520
|
+
body: {
|
|
5521
|
+
terminalType: "PC",
|
|
5522
|
+
dataId: talentId,
|
|
5523
|
+
formId,
|
|
5524
|
+
module: "ebuilderform",
|
|
5525
|
+
newLayout: true,
|
|
5526
|
+
dataCrossLayout: false,
|
|
5527
|
+
permissionId: "",
|
|
5528
|
+
allReadOnly: true,
|
|
5529
|
+
initialDatas: [],
|
|
5530
|
+
dynamicData: false,
|
|
5531
|
+
cost: false,
|
|
5532
|
+
customParam: { objId, dataId: talentId }
|
|
5533
|
+
},
|
|
5534
|
+
operation: "ehr.recruit.candidate.import.apply"
|
|
5535
|
+
});
|
|
5536
|
+
const detailData = snapshot?.data?.formData?.dataDetails || [];
|
|
5537
|
+
const seenRows = {};
|
|
5538
|
+
for (const d of detailData) {
|
|
5539
|
+
if (!d?.subFormId) continue;
|
|
5540
|
+
const key = String(d.subFormId);
|
|
5541
|
+
(seenRows[key] = seenRows[key] || /* @__PURE__ */ new Set()).add(String(d.dataIndex));
|
|
5542
|
+
}
|
|
5543
|
+
const gotRows = Object.values(seenRows).reduce((sum, set) => sum + set.size, 0);
|
|
5544
|
+
if (gotRows < expectedDetailRows) {
|
|
5545
|
+
detailsState = "missing";
|
|
5546
|
+
warnings.push(
|
|
5547
|
+
`\u660E\u7EC6\u884C\u672A\u5B8C\u6574\u843D\u5E93\uFF08\u671F\u671B ${expectedDetailRows} \u884C\uFF0C\u8BFB\u56DE ${gotRows} \u884C\uFF09\uFF1A\u4E3B\u8868\u5DF2\u5199\u5165\uFF0C\u8BF7\u6838\u5BF9\u540E\u8865\u9F50\u660E\u7EC6`
|
|
5548
|
+
);
|
|
5549
|
+
}
|
|
5550
|
+
} catch (error) {
|
|
5551
|
+
detailsState = "unverified";
|
|
5552
|
+
warnings.push(`\u660E\u7EC6\u8BFB\u56DE\u6821\u9A8C\u5931\u8D25\uFF08\u65E0\u6CD5\u786E\u8BA4\u660E\u7EC6\u662F\u5426\u843D\u5E93\uFF09\uFF1A${error?.message || "\u672A\u77E5\u9519\u8BEF"}`);
|
|
5553
|
+
}
|
|
5554
|
+
}
|
|
6118
5555
|
return ehrSuccess("ehr.recruit.candidate.import.apply", {
|
|
6119
|
-
result: "success",
|
|
5556
|
+
result: detailsState === "complete" ? "success" : "partial",
|
|
5557
|
+
detailsState,
|
|
6120
5558
|
talentId,
|
|
6121
5559
|
candidateName: payload.candidateName,
|
|
6122
5560
|
telephone: payload.telephone,
|
|
6123
5561
|
mainTableFields: Object.keys(mainTable).length,
|
|
6124
5562
|
detailRows: payload.subStats || void 0,
|
|
5563
|
+
detailRowsExpected: expectedDetailRows || void 0,
|
|
6125
5564
|
attachment: uploaded ? { name: uploaded.name, size: uploaded.size } : null,
|
|
6126
5565
|
batch: { ok: batchOk, note: batchNote },
|
|
6127
5566
|
labelMatch,
|
|
@@ -6484,6 +5923,7 @@ async function executeAndPrint(ctx, operation, input) {
|
|
|
6484
5923
|
});
|
|
6485
5924
|
ctx.output.write(successEnvelope(operation, result), { json: true });
|
|
6486
5925
|
} catch (error) {
|
|
5926
|
+
reportPlatformError(error);
|
|
6487
5927
|
console.error(JSON.stringify(failureEnvelope(error), null, 2));
|
|
6488
5928
|
process.exitCode = isCliError(error) ? error.exitCode : 1 /* GeneralError */;
|
|
6489
5929
|
}
|