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.
Files changed (401) hide show
  1. package/README.md +17 -0
  2. package/dist/chunks/{archive-JHTONRST.js → archive-P6TBQGKL.js} +13 -5
  3. package/dist/chunks/{archive-oa-FCHLCPHC.js → archive-oa-7TQ2NXOH.js} +12 -5
  4. package/dist/chunks/{asset-RLIHC7DB.js → asset-3ELRG37G.js} +11 -4
  5. package/dist/chunks/{asset-idle-KVOFTLCP.js → asset-idle-WIGMUFMD.js} +7 -3
  6. package/dist/chunks/{attachment-content-RZYDB3MB.js → attachment-content-E3276UOV.js} +5 -4
  7. package/dist/chunks/{blog-42OZTJNP.js → blog-C5NMZAAC.js} +11 -4
  8. package/dist/chunks/{caizhilian-KRK547K5.js → caizhilian-5XSM2DFP.js} +13 -6
  9. package/dist/chunks/{calendar-RTWAMKHD.js → calendar-FI2WNSBO.js} +71 -26
  10. package/dist/chunks/{chunk-CXRQWOZ5.js → chunk-3YBDYOC4.js} +3 -3
  11. package/dist/chunks/{chunk-OOUTBLZ4.js → chunk-56EZERK4.js} +1 -1
  12. package/dist/chunks/chunk-6N4JPNFL.js +76 -0
  13. package/dist/chunks/{chunk-ZUX3P6BQ.js → chunk-727FH2NI.js} +1 -1
  14. package/dist/chunks/chunk-7BDPM5ST.js +11 -0
  15. package/dist/chunks/{chunk-LN447PY2.js → chunk-BCVYBYYT.js} +432 -2247
  16. package/dist/chunks/{chunk-7E6MUOEK.js → chunk-CWYGFU5B.js} +2 -2
  17. package/dist/chunks/{chunk-NOODWMCL.js → chunk-D4ADSZ7H.js} +1 -1
  18. package/dist/chunks/{chunk-WFFNM65B.js → chunk-ETNJSKMM.js} +281 -29
  19. package/dist/chunks/{chunk-CAQNBBQA.js → chunk-F4E4EM35.js} +3 -3
  20. package/dist/chunks/{chunk-4CTESSKI.js → chunk-FAZTGX7S.js} +6 -6
  21. package/dist/chunks/chunk-FRZKBMSW.js +2562 -0
  22. package/dist/chunks/{chunk-BYBSCN4X.js → chunk-G7PQWD4L.js} +6 -3
  23. package/dist/chunks/{chunk-NJKREDA3.js → chunk-GAMZLAG2.js} +1 -1
  24. package/dist/chunks/{chunk-FLS4DPGP.js → chunk-GM6J7Q4B.js} +28 -15
  25. package/dist/chunks/{chunk-NETCCARD.js → chunk-GRDRG6HP.js} +3 -3
  26. package/dist/chunks/chunk-HIT4Y6OI.js +1238 -0
  27. package/dist/chunks/{chunk-EZALDOQH.js → chunk-HP7JIYMT.js} +5 -2
  28. package/dist/chunks/{chunk-IZSSVYAG.js → chunk-IAZ3UPY6.js} +3 -3
  29. package/dist/chunks/{chunk-ZEDWSH32.js → chunk-IC62NFM5.js} +1 -1
  30. package/dist/chunks/{chunk-P26ZWSKU.js → chunk-KIHNAS25.js} +5 -2
  31. package/dist/chunks/{chunk-57IECMWX.js → chunk-N4M2DDFE.js} +29 -15
  32. package/dist/chunks/{chunk-JWRZM2H2.js → chunk-OF4S23UB.js} +4 -4
  33. package/dist/chunks/{chunk-VNBU55SL.js → chunk-PC7VKEB5.js} +80 -2458
  34. package/dist/chunks/{chunk-G2JSIUWF.js → chunk-PUQS5MWL.js} +91 -2
  35. package/dist/chunks/{chunk-E7OK5WD5.js → chunk-Q4OYAQYH.js} +5 -5
  36. package/dist/chunks/{chunk-7BRU4EFH.js → chunk-QVSWRLLU.js} +35 -6
  37. package/dist/chunks/{chunk-T6EGVBKU.js → chunk-TA7FXXJD.js} +6 -3
  38. package/dist/chunks/{chunk-GPMFD4RD.js → chunk-TXUG266F.js} +1 -1
  39. package/dist/chunks/{chunk-4TEDNCON.js → chunk-UFIT2UU3.js} +354 -56
  40. package/dist/chunks/{chunk-LUSPKZKY.js → chunk-UG5G54VL.js} +1 -0
  41. package/dist/chunks/{chunk-NIAJ5ZCG.js → chunk-UL5XUQ25.js} +5 -2
  42. package/dist/chunks/{chunk-FMPJJYYI.js → chunk-WRXSAVKO.js} +1 -1
  43. package/dist/chunks/{chunk-7U577Q7U.js → chunk-WSF4NNMR.js} +3 -3
  44. package/dist/chunks/chunk-XHK4MDR5.js +2497 -0
  45. package/dist/chunks/{chunk-LFMSDBZN.js → chunk-XNIK66I4.js} +326 -161
  46. package/dist/chunks/{chunk-3SO6QL6U.js → chunk-YWX377BY.js} +5 -2
  47. package/dist/chunks/{chunk-BYATLLEF.js → chunk-Z3GDFVJR.js} +1 -1
  48. package/dist/chunks/{chunk-I566ZYNF.js → chunk-Z7VYWPZV.js} +1 -1
  49. package/dist/chunks/{conflict-VR55AOOO.js → conflict-ARLSZJ6V.js} +4 -3
  50. package/dist/chunks/{continuation-2CKSBLA6.js → continuation-3S37AUSH.js} +4 -3
  51. package/dist/chunks/{continuation-RN6PZN2M.js → continuation-3XLYYTKV.js} +4 -3
  52. package/dist/chunks/{continuation-HZIZRZBX.js → continuation-HFW2YT5S.js} +4 -3
  53. package/dist/chunks/{continuation-NLECEJPX.js → continuation-KI7DRRZN.js} +4 -3
  54. package/dist/chunks/{contract-HI4FNPYE.js → contract-DNIIW5VJ.js} +13 -5
  55. package/dist/chunks/{cowork-HJLI353D.js → cowork-GMLRGVIW.js} +31 -14
  56. package/dist/chunks/create-flow-J22BO65E.js +56 -0
  57. package/dist/chunks/{ebuilder-form-HTGI63UU.js → ebuilder-form-ANV2FHYV.js} +12 -7
  58. package/dist/chunks/{ehr-GYXIYH3A.js → ehr-GSTGAIY3.js} +695 -1255
  59. package/dist/chunks/{employee-SAK2QYXX.js → employee-22BGJ3QS.js} +3 -3
  60. package/dist/chunks/{env-DW3G4HUO.js → env-BX3VRFS7.js} +4 -3
  61. package/dist/chunks/{esb-I5INCEFE.js → esb-ATAIASX2.js} +12 -7
  62. package/dist/chunks/{factory-TKXGXS6L.js → factory-PETTFME6.js} +3 -2
  63. package/dist/chunks/{fna-K2MHTQ24.js → fna-YEKBSFSX.js} +14 -8
  64. package/dist/chunks/{group-chat-VYBNMJLG.js → group-chat-BFVXAYFX.js} +7 -4
  65. package/dist/chunks/{host-D5SERMAJ.js → host-HRBXEPDQ.js} +5 -5
  66. package/dist/chunks/{host-JM4YVHFM.js → host-LR55CTHP.js} +5 -5
  67. package/dist/chunks/{host-L3VLITMT.js → host-SUOY6VYQ.js} +5 -5
  68. package/dist/chunks/{host-ZUQTJYYK.js → host-SZGV4UNT.js} +5 -5
  69. package/dist/chunks/{host-256GVCAH.js → host-WIKN2EJ5.js} +5 -5
  70. package/dist/chunks/{hrm-VLRBKTZB.js → hrm-NRDO4W5G.js} +11 -7
  71. package/dist/chunks/{im-QK3VTLXK.js → im-IQ2HN23S.js} +11 -10
  72. package/dist/chunks/{invoice-T5JTA32H.js → invoice-MNRW76PP.js} +636 -1768
  73. package/dist/chunks/{jiuchuanhui-P2FNEQVZ.js → jiuchuanhui-DTRBAX4N.js} +14 -6
  74. package/dist/chunks/{lazy-dispatch-XRRI46M6.js → lazy-dispatch-ZVWAI25B.js} +7 -6
  75. package/dist/chunks/{mail-3Y7MJ6PS.js → mail-ZVAUXOJA.js} +16 -14
  76. package/dist/chunks/{meeting-M7LTXGJE.js → meeting-FEVPZ67S.js} +21 -13
  77. package/dist/chunks/{okr-OBC6S67L.js → okr-SDH3E5RA.js} +12 -5
  78. package/dist/chunks/{operations-5QL3AECO.js → operations-62N6EP3C.js} +4 -3
  79. package/dist/chunks/{plan-5H6I53SK.js → plan-E35JFDI7.js} +12 -5
  80. package/dist/chunks/{project-L75QZV4S.js → project-73QXBAB2.js} +49 -25
  81. package/dist/chunks/reception-UWZVACBN.js +1899 -0
  82. package/dist/chunks/recruit-stage-4MAOCKFY.js +4770 -0
  83. package/dist/chunks/registry-IM5G23LS.js +24 -0
  84. package/dist/chunks/{registry-UGRBCBHO.js → registry-JDUS4E7D.js} +7 -6
  85. package/dist/chunks/{registry-RXPN6BBT.js → registry-KNKSCJNT.js} +7 -6
  86. package/dist/chunks/{registry-NYPYMZXG.js → registry-PO7SI256.js} +4 -4
  87. package/dist/chunks/{registry-QGHFNUWS.js → registry-PVUZQDDQ.js} +3 -3
  88. package/dist/chunks/{room-recommend-A3UDC3CA.js → room-recommend-H7KLXA5R.js} +6 -5
  89. package/dist/chunks/{schedule-5GCACCK7.js → schedule-ESZIBAUO.js} +6 -5
  90. package/dist/chunks/{workflow-M5ZJ7DWF.js → workflow-CWJFJLQU.js} +15 -10
  91. package/dist/cmd/action.js +6 -0
  92. package/dist/cmd/identity/index.js +45 -0
  93. package/dist/cmd/index.js +2 -0
  94. package/dist/core/continuation-ttl.js +18 -0
  95. package/dist/core/error-codes.js +85 -0
  96. package/dist/core/logger.js +11 -0
  97. package/dist/index.js +41 -30
  98. package/dist/internal/e10/auth/commands.js +164 -8
  99. package/dist/internal/e10/auth/error-log.js +182 -0
  100. package/dist/internal/e10/auth/messages.js +6 -0
  101. package/dist/internal/e10/auth/session.js +34 -3
  102. package/dist/internal/e10/auth/xiaoe.js +286 -44
  103. package/dist/internal/e10/auth-recovery.js +72 -14
  104. package/dist/internal/e10/context.js +72 -13
  105. package/dist/internal/e10/index.js +1 -1
  106. package/dist/internal/e10/network-error.js +93 -0
  107. package/dist/internal/e10/request-runtime.js +6 -0
  108. package/dist/internal/skills/install.js +9 -1
  109. package/dist/shortcuts/archive/continuation.js +2 -1
  110. package/dist/shortcuts/archive/index.js +3 -0
  111. package/dist/shortcuts/archive/operations/confirm.js +2 -1
  112. package/dist/shortcuts/archive-oa/continuation.js +2 -1
  113. package/dist/shortcuts/archive-oa/index.js +2 -0
  114. package/dist/shortcuts/archive-oa/operations/confirm.js +2 -1
  115. package/dist/shortcuts/asset/continuation.js +2 -1
  116. package/dist/shortcuts/asset/index.js +2 -0
  117. package/dist/shortcuts/asset-idle/index.js +2 -0
  118. package/dist/shortcuts/blog/continuation.js +2 -1
  119. package/dist/shortcuts/blog/index.js +2 -0
  120. package/dist/shortcuts/caizhilian/continuation.js +2 -1
  121. package/dist/shortcuts/caizhilian/index.js +2 -0
  122. package/dist/shortcuts/caizhilian/operations/confirm.js +3 -2
  123. package/dist/shortcuts/calendar/continuation.js +2 -1
  124. package/dist/shortcuts/calendar/index.js +2 -0
  125. package/dist/shortcuts/calendar/operations/read.js +31 -22
  126. package/dist/shortcuts/calendar/operations/write.js +46 -2
  127. package/dist/shortcuts/contract/continuation.js +2 -1
  128. package/dist/shortcuts/contract/index.js +2 -0
  129. package/dist/shortcuts/contract/operations/write.js +2 -1
  130. package/dist/shortcuts/cowork/continuation.js +2 -1
  131. package/dist/shortcuts/cowork/index.js +2 -0
  132. package/dist/shortcuts/cowork/operations/discuss-write.js +5 -1
  133. package/dist/shortcuts/cowork/operations/item-write.js +1 -7
  134. package/dist/shortcuts/cowork/operations/member-write.js +3 -1
  135. package/dist/shortcuts/cowork/operations/permission-write.js +5 -1
  136. package/dist/shortcuts/cowork/operations/shared.js +7 -0
  137. package/dist/shortcuts/ebuilder-form/continuation.js +2 -1
  138. package/dist/shortcuts/ebuilder-form/index.js +2 -0
  139. package/dist/shortcuts/ebuilder-form/operations/write.js +3 -2
  140. package/dist/shortcuts/ehr/continuation.js +2 -1
  141. package/dist/shortcuts/ehr/index.js +2 -0
  142. package/dist/shortcuts/ehr/operations/attend-write.js +44 -2
  143. package/dist/shortcuts/ehr/operations/hr-contact.js +7 -4
  144. package/dist/shortcuts/ehr/operations/hr-report.js +13 -7
  145. package/dist/shortcuts/ehr/operations/recruit-candidate-import.js +317 -63
  146. package/dist/shortcuts/ehr/operations/recruit-position.js +134 -2
  147. package/dist/shortcuts/ehr/operations/recruit-write.js +263 -18
  148. package/dist/shortcuts/ehr/operations/recruit.js +10 -4
  149. package/dist/shortcuts/ehr/operations/shared.js +47 -0
  150. package/dist/shortcuts/esb/continuation.js +2 -1
  151. package/dist/shortcuts/esb/index.js +2 -0
  152. package/dist/shortcuts/esb/operations/trigger.js +2 -1
  153. package/dist/shortcuts/fna/continuation.js +2 -1
  154. package/dist/shortcuts/fna/index.js +2 -0
  155. package/dist/shortcuts/fna/operations/invoice-writeoff.js +1 -1
  156. package/dist/shortcuts/fna/operations/loan.js +1 -1
  157. package/dist/shortcuts/hrm/index.js +2 -0
  158. package/dist/shortcuts/hrm/operations/org.js +118 -0
  159. package/dist/shortcuts/im/continuation.js +2 -1
  160. package/dist/shortcuts/index.js +10 -0
  161. package/dist/shortcuts/invoice/continuation.js +2 -1
  162. package/dist/shortcuts/invoice/index.js +14 -15
  163. package/dist/shortcuts/invoice/invoice-record.js +93 -0
  164. package/dist/shortcuts/invoice/manifest.js +190 -393
  165. package/dist/shortcuts/invoice/operations/add.js +2 -1
  166. package/dist/shortcuts/invoice/operations/delete.js +2 -1
  167. package/dist/shortcuts/invoice/operations/import.js +2 -1
  168. package/dist/shortcuts/invoice/operations/issuing-contract-detail.js +86 -0
  169. package/dist/shortcuts/invoice/operations/issuing-contracts.js +210 -0
  170. package/dist/shortcuts/invoice/operations/registry.js +17 -17
  171. package/dist/shortcuts/invoice/operations/reim-auto.js +4 -569
  172. package/dist/shortcuts/invoice/operations/reim.js +52 -341
  173. package/dist/shortcuts/invoice/operations/shared.js +21 -4
  174. package/dist/shortcuts/invoice/operations/update.js +2 -1
  175. package/dist/shortcuts/invoice/projection.js +10 -62
  176. package/dist/shortcuts/jiuchuanhui/continuation.js +2 -1
  177. package/dist/shortcuts/jiuchuanhui/index.js +2 -0
  178. package/dist/shortcuts/jiuchuanhui/operations/datajson.js +2 -1
  179. package/dist/shortcuts/jiuchuanhui/operations/esb.js +2 -1
  180. package/dist/shortcuts/mail/continuation.js +2 -1
  181. package/dist/shortcuts/mail/index.js +2 -0
  182. package/dist/shortcuts/mail/operations/mail-blacklist.js +1 -1
  183. package/dist/shortcuts/mail/operations/mail-contacts.js +1 -1
  184. package/dist/shortcuts/mail/operations/mail-send.js +1 -1
  185. package/dist/shortcuts/mail/operations/mail-sign.js +1 -1
  186. package/dist/shortcuts/mail/operations/mail-template.js +1 -1
  187. package/dist/shortcuts/meeting/continuation.js +2 -1
  188. package/dist/shortcuts/meeting/index.js +2 -0
  189. package/dist/shortcuts/meeting/operations/change.js +1 -1
  190. package/dist/shortcuts/meeting/operations/create.js +1 -1
  191. package/dist/shortcuts/meeting/operations/eb/catalog.js +4 -1
  192. package/dist/shortcuts/meeting/operations/eb/create-flow.js +101 -35
  193. package/dist/shortcuts/meeting/operations/eb/decision.js +1 -1
  194. package/dist/shortcuts/meeting/operations/eb/factory.js +34 -1
  195. package/dist/shortcuts/meeting/operations/eb/group-chat.js +25 -3
  196. package/dist/shortcuts/meeting/operations/eb/person-cache.js +96 -0
  197. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +33 -11
  198. package/dist/shortcuts/meeting/operations/lifecycle.js +1 -1
  199. package/dist/shortcuts/meeting/operations/receipts.js +1 -1
  200. package/dist/shortcuts/meeting/operations/signs.js +1 -1
  201. package/dist/shortcuts/okr/continuation.js +2 -1
  202. package/dist/shortcuts/okr/index.js +2 -0
  203. package/dist/shortcuts/okr/operations/write.js +1 -1
  204. package/dist/shortcuts/plan/continuation.js +2 -1
  205. package/dist/shortcuts/plan/index.js +2 -0
  206. package/dist/shortcuts/plan/operations/write.js +1 -1
  207. package/dist/shortcuts/project/continuation.js +2 -1
  208. package/dist/shortcuts/project/index.js +2 -0
  209. package/dist/shortcuts/project/operations/read.js +6 -25
  210. package/dist/shortcuts/project/operations/shared.js +22 -0
  211. package/dist/shortcuts/project/operations/write.js +28 -2
  212. package/dist/shortcuts/reception/constants.js +53 -0
  213. package/dist/shortcuts/reception/errors.js +54 -0
  214. package/dist/shortcuts/reception/host.js +125 -0
  215. package/dist/shortcuts/reception/index.js +198 -0
  216. package/dist/shortcuts/reception/manifest.js +177 -0
  217. package/dist/shortcuts/reception/operations/ask.js +71 -0
  218. package/dist/shortcuts/reception/operations/browsertool.js +58 -0
  219. package/dist/shortcuts/reception/operations/compose.js +129 -0
  220. package/dist/shortcuts/reception/operations/customparams.js +74 -0
  221. package/dist/shortcuts/reception/operations/doc.js +238 -0
  222. package/dist/shortcuts/reception/operations/docrender.js +36 -0
  223. package/dist/shortcuts/reception/operations/panels.js +179 -0
  224. package/dist/shortcuts/reception/operations/registry.js +26 -0
  225. package/dist/shortcuts/reception/operations/render-assets.js +184 -0
  226. package/dist/shortcuts/reception/operations/render.js +123 -0
  227. package/dist/shortcuts/reception/operations/runs.js +38 -0
  228. package/dist/shortcuts/reception/operations/schedule.js +127 -0
  229. package/dist/shortcuts/reception/operations/shared.js +196 -0
  230. package/dist/shortcuts/reception/operations/snapshot.js +68 -0
  231. package/dist/shortcuts/reception/operations/types.js +1 -0
  232. package/dist/shortcuts/reception/operations.js +33 -0
  233. package/dist/shortcuts/reception/upload.js +218 -0
  234. package/dist/shortcuts/recruit-stage/context.js +231 -0
  235. package/dist/shortcuts/recruit-stage/continuation.js +74 -0
  236. package/dist/shortcuts/recruit-stage/errors.js +65 -0
  237. package/dist/shortcuts/recruit-stage/host.js +109 -0
  238. package/dist/shortcuts/recruit-stage/index.js +115 -0
  239. package/dist/shortcuts/recruit-stage/manifest.js +29 -0
  240. package/dist/shortcuts/recruit-stage/operations/interview-arrange.js +722 -0
  241. package/dist/shortcuts/recruit-stage/operations/interview-feedback.js +269 -0
  242. package/dist/shortcuts/recruit-stage/operations/jd-create.js +719 -0
  243. package/dist/shortcuts/recruit-stage/operations/list.js +431 -0
  244. package/dist/shortcuts/recruit-stage/operations/registry.js +38 -0
  245. package/dist/shortcuts/recruit-stage/operations/resume-import.js +1354 -0
  246. package/dist/shortcuts/recruit-stage/operations/search.js +158 -0
  247. package/dist/shortcuts/recruit-stage/operations/types.js +25 -0
  248. package/dist/shortcuts/recruit-stage/school-tiers.json +318 -0
  249. package/dist/shortcuts/recruit-stage/shared.js +608 -0
  250. package/dist/shortcuts/workflow/continuation.js +2 -1
  251. package/dist/shortcuts/workflow/index.js +2 -0
  252. package/dist/shortcuts/workflow/operations/form.js +32 -8
  253. package/dist/shortcuts/workflow/operations/todoSmartConvert/detailFieldRules.js +4 -2
  254. package/dist/shortcuts/workflow/operations/todoSmartConvert/summaryCache.js +13 -6
  255. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailCache.js +17 -24
  256. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailFetcher.js +14 -9
  257. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.js +50 -8
  258. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.core.js +2 -1
  259. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.detail.js +17 -11
  260. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.group.js +7 -39
  261. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.js +3 -2
  262. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.js +51 -15
  263. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.pipeline.js +16 -1
  264. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.smartGroup.js +151 -63
  265. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.subGroup.js +56 -0
  266. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.summary.js +39 -14
  267. package/dist/shortcuts/workflow/operations/write.js +1 -1
  268. package/docs/_catalog.md +3 -0
  269. package/docs/agent-invoice.md +1 -1
  270. package/docs/archive-oa.md +1 -1
  271. package/docs/caizhilian.md +1 -1
  272. package/docs/calendar.md +1 -1
  273. package/docs/contract.md +1 -1
  274. package/docs/e10-auth.md +23 -1
  275. package/docs/ehr.md +2 -2
  276. package/docs/esb.md +1 -1
  277. package/docs/im.md +1 -1
  278. package/docs/invoice.md +8 -12
  279. package/docs/okr.md +1 -1
  280. package/docs/operation-manual.md +8 -0
  281. package/docs/reception.md +119 -0
  282. package/package.json +1 -1
  283. package/scripts/clean.mjs +43 -2
  284. package/scripts/install-skill-to-xiaoe.mjs +105 -0
  285. package/scripts/package-skill.mjs +4 -2
  286. package/skill-template/business-info.json +42 -2
  287. package/skill-template/domains/caizhilian.md +1 -1
  288. package/skill-template/domains/reception-flow.md +18 -0
  289. package/skill-template/domains/recruit-stage.md +29 -0
  290. package/skill-template/domains/yepiaotong.md +4 -7
  291. package/skills/weaver-e10-archive-oa/references/source-manifest.json +14 -14
  292. package/skills/weaver-e10-blog/references/blog-publish.md +1 -1
  293. package/skills/weaver-e10-blog/references/source-manifest.json +7 -7
  294. package/skills/weaver-e10-caizhilian/references/source-manifest.json +21 -21
  295. package/skills/weaver-e10-caizhilian/references/write-protocol.md +2 -2
  296. package/skills/weaver-e10-calendar/SKILL.md +2 -1
  297. package/skills/weaver-e10-calendar/references/calendar-write.md +55 -1
  298. package/skills/weaver-e10-cowork/SKILL.md +1 -1
  299. package/skills/weaver-e10-cowork/references/cowork-write.md +3 -1
  300. package/skills/weaver-e10-ebuilder-form/SKILL.md +1 -1
  301. package/skills/weaver-e10-ebuilder-form/references/custom-api.md +1 -1
  302. package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +1 -1
  303. package/skills/weaver-e10-esb/SKILL.md +2 -2
  304. package/skills/weaver-e10-esb/references/source-manifest.json +22 -22
  305. package/skills/weaver-e10-esb/references/trigger.md +2 -2
  306. package/skills/weaver-e10-jinchengda/references/contract-clause-library-crud.md +1 -1
  307. package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +1 -1
  308. package/skills/weaver-e10-jinchengda/references/contract-request-write.md +1 -1
  309. package/skills/weaver-e10-jinchengda/references/source-manifest.json +29 -29
  310. package/skills/weaver-e10-jucailin/SKILL.md +1 -1
  311. package/skills/weaver-e10-jucailin/references/attend-write.md +10 -2
  312. package/skills/weaver-e10-jucailin/references/hr-contact.md +8 -0
  313. package/skills/weaver-e10-jucailin/references/hr-report.md +8 -0
  314. package/skills/weaver-e10-jucailin/references/recruit-create.md +14 -5
  315. package/skills/weaver-e10-jucailin/references/recruit-read.md +1 -1
  316. package/skills/weaver-e10-jucailin/references/recruit-write.md +5 -4
  317. package/skills/weaver-e10-mail/SKILL.md +1 -1
  318. package/skills/weaver-e10-meeting/SKILL.md +39 -7
  319. package/skills/weaver-e10-meeting/references/meeting-change.md +1 -1
  320. package/skills/weaver-e10-meeting/references/meeting-create.md +1 -1
  321. package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +1 -1
  322. package/skills/weaver-e10-meeting/references/meeting-verification.md +1 -1
  323. package/skills/weaver-e10-okr/references/okr-align.md +1 -1
  324. package/skills/weaver-e10-okr/references/okr-keyresult.md +1 -1
  325. package/skills/weaver-e10-okr/references/okr-write.md +1 -1
  326. package/skills/weaver-e10-okr/references/source-manifest.json +8 -8
  327. package/skills/weaver-e10-plan/references/plan-report-write.md +1 -1
  328. package/skills/weaver-e10-plan/references/source-manifest.json +20 -20
  329. package/skills/weaver-e10-qiyecheng/references/loan-management.md +1 -1
  330. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +18 -18
  331. package/skills/weaver-e10-reception-flow/SKILL.md +173 -0
  332. 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
  333. package/skills/weaver-e10-reception-flow/data/fields-snapshot.json +213 -0
  334. package/skills/weaver-e10-reception-flow/references/browsertool.md +68 -0
  335. package/skills/weaver-e10-reception-flow/references/env-pitfalls.md +51 -0
  336. package/skills/weaver-e10-reception-flow/references/fields-snapshot.md +227 -0
  337. package/skills/weaver-e10-reception-flow/references/guide.md +179 -0
  338. package/skills/weaver-e10-reception-flow/scripts/locate.sh +14 -0
  339. package/skills/weaver-e10-reception-flow/scripts/render.py +724 -0
  340. package/skills/weaver-e10-recruit-stage/SKILL.md +230 -0
  341. package/skills/weaver-e10-recruit-stage/agents/openai.yaml +119 -0
  342. package/skills/weaver-e10-recruit-stage/lib/recruit-xiaoe-file.mjs +188 -0
  343. package/skills/weaver-e10-recruit-stage/lib/xiaoe-session.mjs +66 -0
  344. package/skills/weaver-e10-recruit-stage/references/position-templates.md +202 -0
  345. package/skills/weaver-e10-recruit-stage/references/recruit-arrange-interview.md +322 -0
  346. package/skills/weaver-e10-recruit-stage/references/recruit-capability-check.md +127 -0
  347. package/skills/weaver-e10-recruit-stage/references/recruit-check-install.md +65 -0
  348. package/skills/weaver-e10-recruit-stage/references/recruit-detail-process.md +63 -0
  349. package/skills/weaver-e10-recruit-stage/references/recruit-edit-interview-feedback.md +142 -0
  350. package/skills/weaver-e10-recruit-stage/references/recruit-jd-create.md +95 -0
  351. package/skills/weaver-e10-recruit-stage/references/recruit-jd-template.md +56 -0
  352. package/skills/weaver-e10-recruit-stage/references/recruit-list-candidate.md +101 -0
  353. package/skills/weaver-e10-recruit-stage/references/recruit-list-interview.md +148 -0
  354. package/skills/weaver-e10-recruit-stage/references/recruit-match-candidates.md +77 -0
  355. package/skills/weaver-e10-recruit-stage/references/recruit-output-links.md +59 -0
  356. package/skills/weaver-e10-recruit-stage/references/recruit-resolve-creator.md +69 -0
  357. package/skills/weaver-e10-recruit-stage/references/recruit-resolve-metadata.md +241 -0
  358. package/skills/weaver-e10-recruit-stage/references/recruit-resume-import.md +451 -0
  359. package/skills/weaver-e10-recruit-stage/references/recruit-resume-parse.md +128 -0
  360. package/skills/weaver-e10-recruit-stage/references/recruit-search-candidate.md +146 -0
  361. package/skills/weaver-e10-recruit-stage/references/recruit-urge-feedback.md +69 -0
  362. package/skills/weaver-e10-shared/SKILL.md +1 -1
  363. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +10 -2
  364. package/skills/weaver-e10-shijingran/SKILL.md +7 -6
  365. package/skills/weaver-e10-shijingran/references/operations.md +3 -1
  366. package/skills/weaver-e10-shijingran/references/source-manifest.json +30 -28
  367. package/skills/weaver-e10-shijingran/references/write-operations.md +2 -0
  368. package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +2 -0
  369. package/skills/weaver-e10-wenshuding/references/source-manifest.json +3 -3
  370. package/skills/weaver-e10-workflow/SKILL.md +4 -2
  371. package/skills/weaver-e10-workflow/aigroup/default.json +11 -9
  372. package/skills/weaver-e10-workflow/references/source-manifest.json +32 -32
  373. package/skills/weaver-e10-workflow/references/todo-smart-convert.md +23 -13
  374. package/skills/weaver-e10-workflow/tools/todo-summary.cjs +62 -20
  375. package/skills/weaver-e10-yepiaotong/SKILL.md +28 -36
  376. package/skills/weaver-e10-yepiaotong/references/invoice-agent-entry.md +6 -3
  377. package/skills/weaver-e10-yepiaotong/references/invoice-detail.md +13 -10
  378. package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +2 -0
  379. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-workflow.md +194 -155
  380. package/skills/weaver-e10-yepiaotong/references/invoice-output-view.md +28 -32
  381. package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +5 -1
  382. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +8 -10
  383. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +211 -616
  384. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +149 -117
  385. package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +17 -20
  386. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +20 -39
  387. package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +55 -22
  388. package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +7 -17
  389. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +88 -92
  390. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +144 -354
  391. package/skills/weaver-e10-yimiaoban/SKILL.md +1 -1
  392. package/skills/weaver-e10-yimiaoban/references/msg-write.md +1 -1
  393. package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +1 -1
  394. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +7 -7
  395. package/dist/chunks/chunk-SPRHHSVC.js +0 -465
  396. package/dist/chunks/registry-KMHCPAAD.js +0 -22
  397. package/dist/shortcuts/invoice/markdown.js +0 -172
  398. package/dist/shortcuts/invoice/operations/issuing-qys.js +0 -424
  399. package/skills/weaver-e10-meeting.zip +0 -0
  400. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +0 -131
  401. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-form-fill-rules.md +0 -179
@@ -0,0 +1,724 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ render.py — 一次把接待信息渲染成两份产物(对外 docx + 内部 md)
5
+
6
+ 为什么要有它:原流程每次都让模型现场写 python-docx 代码,既慢又容易踩
7
+ 「模板 444 只读 -> shutil.copy 复制权限位 -> d.save() 抛 PermissionError」这个坑。
8
+ 本脚本把踩过的坑固化成代码:
9
+
10
+ 1) 复制模板一律用 copyfile(不复制权限位)+ 落盘后 chmod 644
11
+ 2) 表格行数按实际行程自动增删(克隆末行以保留版式)
12
+ 3) 段落按文本前缀定位,模板微调不会错位
13
+ 4) 对外件自动剔除内部口径(分工/待办/金额/审批)
14
+
15
+ 用法:
16
+ python3 scripts/render.py --data recv.json --out-dir /workspace/files
17
+ python3 scripts/render.py --data recv.json --out-dir ./recv --only docx|md
18
+
19
+ 输入 JSON(字段均可缺省,缺省即不写):
20
+ {
21
+ "customer": "某某集团有限公司",
22
+ "headcount": 5,
23
+ "visitDate": "2026-10-22",
24
+ "visitType": "参观上海总部",
25
+ "contact": "张三(泛微网络 XX中心 XX组)",
26
+ "companions": [{"name": "张三", "mobile": "13800138000"}],
27
+ "demand": "商务洽谈 + 技术交流",
28
+ "pickup": "", "meal": "食堂用餐", "mealHeadcount": 6,
29
+ "hotel": "无需住宿", "gift": "不需要伴手礼", "agendaStart": "09:30",
30
+ "venue": "泛微网络 上海总部", "meetingRoom": "总部129会议室",
31
+ "schedule": [["上午","抵达泛微上海总部,签到与欢迎","泛微上海总部"]],
32
+ "todo": ["客户性质", "项目金额(万元)"]
33
+ }
34
+ """
35
+ import argparse, json, os, re, shutil, sys, datetime, hashlib
36
+
37
+ try:
38
+ import docx
39
+ from docx.shared import Pt
40
+ except ImportError:
41
+ docx = None
42
+
43
+ HERE = os.path.dirname(os.path.abspath(__file__))
44
+ TPL = os.path.join(HERE, '..', 'assets', '行程单模板-泛微.docx')
45
+ WEEK = '一二三四五六日'
46
+
47
+ # v2.8:对外件内部口径清洗(原版只剔段落级内部字段,表格与地点里的
48
+ # 「(具体单位待确认)」「待确认」会原样漏到客户版,属产物质量缺陷)
49
+ INTERNAL_MARKS = ('待确认', '待补', '待定', '待办', '内部', '未定', 'TBD', 'tbd')
50
+ EXTERNAL_FALLBACK = '以现场安排为准'
51
+ _PAREN = re.compile(r'[((][^(())]*[))]')
52
+
53
+
54
+ def has_mark(v):
55
+ return any(k in str(v or '') for k in INTERNAL_MARKS)
56
+
57
+
58
+ def ext(v, fallback=EXTERNAL_FALLBACK):
59
+ """对外件取值:先剥掉含内部口径的括注,整串仍带内部口径则用兜底语。"""
60
+ s = str(v or '').strip()
61
+ if not s:
62
+ return ''
63
+ for _ in range(3):
64
+ s2 = _PAREN.sub(lambda m: '' if has_mark(m.group(0)) else m.group(0), s).strip()
65
+ if s2 == s:
66
+ break
67
+ s = s2
68
+ if not s or has_mark(s):
69
+ return fallback
70
+ return s
71
+
72
+
73
+ _RE_NUM = re.compile(r'\d+(?:\.\d+)?')
74
+
75
+
76
+ def num(v, default=0):
77
+ """人数类字段取数:兼容 8 / "8" / "6~10人" 等写法。
78
+ 区间取上界:用餐与场地按人数上限预留更安全;无法解析时返回 default。"""
79
+ if v is None or isinstance(v, bool) or v == '':
80
+ return default
81
+ if isinstance(v, (int, float)):
82
+ return int(v)
83
+ nums = _RE_NUM.findall(str(v))
84
+ if not nums:
85
+ return default
86
+ try:
87
+ return max(int(float(n)) for n in nums)
88
+ except (TypeError, ValueError):
89
+ return default
90
+
91
+
92
+ def ppl(v):
93
+ """人数展示:剥掉「左右/上下/余人」等模糊尾巴与「人/位/名」量词,避免「约8人左右 人」。"""
94
+ if v is None or v == '':
95
+ return ''
96
+ s = re.sub(r'(左右|上下|多人|余人|以上|以下|人|位|名)\s*$', '', str(v).strip()).strip()
97
+ return re.sub(r'[\s人位名]+$', '', s).strip()
98
+
99
+
100
+ def scan_docx(path):
101
+ """自检:对外件里是否还残留内部口径(有残留就是质量缺陷,要报出来)。"""
102
+ try:
103
+ dd = docx.Document(path)
104
+ except Exception:
105
+ return {'externalLeaks': 0, 'leakSamples': []}
106
+ lines = []
107
+ for p in dd.paragraphs:
108
+ if p.text.strip():
109
+ lines.append(p.text)
110
+ para = len(lines)
111
+ for t in dd.tables:
112
+ for row in t.rows:
113
+ for c in row.cells:
114
+ if c.text.strip():
115
+ lines.append(c.text)
116
+ leaks = [ln for ln in lines if has_mark(ln)]
117
+ return {'externalLeaks': len(leaks), 'leakSamples': leaks[:3], 'paragraphs': para}
118
+
119
+
120
+ def sha8(path):
121
+ """产物指纹前 8 位:给上层 verify 用,让模型不必 cat 全文就能确认文件是刚生成的那份。"""
122
+ try:
123
+ with open(path, 'rb') as f:
124
+ return hashlib.sha256(f.read()).hexdigest()[:8]
125
+ except Exception:
126
+ return ''
127
+
128
+
129
+ def prepare_target(path):
130
+ """目标已存在且为只读时先放开权限,否则 copyfile/open('w') 会直接 PermissionError。"""
131
+ if os.path.exists(path):
132
+ try:
133
+ os.chmod(path, 0o644)
134
+ except OSError:
135
+ pass
136
+
137
+
138
+ def safe_write(path):
139
+ """落盘后统一放开权限,避免只读模板把后续步骤卡死。"""
140
+ try:
141
+ os.chmod(path, 0o644)
142
+ except OSError:
143
+ pass
144
+
145
+
146
+ def cn_date(s):
147
+ try:
148
+ d = datetime.date.fromisoformat(s)
149
+ return f'{d.year}年{d.month}月{d.day}日(星期{WEEK[d.weekday()]})'
150
+ except Exception:
151
+ return s or ''
152
+
153
+
154
+ def set_para(p, text):
155
+ if p.runs:
156
+ p.runs[0].text = text
157
+ for r in p.runs[1:]:
158
+ r.text = ''
159
+ else:
160
+ p.add_run(text)
161
+
162
+
163
+ def fill_para(doc, prefix, text):
164
+ """按前缀定位段落并改写;前缀不中时退化为包含匹配(模板里有「1月2日参观行程安排:」这类前缀不固定的行);仍不中则追加。"""
165
+ for p in doc.paragraphs:
166
+ if p.text.strip().startswith(prefix):
167
+ set_para(p, text)
168
+ return True
169
+ for p in doc.paragraphs:
170
+ if prefix in p.text:
171
+ set_para(p, text)
172
+ return True
173
+ doc.add_paragraph(text)
174
+ return False
175
+
176
+
177
+ def resize_table(table, need_rows):
178
+ """need_rows = 数据行数(不含表头)。克隆末行以保留边框与字体。"""
179
+ import copy
180
+ have = len(table.rows) - 1
181
+ if need_rows > have:
182
+ for _ in range(need_rows - have):
183
+ tr = copy.deepcopy(table.rows[-1]._tr)
184
+ table.rows[-1]._tr.addnext(tr)
185
+ elif need_rows < have:
186
+ for _ in range(have - need_rows):
187
+ tr = table.rows[-1]._tr
188
+ tr.getparent().remove(tr)
189
+
190
+
191
+ SCHED_KEYS = {
192
+ 'date': ('date', '日期', 'rq'),
193
+ 'time': ('time', '时间', '时段', 'sj'),
194
+ 'item': ('item', '接待事项', '事项', 'jdsx'),
195
+ 'place': ('place', '地点', 'venue', 'dd'),
196
+ 'person': ('person', '接待人员', '人员', 'jdry'),
197
+ 'activity': ('activity', '活动安排', '安排', 'hdap'),
198
+ 'remark': ('remark', '备注', 'bz'),
199
+ }
200
+ SCHED_ORDER = ['date', 'time', 'item', 'place', 'person', 'activity', 'remark']
201
+
202
+
203
+ def _pick(row, key):
204
+ for alias in SCHED_KEYS[key]:
205
+ if alias in row and row.get(alias) not in (None, ''):
206
+ return row.get(alias)
207
+ return ''
208
+
209
+
210
+ def norm_schedule(d):
211
+ """把 schedule 归一成 7 字段行(date/time/item/place/person/activity/remark)。
212
+
213
+ v4.7:既兼容旧的三元组 [时段, 安排, 地点],也接受 7 字段对象(中英文键均可),
214
+ 产出的结构同时用于对外行程单、内部方案与流程【日程明细】子表。
215
+ """
216
+ rows = []
217
+ for raw in (d.get('schedule') or []):
218
+ if isinstance(raw, dict):
219
+ rows.append({k: _pick(raw, k) for k in SCHED_ORDER})
220
+ elif isinstance(raw, (list, tuple)):
221
+ vals = list(raw) + [''] * 7
222
+ rows.append({
223
+ 'date': vals[0] if len(raw) >= 7 else '',
224
+ 'time': vals[0] if len(raw) < 7 else vals[1],
225
+ 'item': vals[1] if len(raw) < 7 else vals[2],
226
+ 'place': vals[2] if len(raw) < 7 else vals[3],
227
+ 'person': '' if len(raw) < 7 else vals[4],
228
+ 'activity': '' if len(raw) < 7 else vals[5],
229
+ 'remark': '' if len(raw) < 7 else vals[6],
230
+ })
231
+ return rows
232
+
233
+
234
+ # ==================== v4.9:标准议程 + 陪同人员联系方式 ====================
235
+ # 对外行程单只呈现「公司参观 → 方案介绍 → 讨论交流」这类议程环节。
236
+ # 用餐、接送、住宿、返程等后勤动作一律不进时间表(它们写在行程单抬头
237
+ # 与内部方案的「食宿与用车」章节),这是接待口径不是报错。
238
+ AGENDA_EXCLUDE = (
239
+ '用餐', '午餐', '晚餐', '早餐', '午宴', '晚宴', '宴请', '食堂', '餐厅', '饭',
240
+ '接机', '接站', '送机', '送站', '接送', '用车', '车辆', '商务车', '大巴',
241
+ '住宿', '入住', '离店', '酒店', '返程', '接返', '出发去机场',
242
+ )
243
+ # (展示名, 起始偏移分钟, 时长分钟, 活动说明缺省值)
244
+ STANDARD_AGENDA = (
245
+ ('公司参观', 0, 45, '参观泛微上海总部展厅与办公区,了解公司发展历程与产品能力'),
246
+ ('方案介绍', 45, 75, ''),
247
+ ('讨论交流', 120, 30, '双方围绕关注点交流答疑,明确后续推进节奏'),
248
+ )
249
+ DEFAULT_START = '09:30'
250
+
251
+
252
+ def _hm(minutes):
253
+ return f'{minutes // 60:02d}:{minutes % 60:02d}'
254
+
255
+
256
+ def _parse_hm(s):
257
+ m = re.match(r'^\s*(\d{1,2})[::](\d{2})\s*$', str(s or ''))
258
+ if not m:
259
+ return None
260
+ h, mi = int(m.group(1)), int(m.group(2))
261
+ return h * 60 + mi if (0 <= h <= 23 and 0 <= mi <= 59) else None
262
+
263
+
264
+ def is_logistics(text):
265
+ """判断一行是否属于用餐/接送/住宿类后勤动作(不进议程时间表)。"""
266
+ s = str(text or '')
267
+ return any(k in s for k in AGENDA_EXCLUDE)
268
+
269
+
270
+ def _agenda_row(start, end, item, activity='', place='', person='', remark=''):
271
+ return {
272
+ 'start': start, 'end': end,
273
+ 'time': f'{start}-{end}' if (start and end) else (start or end),
274
+ 'item': item, 'activity': activity, 'place': place,
275
+ 'person': person, 'remark': remark,
276
+ }
277
+
278
+
279
+ def norm_agenda(d):
280
+ """行程归一为「议程行」,自动剔除用餐/接送/住宿等后勤动作。
281
+
282
+ 取值优先级:
283
+ 1) data.agenda 显式议程(逐行 time/start+end/item/activity/place/person)
284
+ 2) data.schedule 中剔除后勤动作后的行(保留客户真实时间)
285
+ 3) 标准议程:公司参观 → 方案介绍 → 讨论交流(起点 data.agendaStart,缺省 09:30)
286
+ """
287
+ venue = str(d.get('venue') or '泛微上海总部').strip()
288
+ room = str(d.get('meetingRoom') or '').strip() or venue
289
+
290
+ explicit = [r for r in (d.get('agenda') or []) if isinstance(r, dict)]
291
+ if explicit:
292
+ rows = []
293
+ for r in explicit:
294
+ start = str(r.get('start') or r.get('time') or '').strip()
295
+ end = str(r.get('end') or '').strip()
296
+ rows.append(_agenda_row(
297
+ start, end,
298
+ str(r.get('item') or r.get('name') or '').strip(),
299
+ str(r.get('activity') or '').strip(),
300
+ str(r.get('place') or r.get('venue') or '').strip(),
301
+ str(r.get('person') or '').strip(),
302
+ str(r.get('remark') or '').strip(),
303
+ ))
304
+ return rows
305
+
306
+ base = _parse_hm(d.get('agendaStart')) or _parse_hm(DEFAULT_START)
307
+ demand = str(d.get('demand') or '').strip()
308
+ rows = []
309
+ for name, off, dur, act in STANDARD_AGENDA:
310
+ start, end = _hm(base + off), _hm(base + off + dur)
311
+ if name == '方案介绍':
312
+ act = act or (demand or '泛微数字化运营平台整体方案介绍')
313
+ row = _agenda_row(start, end, name, act, venue if name == '公司参观' else room)
314
+ row['dur'] = dur
315
+ rows.append(row)
316
+
317
+ # 真实行程里已有对应环节时,用客户的实际时间/地点/人员覆盖标准环节,
318
+ # 保证输出恒为「公司参观—方案介绍—讨论交流」三段,但时间贴合实际。
319
+ alias = (
320
+ ('公司参观', ('参观', '展厅', '走访')),
321
+ ('方案介绍', ('介绍', '演示', '讲解', '汇报', 'PPT', 'ppt', '方案')),
322
+ ('讨论交流', ('交流', '讨论', '答疑', '座谈', '洽谈', '沟通')),
323
+ )
324
+ for r in norm_schedule(d):
325
+ blob = ' '.join([str(r.get('item') or ''), str(r.get('activity') or '')])
326
+ if is_logistics(blob):
327
+ continue
328
+ t = str(r.get('time') or '').strip()
329
+ parts = [p for p in re.split(r'\s*[-—~至到]+\s*', t) if p.strip()]
330
+ st = parts[0].strip() if parts else ''
331
+ en = parts[1].strip() if len(parts) >= 2 else ''
332
+ for idx, (nm, keys) in enumerate(alias):
333
+ if any(k in blob for k in keys):
334
+ row = rows[idx]
335
+ if st:
336
+ if not en:
337
+ _s = _parse_hm(st)
338
+ en = _hm(_s + int(row.get('dur') or 45)) if _s is not None else ''
339
+ row['start'], row['end'] = st, en
340
+ row['time'] = f'{st}-{en}' if en else st
341
+ if r.get('place'):
342
+ row['place'] = r.get('place')
343
+ if r.get('person'):
344
+ row['person'] = r.get('person')
345
+ if r.get('activity') and not row['activity']:
346
+ row['activity'] = r.get('activity')
347
+ break
348
+
349
+ prev_end = None
350
+ for row in rows:
351
+ st = _parse_hm(row.get('start'))
352
+ if prev_end is not None and st is not None and st < prev_end:
353
+ st = prev_end
354
+ row['start'] = _hm(st)
355
+ row['end'] = _hm(st + int(row.get('dur') or 45))
356
+ row['time'] = f"{row['start']}-{row['end']}"
357
+ en = _parse_hm(row.get('end'))
358
+ if en is None and st is not None:
359
+ en = st + int(row.get('dur') or 45)
360
+ row['end'] = _hm(en)
361
+ row['time'] = f"{row['start']}-{row['end']}"
362
+ if en is not None:
363
+ prev_end = en if prev_end is None else max(prev_end, en)
364
+ for row in rows:
365
+ row.pop('dur', None)
366
+ return rows
367
+
368
+
369
+ MOBILE_RE = re.compile(r'^1[3-9]\d{9}$')
370
+
371
+
372
+ def _mobile_of(x):
373
+ """v4.10:只取手机号(11 位)。座机 telephone、脱敏串一律不取、不回退。"""
374
+ if not isinstance(x, dict):
375
+ return ''
376
+ for k in ('mobile', 'mobile_plain', 'cellphone', 'phone_mobile', '手机号'):
377
+ v = str(x.get(k) or '').strip()
378
+ if not v or 'desensiti' in v.lower():
379
+ continue
380
+ v = re.sub(r'[\s-]', '', v)
381
+ if MOBILE_RE.match(v):
382
+ return v
383
+ return ''
384
+
385
+
386
+ def norm_companions(d):
387
+ """陪同人员归一:[{name, phone}]。
388
+
389
+ v4.10 口径:phone 只认手机号(11 位)。座机(telephone)不再作为兜底,
390
+ 取不到手机号就只写姓名,对外件不出现内部口径。
391
+ """
392
+ out = []
393
+ for x in (d.get('companions') or []):
394
+ if isinstance(x, dict):
395
+ nm = str(x.get('name') or x.get('text') or '').strip()
396
+ tel = _mobile_of(x)
397
+ else:
398
+ s = str(x or '').strip()
399
+ nm, tel = s, ''
400
+ m = re.search(r'[((]([^(())]*)[))]', s)
401
+ if m:
402
+ inner = m.group(1).strip()
403
+ # 只有「11 位手机号」的括注才当电话;"张三(SH)" 这类机构后缀保留原名
404
+ if MOBILE_RE.match(re.sub(r'[\s-]', '', inner)):
405
+ tel = re.sub(r'[\s-]', '', inner)
406
+ nm = (s[:m.start()] + s[m.end():]).strip()
407
+ if nm:
408
+ out.append({'name': nm, 'phone': tel})
409
+ return out
410
+
411
+
412
+ def contact_line(d):
413
+ """接待人员展示串:姓名(电话);无电话只写姓名,不写「待补」。"""
414
+ parts = []
415
+ for c in norm_companions(d):
416
+ parts.append(f"{c['name']}({c['phone']})" if c['phone'] else c['name'])
417
+ if parts:
418
+ return '、'.join(parts)
419
+ return str(d.get('contact') or '').strip()
420
+
421
+
422
+ def sched_cells(row):
423
+ """议程行 -> 对外行程单/内部方案的三列表格(时间 | 安排 | 地点)。"""
424
+ t = row.get('time') or ''
425
+ item = row.get('item') or ''
426
+ act = row.get('activity') or ''
427
+ main = item if not act else (f'{item}:{act}' if item else act)
428
+ return [t, main, row.get('place') or '']
429
+
430
+
431
+ def build_docx(d, out_path):
432
+ os.makedirs(os.path.dirname(out_path) or '.', exist_ok=True)
433
+ prepare_target(out_path)
434
+ # 关键:copyfile 不复制 444 权限位(用 shutil.copy 会把只读位一起带过去)
435
+ shutil.copyfile(TPL, out_path)
436
+ safe_write(out_path)
437
+
438
+ doc = docx.Document(out_path)
439
+ customer = d.get('customer', '')
440
+ visit_date = d.get('visitDate', '')
441
+ venue = d.get('venue') or '泛微网络 上海总部'
442
+
443
+ cleaned = []
444
+
445
+ def ext_track(field, raw):
446
+ val = ext(raw)
447
+ if str(raw or '').strip() != val:
448
+ cleaned.append(f'{field}: {raw} -> {val or "(不写)"}')
449
+ return val
450
+
451
+ venue = ext_track('参观地点', venue)
452
+ fill_para(doc, '参观时间', f'参观时间:{cn_date(visit_date)}')
453
+ fill_para(doc, '参观地点', f'参观地点:{venue}')
454
+ fill_para(doc, '莅临领导', f'莅临领导:贵司各位来宾(共 {ppl(d.get("headcount"))} 人)' if d.get('headcount') else '莅临领导:贵司各位来宾')
455
+ contact_ext = ext_track('接待人员', contact_line(d) or '泛微接待团队')
456
+ fill_para(doc, '接待人员', f'接待人员:{contact_ext}')
457
+ if visit_date:
458
+ fill_para(doc, '参观行程安排', f'{cn_date(visit_date).split("(")[0]}参观行程安排:')
459
+
460
+ schedule = [sched_cells(r) for r in norm_agenda(d)]
461
+ if doc.tables and schedule:
462
+ t = doc.tables[0]
463
+ resize_table(t, len(schedule))
464
+ for i, row in enumerate(schedule, start=1):
465
+ cells = t.rows[i].cells
466
+ for ci, (cell, val) in enumerate(zip(cells, list(row) + ['', '', ''])):
467
+ ps = cell.paragraphs
468
+ txt = '' if val is None else str(val)
469
+ # 地点列(第 3 列)与任何含内部口径的单元格统一走对外口径
470
+ if ci == 2:
471
+ txt = ext_track('行程地点', txt)
472
+ elif has_mark(txt):
473
+ txt = ext_track('行程安排', txt)
474
+ set_para(ps[0], txt)
475
+ for extra in ps[1:]:
476
+ set_para(extra, '')
477
+
478
+ doc.add_paragraph('具体时间安排以现场为准;如有调整,我们将第一时间与贵司沟通。')
479
+ doc.save(out_path)
480
+ safe_write(out_path)
481
+ qa = scan_docx(out_path)
482
+ qa['cleaned'] = cleaned
483
+ return out_path, qa
484
+
485
+
486
+ def norm_cases(d):
487
+ """案例参考:兼容字符串 / 对象 / {items|list} 三种写法,字段名给多个别名。
488
+ 只取能落到表格的内容;空则整段不出(不写"暂无案例")。"""
489
+ raw = d.get('cases') or []
490
+ if isinstance(raw, dict):
491
+ raw = raw.get('items') or raw.get('list') or raw.get('cases') or []
492
+ if not isinstance(raw, list):
493
+ return []
494
+ out = []
495
+ for c in raw:
496
+ if isinstance(c, str):
497
+ s = c.strip()
498
+ if s:
499
+ out.append({'title': s, 'relevance': '', 'date': ''})
500
+ elif isinstance(c, dict):
501
+ title = str(c.get('title') or c.get('material') or c.get('name') or '').strip()
502
+ rel = str(c.get('relevance') or c.get('point') or c.get('why') or '').strip()
503
+ date = str(c.get('date') or c.get('time') or c.get('when') or '').strip()
504
+ if title or rel:
505
+ out.append({'title': title, 'relevance': rel, 'date': date})
506
+ return out
507
+
508
+
509
+ def norm_experts(d):
510
+ """专家参考:兼容字符串 / 对象 / {items|list},字段名给多个别名。
511
+ 只取能落到表格的内容;空则整段不出。"""
512
+ raw = d.get('experts') or []
513
+ if isinstance(raw, dict):
514
+ raw = raw.get('items') or raw.get('list') or raw.get('experts') or []
515
+ if not isinstance(raw, list):
516
+ return []
517
+ out = []
518
+ for e in raw:
519
+ if isinstance(e, str):
520
+ s = e.strip()
521
+ if s:
522
+ out.append({'name': s, 'dept': '', 'relevance': ''})
523
+ elif isinstance(e, dict):
524
+ name = str(e.get('name') or e.get('expert') or e.get('person') or '').strip()
525
+ dept = str(e.get('dept') or e.get('department') or e.get('role') or e.get('title') or '').strip()
526
+ rel = str(e.get('relevance') or e.get('point') or e.get('match') or e.get('why') or '').strip()
527
+ if name or dept or rel:
528
+ out.append({'name': name, 'dept': dept, 'relevance': rel})
529
+ return out
530
+
531
+
532
+ def _cell(s):
533
+ """表格单元格:竖线会截断表格,换行会断行,统一压平。"""
534
+ return str(s or '').replace('|', '/').replace('\n', ' ').strip() or '—'
535
+
536
+
537
+ _CJK_NUM = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二']
538
+
539
+
540
+ def build_md(d, out_path):
541
+ os.makedirs(os.path.dirname(out_path) or '.', exist_ok=True)
542
+ prepare_target(out_path)
543
+ L = []
544
+ A = L.append
545
+ _n = [0]
546
+
547
+ def sec(t):
548
+ """章节号自增:中间插章节时无需手改后面所有编号。"""
549
+ _n[0] += 1
550
+ return f'## {_CJK_NUM[_n[0] - 1]}、{t}\n'
551
+
552
+ A(f'# 客户接待交流参考文档(内部)\n')
553
+ A(f'> 编制日期:{datetime.date.today().isoformat()} | 流程:泛微客户参观接待流程(草稿,待发起) | 内部文件,未经许可不得外发\n')
554
+
555
+ A(sec('客户与来访信息'))
556
+ A('| 项目 | 内容 |')
557
+ A('| --- | --- |')
558
+ A(f'| 来访客户 | {d.get("customer", "待补")} |')
559
+ A(f'| 来访人数 | {ppl(d.get("headcount", "待补"))} 人 |' if d.get('headcount') else '| 来访人数 | 待补 |')
560
+ A(f'| 客户带队人 / 来访名单 | {d.get("visitors") or "待补"} |')
561
+ A(f'| 客户性质 | {d.get("nature") or "待补(流程必填项,请在界面选择)"} |')
562
+ A(f'| 参观日期 | {cn_date(d.get("visitDate")) or "待补"} |')
563
+ A(f'| 参观类型 | {d.get("visitType") or "待补"} |')
564
+ A(f'| 客户需求 | {d.get("demand") or "待补"} |')
565
+ A(f'| 主联络人 | {d.get("contact") or "待补"} |')
566
+ A(f'| 项目金额 | {d.get("amount") or "待补(不在本方案中估算)"} |')
567
+ A('')
568
+
569
+ A(sec('接待目标'))
570
+ A('1. 向来访客户完整展示泛微上海总部办公环境、产品与数智化能力,建立直观认知。')
571
+ A('2. 围绕商务合作模式与技术实现路径开展双向沟通,明确客户关注点与后续推进节奏。')
572
+ A('3. 通过规范、有温度的接待流程,强化客户对泛微交付能力与服务体系的信任。\n')
573
+
574
+ # 案例参考:仅当有搜索结果时成章(软依赖,取不到就整段省略)
575
+ cases = norm_cases(d)
576
+ if cases:
577
+ A(sec('相关案例参考'))
578
+ note = str(d.get('casesNote') or '').strip()
579
+ if note:
580
+ A(f'> {note}\n')
581
+ A('| 材料 | 与本次拜访的关联 | 时间 |')
582
+ A('| --- | --- | --- |')
583
+ for c in cases:
584
+ A(f'| {_cell(c["title"])} | {_cell(c["relevance"])} | {_cell(c["date"])} |')
585
+ A('')
586
+
587
+ # 专家参考:同样软依赖,没有就整段省略
588
+ experts = norm_experts(d)
589
+ if experts:
590
+ A(sec('相关专家参考'))
591
+ enote = str(d.get('expertsNote') or '').strip()
592
+ if enote:
593
+ A(f'> {enote}\n')
594
+ A('| 专家 | 部门 / 岗位 | 与本次需求的匹配点 |')
595
+ A('| --- | --- | --- |')
596
+ for e in experts:
597
+ A(f'| {_cell(e["name"])} | {_cell(e["dept"])} | {_cell(e["relevance"])} |')
598
+ A('')
599
+
600
+ A(sec(f'日程安排({d.get("visitDate", "")})'))
601
+ A('| 时段 | 安排 | 地点 |')
602
+ A('| --- | --- | --- |')
603
+ for row in [sched_cells(r) for r in norm_agenda(d)]:
604
+ r = list(row) + ['', '', '']
605
+ A(f'| {r[0]} | {r[1]} | {r[2]} |')
606
+ A('\n> 各环节具体起止时间待与客户最终确认;接送与用车安排未落实时需在行程确认后同步客户。\n')
607
+
608
+ A(sec('人员分工'))
609
+ A('| 角色 | 人员 | 职责 |')
610
+ A('| --- | --- | --- |')
611
+ A(f'| 主联络人 / 全程陪同 | {contact_line(d) or "待定"} | 接待总协调,全程陪同参观,客户沟通对接 |')
612
+ A('| 商务线条 | 待定 | 商务合作模式沟通、报价与合同口径 |')
613
+ A('| 技术线条 | 待定 | 技术方案讲解、客户技术疑问应答 |')
614
+ A('| 会务支持 | 待定 | 场地、餐饮、物料、字幕与签到准备 |\n')
615
+ A('> 是否需公司高层参与,尚未表态的,建议在客户层级明确后再定。\n')
616
+
617
+ A(sec('食宿与用车'))
618
+ hc = num(d.get('headcount'))
619
+ comp = len(d.get('companions') or [])
620
+ meal_hc = d.get('mealHeadcount') or ((hc + comp) if (hc or comp) else '')
621
+ cust_hc = ppl(d.get('headcount'))
622
+ A(f'- **用餐**:形式为{d.get("meal") or "待定"};用餐人数 {ppl(meal_hc) or "待定"}(客户 {cust_hc + " 人" if cust_hc else "人数待补"} + 陪同 {comp} 人,可调整);用餐档次需在流程界面按实际情况选择。')
623
+ A(f'- **住宿**:{d.get("hotel") or "待定"}。')
624
+ A(f'- **接送 / 用车**:{d.get("pickup") or "暂未确定,需补充接机时间、地点、车型与数量、送机安排"}。')
625
+ A(f'- **伴手礼**:{d.get("gift") or "待定"}。\n')
626
+
627
+ A(sec('会议与会务'))
628
+ A(f'- 场地:{d.get("meetingRoom") or "总部129/130/131会议室(按人数择一)"}(按实际人数预留,建议提前 1 天确认可用)。')
629
+ A(f'- 欢迎字幕:欢迎{d.get("customer", "")}莅临指导。')
630
+ A('- 会务物料:公司介绍资料、方案材料、演示环境、席位牌、签到表(待准备)。')
631
+ A('- 演示准备:提前调试演示环境与投屏,准备商务洽谈与技术交流对应的介绍材料。\n')
632
+
633
+ A(sec('应急预案'))
634
+ A('- 客户行程变更:由主联络人第一时间同步会务支持调整场地、餐饮与人员安排。')
635
+ A('- 关键人员临时缺席:由同线条备份人员顶替,确保商务与技术口径均有对应人负责。')
636
+ A('- 设备 / 演示故障:准备离线材料与备份设备,必要时改用文档讲解。')
637
+ A('- 用餐与场地冲突:提前确认餐厅与会议室备用方案。\n')
638
+
639
+ A(sec('待确认事项'))
640
+ todo = d.get('todo') or []
641
+ if todo:
642
+ for i, t in enumerate(todo, start=1):
643
+ A(f'{i}. {t}')
644
+ else:
645
+ A('无')
646
+ A('')
647
+
648
+ with open(out_path, 'w', encoding='utf-8') as f:
649
+ f.write('\n'.join(L))
650
+ safe_write(out_path)
651
+ return out_path
652
+
653
+
654
+ def main():
655
+ ap = argparse.ArgumentParser()
656
+ ap.add_argument('--data', required=True, help='接待信息 JSON 文件')
657
+ ap.add_argument('--out-dir', default='/workspace/files')
658
+ ap.add_argument('--only', choices=['docx', 'md'], help='只生成其中一份')
659
+ ap.add_argument('--docx-name', default='客户接待行程单.docx')
660
+ ap.add_argument('--md-name', default='接待交流参考文档.md')
661
+ a = ap.parse_args()
662
+
663
+ with open(a.data, encoding='utf-8') as f:
664
+ d = json.load(f)
665
+
666
+ res = {'ok': True, 'files': [], 'qa': {}}
667
+ # v4.4:verify 统计随渲染结果一起回传,供 e10.mjs 组装「可核验证据」,
668
+ # 让上层不必 cat / 重读产物就能确认「文件渲染对了」(省一整批往返)
669
+ verify = {}
670
+ if a.only != 'md':
671
+ if docx is None:
672
+ res.update(ok=False, error='缺少 python-docx,请先安装:pip install python-docx')
673
+ print(json.dumps(res, ensure_ascii=False))
674
+ return 1
675
+ if not os.path.exists(TPL):
676
+ res.update(ok=False, error='内置模板缺失: assets/行程单模板-泛微.docx')
677
+ print(json.dumps(res, ensure_ascii=False))
678
+ return 1
679
+ p, docx_qa = build_docx(d, os.path.join(a.out_dir, a.docx_name))
680
+ res['files'].append({'kind': 'docx', 'path': p, 'size': os.path.getsize(p), 'audience': 'customer'})
681
+ res['qa']['external'] = docx_qa
682
+ verify['docxParagraphs'] = docx_qa.get('paragraphs', 0)
683
+ verify['docxSha256'] = sha8(p)
684
+ verify['externalLeaks'] = docx_qa.get('externalLeaks', 0)
685
+ if docx_qa.get('cleaned'):
686
+ verify['cleaned'] = docx_qa['cleaned']
687
+ warn = list(res['qa'].get('warnings') or [])
688
+ if docx_qa.get('externalLeaks'):
689
+ warn.append(f'对外行程单仍含内部口径 {docx_qa["externalLeaks"]} 处,请检查')
690
+ if warn:
691
+ res['qa']['warnings'] = warn
692
+ if a.only != 'docx':
693
+ p = build_md(d, os.path.join(a.out_dir, a.md_name))
694
+ res['files'].append({'kind': 'md', 'path': p, 'size': os.path.getsize(p), 'audience': 'internal'})
695
+ try:
696
+ with open(p, encoding='utf-8') as f:
697
+ secs = [ln.strip() for ln in f.read().splitlines() if ln.startswith('## ')]
698
+ except Exception:
699
+ secs = []
700
+ verify['mdSections'] = len(secs)
701
+ verify['mdHead'] = secs[0] if secs else ''
702
+ verify['mdTail'] = secs[-1] if secs else ''
703
+ verify['mdSha256'] = sha8(p)
704
+
705
+ # v4.7:把日程行结构化输出,供流程【日程明细】子表直接使用
706
+ agenda_rows = norm_agenda(d)
707
+ res['agendaRows'] = agenda_rows
708
+ res['scheduleRows'] = [{
709
+ 'date': d.get('visitDate') or '',
710
+ 'time': r.get('start') or '',
711
+ 'item': r.get('item') or '',
712
+ 'place': r.get('place') or '',
713
+ 'person': r.get('person') or '',
714
+ 'activity': r.get('activity') or '',
715
+ 'remark': r.get('remark') or '',
716
+ } for r in agenda_rows]
717
+ verify['fileCount'] = len(res['files'])
718
+ res['verify'] = verify
719
+ print(json.dumps(res, ensure_ascii=False))
720
+ return 0
721
+
722
+
723
+ if __name__ == '__main__':
724
+ sys.exit(main())