@yss123/cage-cli 0.2.0 → 0.3.0

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 (607) hide show
  1. package/README.md +47 -3
  2. package/bin/cage.js +5 -0
  3. package/bin/create-cage-app.js +5 -0
  4. package/dist/analyze.d.ts +16 -0
  5. package/dist/analyze.js +18 -2
  6. package/dist/analyze.js.map +1 -1
  7. package/dist/baseline.d.ts +8 -0
  8. package/dist/baseline.js +13 -0
  9. package/dist/baseline.js.map +1 -1
  10. package/dist/bootstrap.d.ts +20 -0
  11. package/dist/bootstrap.js +75 -0
  12. package/dist/bootstrap.js.map +1 -0
  13. package/dist/budget.d.ts +7 -0
  14. package/dist/budget.js +49 -5
  15. package/dist/budget.js.map +1 -1
  16. package/dist/capabilities.d.ts +38 -0
  17. package/dist/capabilities.js +133 -0
  18. package/dist/capabilities.js.map +1 -0
  19. package/dist/config.d.ts +31 -2
  20. package/dist/config.js +22 -0
  21. package/dist/config.js.map +1 -1
  22. package/dist/context.d.ts +14 -0
  23. package/dist/context.js +35 -2
  24. package/dist/context.js.map +1 -1
  25. package/dist/create-prompt.d.ts +7 -0
  26. package/dist/create-prompt.js +12 -0
  27. package/dist/create-prompt.js.map +1 -1
  28. package/dist/create.d.ts +21 -1
  29. package/dist/create.js +23 -1
  30. package/dist/create.js.map +1 -1
  31. package/dist/derive.d.ts +23 -0
  32. package/dist/derive.js +40 -0
  33. package/dist/derive.js.map +1 -1
  34. package/dist/dev.d.ts +6 -0
  35. package/dist/dev.js +11 -0
  36. package/dist/dev.js.map +1 -1
  37. package/dist/doctor.d.ts +98 -0
  38. package/dist/doctor.js +93 -0
  39. package/dist/doctor.js.map +1 -0
  40. package/dist/env.d.ts +6 -0
  41. package/dist/env.js +11 -0
  42. package/dist/env.js.map +1 -1
  43. package/dist/findings.d.ts +27 -0
  44. package/dist/findings.js +20 -0
  45. package/dist/findings.js.map +1 -1
  46. package/dist/gen/contracts.d.ts +28 -0
  47. package/dist/gen/contracts.js +52 -12
  48. package/dist/gen/contracts.js.map +1 -1
  49. package/dist/gen/index.d.ts +26 -0
  50. package/dist/gen/index.js +69 -1
  51. package/dist/gen/index.js.map +1 -1
  52. package/dist/gen/zod-code.d.ts +42 -0
  53. package/dist/gen/zod-code.js +178 -16
  54. package/dist/gen/zod-code.js.map +1 -1
  55. package/dist/graph-approvals.d.ts +60 -0
  56. package/dist/graph-approvals.js +80 -0
  57. package/dist/graph-approvals.js.map +1 -0
  58. package/dist/graph-business.d.ts +135 -0
  59. package/dist/graph-business.js +404 -0
  60. package/dist/graph-business.js.map +1 -0
  61. package/dist/graph-command.d.ts +17 -0
  62. package/dist/graph-command.js +21 -0
  63. package/dist/graph-command.js.map +1 -1
  64. package/dist/graph-model.d.ts +44 -0
  65. package/dist/graph-model.js +36 -3
  66. package/dist/graph-model.js.map +1 -1
  67. package/dist/graph-presentation.d.ts +16 -0
  68. package/dist/graph-presentation.js +10 -1
  69. package/dist/graph-presentation.js.map +1 -1
  70. package/dist/graph-query.d.ts +95 -0
  71. package/dist/graph-query.js +62 -0
  72. package/dist/graph-query.js.map +1 -1
  73. package/dist/graph-relations.d.ts +20 -0
  74. package/dist/graph-relations.js +34 -4
  75. package/dist/graph-relations.js.map +1 -1
  76. package/dist/graph-search.d.ts +35 -0
  77. package/dist/graph-search.js +36 -0
  78. package/dist/graph-search.js.map +1 -1
  79. package/dist/graph-snapshot.d.ts +26 -0
  80. package/dist/graph-snapshot.js +30 -1
  81. package/dist/graph-snapshot.js.map +1 -1
  82. package/dist/graph.d.ts +13 -2
  83. package/dist/graph.js +59 -4
  84. package/dist/graph.js.map +1 -1
  85. package/dist/impact.d.ts +50 -0
  86. package/dist/impact.js +62 -2
  87. package/dist/impact.js.map +1 -1
  88. package/dist/index.d.ts +10 -0
  89. package/dist/index.js +10 -0
  90. package/dist/index.js.map +1 -1
  91. package/dist/init.d.ts +12 -0
  92. package/dist/init.js +15 -0
  93. package/dist/init.js.map +1 -1
  94. package/dist/load.d.ts +10 -0
  95. package/dist/load.js +15 -0
  96. package/dist/load.js.map +1 -1
  97. package/dist/main.d.ts +6 -0
  98. package/dist/main.js +93 -5
  99. package/dist/main.js.map +1 -1
  100. package/dist/migrate.d.ts +12 -0
  101. package/dist/migrate.js +17 -0
  102. package/dist/migrate.js.map +1 -1
  103. package/dist/ontology.d.ts +67 -2
  104. package/dist/ontology.js +89 -2
  105. package/dist/ontology.js.map +1 -1
  106. package/dist/process-rules.d.ts +21 -0
  107. package/dist/process-rules.js +100 -0
  108. package/dist/process-rules.js.map +1 -0
  109. package/dist/process.d.ts +32 -0
  110. package/dist/process.js +32 -0
  111. package/dist/process.js.map +1 -1
  112. package/dist/project-structure.d.ts +5 -0
  113. package/dist/project-structure.js +10 -0
  114. package/dist/project-structure.js.map +1 -1
  115. package/dist/registration.d.ts +16 -0
  116. package/dist/registration.js +56 -0
  117. package/dist/registration.js.map +1 -0
  118. package/dist/rules.d.ts +52 -0
  119. package/dist/rules.js +58 -0
  120. package/dist/rules.js.map +1 -1
  121. package/dist/runtime-diagnostics.d.ts +27 -0
  122. package/dist/runtime-diagnostics.js +60 -0
  123. package/dist/runtime-diagnostics.js.map +1 -0
  124. package/dist/snapshots.d.ts +40 -0
  125. package/dist/snapshots.js +62 -0
  126. package/dist/snapshots.js.map +1 -0
  127. package/dist/static-check.d.ts +33 -0
  128. package/dist/static-check.js +37 -1
  129. package/dist/static-check.js.map +1 -1
  130. package/dist/sync.d.ts +11 -0
  131. package/dist/sync.js +65 -8
  132. package/dist/sync.js.map +1 -1
  133. package/dist/upgrade.d.ts +16 -0
  134. package/dist/upgrade.js +21 -0
  135. package/dist/upgrade.js.map +1 -1
  136. package/dist/verify.d.ts +14 -0
  137. package/dist/verify.js +19 -0
  138. package/dist/verify.js.map +1 -1
  139. package/dist/version.js +5 -0
  140. package/dist/version.js.map +1 -1
  141. package/graph-ui/app.js +321 -27
  142. package/graph-ui/approval-flow.js +165 -0
  143. package/graph-ui/business.css +985 -0
  144. package/graph-ui/business.js +549 -0
  145. package/graph-ui/flowchart-interaction.js +177 -0
  146. package/graph-ui/flowchart.js +1059 -0
  147. package/graph-ui/graph-approvals.js +79 -0
  148. package/graph-ui/graph-business.js +403 -0
  149. package/graph-ui/graph-model.js +36 -3
  150. package/graph-ui/graph-relations.js +34 -4
  151. package/graph-ui/graph-search.js +36 -0
  152. package/graph-ui/index.html +26 -12
  153. package/graph-ui/model.js +28 -0
  154. package/graph-ui/relations.js +4 -0
  155. package/graph-ui/structure.js +44 -0
  156. package/graph-ui/style.css +12 -0
  157. package/package.json +6 -4
  158. package/templates/app/.dockerignore +2 -0
  159. package/templates/app/.env.example +10 -0
  160. package/templates/app/AGENTS.md +49 -9
  161. package/templates/app/README.md +4 -1
  162. package/templates/app/_gitignore +1 -0
  163. package/templates/app/apps/api/package.json +2 -2
  164. package/templates/app/apps/api/src/main.ts +5 -1
  165. package/templates/app/apps/api/src/worker.ts +3 -0
  166. package/templates/app/apps/web/index.html +1 -0
  167. package/templates/app/apps/web/package.json +7 -3
  168. package/templates/app/apps/web/src/app/app.tsx +122 -12
  169. package/templates/app/apps/web/src/app/styles/global.css +88 -8
  170. package/templates/app/apps/web/src/app/use-session.ts +43 -0
  171. package/templates/app/apps/web/src/app/workspace-layout.tsx +58 -19
  172. package/templates/app/apps/web/src/main.tsx +5 -0
  173. package/templates/app/apps/web/src/modules/approval/hooks/use-approval-tasks.ts +11 -0
  174. package/templates/app/apps/web/src/modules/approval/index.ts +4 -0
  175. package/templates/app/apps/web/src/modules/approval/pages/approval-tasks-page.tsx +20 -1
  176. package/templates/app/apps/web/src/modules/auth/index.ts +4 -0
  177. package/templates/app/apps/web/src/modules/auth/pages/login-page.tsx +12 -0
  178. package/templates/app/apps/web/src/modules/inventory/index.ts +4 -0
  179. package/templates/app/apps/web/src/modules/inventory/pages/inventory-page.tsx +29 -1
  180. package/templates/app/apps/web/src/modules/purchase/components/approval-history.tsx +32 -0
  181. package/templates/app/apps/web/src/modules/purchase/components/order-attachments.tsx +29 -0
  182. package/templates/app/apps/web/src/modules/purchase/components/purchase-assistant-context.tsx +17 -0
  183. package/templates/app/apps/web/src/modules/purchase/components/purchase-order-form.css +6 -0
  184. package/templates/app/apps/web/src/modules/purchase/components/purchase-order-form.tsx +25 -3
  185. package/templates/app/apps/web/src/modules/purchase/index.ts +5 -0
  186. package/templates/app/apps/web/src/modules/purchase/lib/presentation.ts +20 -0
  187. package/templates/app/apps/web/src/modules/purchase/pages/purchase-intelligence.css +15 -0
  188. package/templates/app/apps/web/src/modules/purchase/pages/purchase-order-detail-page.tsx +154 -0
  189. package/templates/app/apps/web/src/modules/purchase/pages/purchase-orders-page.tsx +52 -22
  190. package/templates/app/apps/web/src/modules/workspace/index.ts +5 -0
  191. package/templates/app/apps/web/src/modules/workspace/pages/home-page.tsx +44 -0
  192. package/templates/app/apps/web/src/shared/hooks/use-command.ts +13 -0
  193. package/templates/app/apps/web/src/shared/lib/error-message.ts +9 -0
  194. package/templates/app/apps/web/src/shared/lib/navigation.ts +21 -0
  195. package/templates/app/apps/web/src/shared/ui/assistant-markdown.tsx +19 -0
  196. package/templates/app/apps/web/src/shared/ui/assistant-panel.css +134 -0
  197. package/templates/app/apps/web/src/shared/ui/assistant-panel.tsx +200 -0
  198. package/templates/app/apps/web/src/shared/ui/assistant-scope.tsx +72 -0
  199. package/templates/app/apps/web/src/shared/ui/attachment-upload.css +28 -0
  200. package/templates/app/apps/web/src/shared/ui/attachment-upload.tsx +163 -0
  201. package/templates/app/apps/web/src/shared/ui/notice.tsx +7 -0
  202. package/templates/app/apps/web/src/shared/ui/page-heading.tsx +7 -0
  203. package/templates/app/apps/web/src/shared/ui/page-state.css +47 -0
  204. package/templates/app/apps/web/src/shared/ui/page-state.tsx +76 -0
  205. package/templates/app/apps/web/src/shared/ui/require-capability.tsx +34 -0
  206. package/templates/app/apps/web/vite.config.ts +5 -0
  207. package/templates/app/cage.config.json +9 -0
  208. package/templates/app/db/migrations/0002_draft.sql +12 -0
  209. package/templates/app/db/migrations/0003_draft.sql +8 -0
  210. package/templates/app/deploy/nginx.conf +52 -0
  211. package/templates/app/docs/ai/README.md +21 -0
  212. package/templates/app/docs/ai/architecture.md +26 -0
  213. package/templates/app/docs/ai/commenting.md +203 -0
  214. package/templates/app/docs/ai/diagnostics.md +80 -0
  215. package/templates/app/docs/ai/files.md +93 -0
  216. package/templates/app/docs/ai/intelligence.md +348 -0
  217. package/templates/app/docs/ai/ontology-context.md +59 -4
  218. package/templates/app/docs/ai/primitives.md +33 -0
  219. package/templates/app/docs/ai/project-structure.md +8 -3
  220. package/templates/app/docs/ai/purchase-example.md +16 -2
  221. package/templates/app/docs/ai/recipes.md +9 -1
  222. package/templates/app/docs/ai/routing.md +86 -0
  223. package/templates/app/docs/ai/troubleshooting.md +5 -0
  224. package/templates/app/docs/ai/workflow.md +24 -11
  225. package/templates/app/docs/errors/CAGE-AI-001.md +61 -0
  226. package/templates/app/docs/errors/CAGE-APPR-001.md +7 -6
  227. package/templates/app/docs/errors/CAGE-APPR-002.md +2 -2
  228. package/templates/app/docs/errors/CAGE-APPR-003.md +1 -1
  229. package/templates/app/docs/errors/CAGE-APPR-004.md +4 -4
  230. package/templates/app/docs/errors/CAGE-APPR-005.md +1 -1
  231. package/templates/app/docs/errors/CAGE-APPR-006.md +12 -6
  232. package/templates/app/docs/errors/CAGE-APPR-007.md +3 -3
  233. package/templates/app/docs/errors/CAGE-APPR-010.md +5 -5
  234. package/templates/app/docs/errors/CAGE-AUDIT-001.md +53 -0
  235. package/templates/app/docs/errors/CAGE-AUTH-001.md +1 -1
  236. package/templates/app/docs/errors/CAGE-BIZ-001.md +51 -0
  237. package/templates/app/docs/errors/CAGE-BIZ-002.md +49 -0
  238. package/templates/app/docs/errors/CAGE-BUDGET-001.md +1 -1
  239. package/templates/app/docs/errors/CAGE-BUDGET-002.md +1 -1
  240. package/templates/app/docs/errors/CAGE-BUDGET-003.md +1 -1
  241. package/templates/app/docs/errors/CAGE-CMD-002.md +1 -1
  242. package/templates/app/docs/errors/CAGE-CMD-003.md +1 -1
  243. package/templates/app/docs/errors/CAGE-CONN-001.md +3 -3
  244. package/templates/app/docs/errors/CAGE-CONN-002.md +1 -1
  245. package/templates/app/docs/errors/CAGE-CONN-003.md +1 -1
  246. package/templates/app/docs/errors/CAGE-CONN-004.md +1 -1
  247. package/templates/app/docs/errors/CAGE-CONN-005.md +1 -1
  248. package/templates/app/docs/errors/CAGE-CONN-006.md +1 -1
  249. package/templates/app/docs/errors/CAGE-CONN-007.md +6 -6
  250. package/templates/app/docs/errors/CAGE-CONN-008.md +5 -5
  251. package/templates/app/docs/errors/CAGE-CONN-009.md +6 -6
  252. package/templates/app/docs/errors/CAGE-CONN-010.md +6 -6
  253. package/templates/app/docs/errors/CAGE-CONN-011.md +1 -1
  254. package/templates/app/docs/errors/CAGE-CONN-012.md +1 -1
  255. package/templates/app/docs/errors/CAGE-CONN-013.md +49 -0
  256. package/templates/app/docs/errors/CAGE-CONN-014.md +48 -0
  257. package/templates/app/docs/errors/CAGE-CONN-015.md +49 -0
  258. package/templates/app/docs/errors/CAGE-CREATE-001.md +10 -9
  259. package/templates/app/docs/errors/CAGE-DECL-001.md +2 -2
  260. package/templates/app/docs/errors/CAGE-DECL-002.md +7 -6
  261. package/templates/app/docs/errors/CAGE-DECL-003.md +1 -1
  262. package/templates/app/docs/errors/CAGE-DECL-004.md +1 -1
  263. package/templates/app/docs/errors/CAGE-DEP-001.md +2 -2
  264. package/templates/app/docs/errors/CAGE-DEP-002.md +1 -1
  265. package/templates/app/docs/errors/CAGE-DEP-003.md +2 -2
  266. package/templates/app/docs/errors/CAGE-DEP-004.md +1 -1
  267. package/templates/app/docs/errors/CAGE-DEP-005.md +1 -1
  268. package/templates/app/docs/errors/CAGE-DIAG-001.md +53 -0
  269. package/templates/app/docs/errors/CAGE-DLQ-001.md +2 -2
  270. package/templates/app/docs/errors/CAGE-ENV-001.md +4 -4
  271. package/templates/app/docs/errors/CAGE-ENV-002.md +51 -0
  272. package/templates/app/docs/errors/CAGE-ENV-003.md +48 -0
  273. package/templates/app/docs/errors/CAGE-EVENT-001.md +1 -1
  274. package/templates/app/docs/errors/CAGE-EVENT-002.md +7 -7
  275. package/templates/app/docs/errors/CAGE-FIELD-001.md +2 -2
  276. package/templates/app/docs/errors/CAGE-FIELD-002.md +1 -1
  277. package/templates/app/docs/errors/CAGE-FIELD-003.md +1 -1
  278. package/templates/app/docs/errors/CAGE-FIELD-004.md +1 -1
  279. package/templates/app/docs/errors/CAGE-FILE-001.md +56 -0
  280. package/templates/app/docs/errors/CAGE-GEN-001.md +2 -2
  281. package/templates/app/docs/errors/CAGE-GEN-002.md +1 -1
  282. package/templates/app/docs/errors/CAGE-GEN-003.md +53 -0
  283. package/templates/app/docs/errors/CAGE-GRANT-001.md +3 -3
  284. package/templates/app/docs/errors/CAGE-GRANT-002.md +2 -2
  285. package/templates/app/docs/errors/CAGE-GRANT-003.md +7 -6
  286. package/templates/app/docs/errors/CAGE-IMPACT-001.md +2 -2
  287. package/templates/app/docs/errors/CAGE-IMPACT-002.md +52 -0
  288. package/templates/app/docs/errors/CAGE-INIT-001.md +1 -1
  289. package/templates/app/docs/errors/CAGE-INIT-002.md +1 -1
  290. package/templates/app/docs/errors/CAGE-INIT-003.md +2 -2
  291. package/templates/app/docs/errors/CAGE-INIT-004.md +1 -1
  292. package/templates/app/docs/errors/CAGE-INIT-005.md +52 -0
  293. package/templates/app/docs/errors/CAGE-JOB-001.md +1 -1
  294. package/templates/app/docs/errors/CAGE-JOB-002.md +1 -1
  295. package/templates/app/docs/errors/CAGE-JOB-003.md +1 -1
  296. package/templates/app/docs/errors/CAGE-LINT-001.md +1 -1
  297. package/templates/app/docs/errors/CAGE-MIG-001.md +1 -1
  298. package/templates/app/docs/errors/CAGE-MIG-002.md +1 -1
  299. package/templates/app/docs/errors/CAGE-MIG-005.md +1 -1
  300. package/templates/app/docs/errors/CAGE-NAME-001.md +1 -1
  301. package/templates/app/docs/errors/CAGE-NAME-002.md +1 -1
  302. package/templates/app/docs/errors/CAGE-NAME-003.md +3 -3
  303. package/templates/app/docs/errors/CAGE-NAME-004.md +1 -1
  304. package/templates/app/docs/errors/CAGE-NAME-005.md +1 -1
  305. package/templates/app/docs/errors/CAGE-NAME-006.md +1 -1
  306. package/templates/app/docs/errors/CAGE-ORG-001.md +7 -6
  307. package/templates/app/docs/errors/CAGE-PAIR-002.md +6 -5
  308. package/templates/app/docs/errors/CAGE-QUERY-001.md +1 -1
  309. package/templates/app/docs/errors/CAGE-QUERY-002.md +2 -2
  310. package/templates/app/docs/errors/CAGE-QUERY-003.md +7 -6
  311. package/templates/app/docs/errors/CAGE-REACT-001.md +3 -3
  312. package/templates/app/docs/errors/CAGE-REACT-002.md +1 -1
  313. package/templates/app/docs/errors/CAGE-REACT-003.md +50 -0
  314. package/templates/app/docs/errors/CAGE-READS-001.md +9 -6
  315. package/templates/app/docs/errors/CAGE-REG-001.md +13 -12
  316. package/templates/app/docs/errors/CAGE-REG-002.md +2 -1
  317. package/templates/app/docs/errors/CAGE-REG-003.md +1 -1
  318. package/templates/app/docs/errors/CAGE-REL-001.md +14 -14
  319. package/templates/app/docs/errors/CAGE-ROUTE-001.md +7 -6
  320. package/templates/app/docs/errors/CAGE-SCOPE-001.md +1 -1
  321. package/templates/app/docs/errors/CAGE-SCOPE-002.md +2 -2
  322. package/templates/app/docs/errors/CAGE-SECRET-001.md +2 -2
  323. package/templates/app/docs/errors/CAGE-SECRET-002.md +1 -1
  324. package/templates/app/docs/errors/CAGE-SENS-001.md +5 -5
  325. package/templates/app/docs/errors/CAGE-SQL-001.md +1 -1
  326. package/templates/app/docs/errors/CAGE-SQL-002.md +1 -1
  327. package/templates/app/docs/errors/CAGE-STATE-001.md +3 -3
  328. package/templates/app/docs/errors/CAGE-STATE-002.md +1 -1
  329. package/templates/app/docs/errors/CAGE-STATE-003.md +1 -1
  330. package/templates/app/docs/errors/CAGE-STATE-004.md +1 -1
  331. package/templates/app/docs/errors/CAGE-STATE-005.md +3 -2
  332. package/templates/app/docs/errors/CAGE-STATE-010.md +5 -5
  333. package/templates/app/docs/errors/CAGE-STATE-011.md +5 -5
  334. package/templates/app/docs/errors/CAGE-STRUCT-001.md +1 -1
  335. package/templates/app/docs/errors/CAGE-STRUCT-002.md +1 -1
  336. package/templates/app/docs/errors/CAGE-SYNC-001.md +3 -2
  337. package/templates/app/docs/errors/CAGE-TEST-001.md +1 -1
  338. package/templates/app/docs/errors/CAGE-TEST-002.md +50 -0
  339. package/templates/app/docs/errors/CAGE-TEST-003.md +52 -0
  340. package/templates/app/docs/errors/CAGE-UNSAFE-001.md +3 -2
  341. package/templates/app/docs/errors/CAGE-UPGRADE-001.md +2 -2
  342. package/templates/app/docs/errors/CAGE-WORKER-001.md +48 -0
  343. package/templates/app/docs/errors/CAGE-WORKER-002.md +50 -0
  344. package/templates/app/docs/errors/CAGE-WORKER-003.md +48 -0
  345. package/templates/app/docs/errors/README.md +50 -0
  346. package/templates/app/package.json +3 -3
  347. package/templates/app/packages/contracts/package.json +1 -1
  348. package/templates/app/packages/contracts/src/aggregates/dept/index.ts +10 -10
  349. package/templates/app/packages/contracts/src/aggregates/inventory/index.ts +5 -5
  350. package/templates/app/packages/contracts/src/aggregates/inventory-lock/index.ts +4 -4
  351. package/templates/app/packages/contracts/src/aggregates/purchase-order/index.ts +26 -12
  352. package/templates/app/packages/contracts/src/aggregates/role/index.ts +15 -15
  353. package/templates/app/packages/contracts/src/aggregates/user/index.ts +16 -16
  354. package/templates/app/packages/contracts/src/index.ts +7 -1
  355. package/templates/app/packages/contracts/src/queries/index.ts +2 -2
  356. package/templates/app/packages/domain/package.json +5 -4
  357. package/templates/app/packages/domain/src/index.ts +4 -0
  358. package/templates/app/packages/domain/src/integrations/erp.ts +15 -0
  359. package/templates/app/packages/domain/src/integrations/intelligence.ts +20 -0
  360. package/templates/app/packages/domain/src/modules/inventory/index.ts +1 -0
  361. package/templates/app/packages/domain/src/modules/inventory/inventory.ts +12 -0
  362. package/templates/app/packages/domain/src/modules/purchase/approvals.ts +22 -1
  363. package/templates/app/packages/domain/src/modules/purchase/index.ts +1 -0
  364. package/templates/app/packages/domain/src/modules/purchase/intelligence.test.ts +62 -0
  365. package/templates/app/packages/domain/src/modules/purchase/jobs.ts +5 -0
  366. package/templates/app/packages/domain/src/modules/purchase/purchase-order.test.ts +9 -0
  367. package/templates/app/packages/domain/src/modules/purchase/purchase-order.ts +70 -0
  368. package/templates/app/packages/domain/src/modules/purchase/queries.ts +5 -0
  369. package/templates/app/packages/domain/src/workflows/purchase-inventory.ts +6 -0
  370. package/templates/app/packages/domain/src/workflows/purchase-process.ts +42 -0
  371. package/templates/blank/.dockerignore +2 -0
  372. package/templates/blank/.env.example +10 -0
  373. package/templates/blank/AGENTS.md +49 -9
  374. package/templates/blank/README.md +4 -1
  375. package/templates/blank/_gitignore +1 -0
  376. package/templates/blank/apps/api/package.json +1 -1
  377. package/templates/blank/apps/api/src/main.ts +4 -1
  378. package/templates/blank/apps/api/src/worker.ts +2 -0
  379. package/templates/blank/apps/web/index.html +1 -0
  380. package/templates/blank/apps/web/package.json +7 -3
  381. package/templates/blank/apps/web/src/app/app.tsx +80 -18
  382. package/templates/blank/apps/web/src/app/styles/global.css +90 -0
  383. package/templates/blank/apps/web/src/app/use-session.ts +43 -0
  384. package/templates/blank/apps/web/src/app/workspace-layout.tsx +30 -5
  385. package/templates/blank/apps/web/src/main.tsx +5 -0
  386. package/templates/blank/apps/web/src/modules/auth/index.ts +4 -0
  387. package/templates/blank/apps/web/src/modules/auth/pages/login-page.tsx +18 -1
  388. package/templates/blank/apps/web/src/modules/directory/index.ts +7 -0
  389. package/templates/blank/apps/web/src/modules/directory/pages/user-detail-page.tsx +78 -0
  390. package/templates/blank/apps/web/src/modules/directory/pages/users-page.tsx +93 -0
  391. package/templates/blank/apps/web/src/modules/workspace/index.ts +4 -0
  392. package/templates/blank/apps/web/src/modules/workspace/pages/home-page.tsx +17 -0
  393. package/templates/blank/apps/web/src/shared/lib/error-message.ts +11 -0
  394. package/templates/blank/apps/web/src/shared/lib/navigation.ts +21 -0
  395. package/templates/blank/apps/web/src/shared/ui/brand.tsx +10 -2
  396. package/templates/blank/apps/web/src/shared/ui/page-state.css +47 -0
  397. package/templates/blank/apps/web/src/shared/ui/page-state.tsx +76 -0
  398. package/templates/blank/apps/web/src/shared/ui/require-capability.tsx +34 -0
  399. package/templates/blank/apps/web/vite.config.ts +5 -0
  400. package/templates/blank/deploy/nginx.conf +52 -0
  401. package/templates/blank/docs/ai/README.md +21 -0
  402. package/templates/blank/docs/ai/architecture.md +26 -0
  403. package/templates/blank/docs/ai/commenting.md +203 -0
  404. package/templates/blank/docs/ai/diagnostics.md +80 -0
  405. package/templates/blank/docs/ai/files.md +93 -0
  406. package/templates/blank/docs/ai/intelligence.md +348 -0
  407. package/templates/blank/docs/ai/ontology-context.md +59 -4
  408. package/templates/blank/docs/ai/primitives.md +33 -0
  409. package/templates/blank/docs/ai/project-structure.md +8 -3
  410. package/templates/blank/docs/ai/purchase-example.md +16 -2
  411. package/templates/blank/docs/ai/recipes.md +9 -1
  412. package/templates/blank/docs/ai/routing.md +86 -0
  413. package/templates/blank/docs/ai/troubleshooting.md +5 -0
  414. package/templates/blank/docs/ai/workflow.md +24 -11
  415. package/templates/blank/docs/errors/CAGE-AI-001.md +61 -0
  416. package/templates/blank/docs/errors/CAGE-APPR-001.md +7 -6
  417. package/templates/blank/docs/errors/CAGE-APPR-002.md +2 -2
  418. package/templates/blank/docs/errors/CAGE-APPR-003.md +1 -1
  419. package/templates/blank/docs/errors/CAGE-APPR-004.md +4 -4
  420. package/templates/blank/docs/errors/CAGE-APPR-005.md +1 -1
  421. package/templates/blank/docs/errors/CAGE-APPR-006.md +12 -6
  422. package/templates/blank/docs/errors/CAGE-APPR-007.md +3 -3
  423. package/templates/blank/docs/errors/CAGE-APPR-010.md +5 -5
  424. package/templates/blank/docs/errors/CAGE-AUDIT-001.md +53 -0
  425. package/templates/blank/docs/errors/CAGE-AUTH-001.md +1 -1
  426. package/templates/blank/docs/errors/CAGE-BIZ-001.md +51 -0
  427. package/templates/blank/docs/errors/CAGE-BIZ-002.md +49 -0
  428. package/templates/blank/docs/errors/CAGE-BUDGET-001.md +1 -1
  429. package/templates/blank/docs/errors/CAGE-BUDGET-002.md +1 -1
  430. package/templates/blank/docs/errors/CAGE-BUDGET-003.md +1 -1
  431. package/templates/blank/docs/errors/CAGE-CMD-002.md +1 -1
  432. package/templates/blank/docs/errors/CAGE-CMD-003.md +1 -1
  433. package/templates/blank/docs/errors/CAGE-CONN-001.md +3 -3
  434. package/templates/blank/docs/errors/CAGE-CONN-002.md +1 -1
  435. package/templates/blank/docs/errors/CAGE-CONN-003.md +1 -1
  436. package/templates/blank/docs/errors/CAGE-CONN-004.md +1 -1
  437. package/templates/blank/docs/errors/CAGE-CONN-005.md +1 -1
  438. package/templates/blank/docs/errors/CAGE-CONN-006.md +1 -1
  439. package/templates/blank/docs/errors/CAGE-CONN-007.md +6 -6
  440. package/templates/blank/docs/errors/CAGE-CONN-008.md +5 -5
  441. package/templates/blank/docs/errors/CAGE-CONN-009.md +6 -6
  442. package/templates/blank/docs/errors/CAGE-CONN-010.md +6 -6
  443. package/templates/blank/docs/errors/CAGE-CONN-011.md +1 -1
  444. package/templates/blank/docs/errors/CAGE-CONN-012.md +1 -1
  445. package/templates/blank/docs/errors/CAGE-CONN-013.md +49 -0
  446. package/templates/blank/docs/errors/CAGE-CONN-014.md +48 -0
  447. package/templates/blank/docs/errors/CAGE-CONN-015.md +49 -0
  448. package/templates/blank/docs/errors/CAGE-CREATE-001.md +10 -9
  449. package/templates/blank/docs/errors/CAGE-DECL-001.md +2 -2
  450. package/templates/blank/docs/errors/CAGE-DECL-002.md +7 -6
  451. package/templates/blank/docs/errors/CAGE-DECL-003.md +1 -1
  452. package/templates/blank/docs/errors/CAGE-DECL-004.md +1 -1
  453. package/templates/blank/docs/errors/CAGE-DEP-001.md +2 -2
  454. package/templates/blank/docs/errors/CAGE-DEP-002.md +1 -1
  455. package/templates/blank/docs/errors/CAGE-DEP-003.md +2 -2
  456. package/templates/blank/docs/errors/CAGE-DEP-004.md +1 -1
  457. package/templates/blank/docs/errors/CAGE-DEP-005.md +1 -1
  458. package/templates/blank/docs/errors/CAGE-DIAG-001.md +53 -0
  459. package/templates/blank/docs/errors/CAGE-DLQ-001.md +2 -2
  460. package/templates/blank/docs/errors/CAGE-ENV-001.md +4 -4
  461. package/templates/blank/docs/errors/CAGE-ENV-002.md +51 -0
  462. package/templates/blank/docs/errors/CAGE-ENV-003.md +48 -0
  463. package/templates/blank/docs/errors/CAGE-EVENT-001.md +1 -1
  464. package/templates/blank/docs/errors/CAGE-EVENT-002.md +7 -7
  465. package/templates/blank/docs/errors/CAGE-FIELD-001.md +2 -2
  466. package/templates/blank/docs/errors/CAGE-FIELD-002.md +1 -1
  467. package/templates/blank/docs/errors/CAGE-FIELD-003.md +1 -1
  468. package/templates/blank/docs/errors/CAGE-FIELD-004.md +1 -1
  469. package/templates/blank/docs/errors/CAGE-FILE-001.md +56 -0
  470. package/templates/blank/docs/errors/CAGE-GEN-001.md +2 -2
  471. package/templates/blank/docs/errors/CAGE-GEN-002.md +1 -1
  472. package/templates/blank/docs/errors/CAGE-GEN-003.md +53 -0
  473. package/templates/blank/docs/errors/CAGE-GRANT-001.md +3 -3
  474. package/templates/blank/docs/errors/CAGE-GRANT-002.md +2 -2
  475. package/templates/blank/docs/errors/CAGE-GRANT-003.md +7 -6
  476. package/templates/blank/docs/errors/CAGE-IMPACT-001.md +2 -2
  477. package/templates/blank/docs/errors/CAGE-IMPACT-002.md +52 -0
  478. package/templates/blank/docs/errors/CAGE-INIT-001.md +1 -1
  479. package/templates/blank/docs/errors/CAGE-INIT-002.md +1 -1
  480. package/templates/blank/docs/errors/CAGE-INIT-003.md +2 -2
  481. package/templates/blank/docs/errors/CAGE-INIT-004.md +1 -1
  482. package/templates/blank/docs/errors/CAGE-INIT-005.md +52 -0
  483. package/templates/blank/docs/errors/CAGE-JOB-001.md +1 -1
  484. package/templates/blank/docs/errors/CAGE-JOB-002.md +1 -1
  485. package/templates/blank/docs/errors/CAGE-JOB-003.md +1 -1
  486. package/templates/blank/docs/errors/CAGE-LINT-001.md +1 -1
  487. package/templates/blank/docs/errors/CAGE-MIG-001.md +1 -1
  488. package/templates/blank/docs/errors/CAGE-MIG-002.md +1 -1
  489. package/templates/blank/docs/errors/CAGE-MIG-005.md +1 -1
  490. package/templates/blank/docs/errors/CAGE-NAME-001.md +1 -1
  491. package/templates/blank/docs/errors/CAGE-NAME-002.md +1 -1
  492. package/templates/blank/docs/errors/CAGE-NAME-003.md +3 -3
  493. package/templates/blank/docs/errors/CAGE-NAME-004.md +1 -1
  494. package/templates/blank/docs/errors/CAGE-NAME-005.md +1 -1
  495. package/templates/blank/docs/errors/CAGE-NAME-006.md +1 -1
  496. package/templates/blank/docs/errors/CAGE-ORG-001.md +7 -6
  497. package/templates/blank/docs/errors/CAGE-PAIR-002.md +6 -5
  498. package/templates/blank/docs/errors/CAGE-QUERY-001.md +1 -1
  499. package/templates/blank/docs/errors/CAGE-QUERY-002.md +2 -2
  500. package/templates/blank/docs/errors/CAGE-QUERY-003.md +7 -6
  501. package/templates/blank/docs/errors/CAGE-REACT-001.md +3 -3
  502. package/templates/blank/docs/errors/CAGE-REACT-002.md +1 -1
  503. package/templates/blank/docs/errors/CAGE-REACT-003.md +50 -0
  504. package/templates/blank/docs/errors/CAGE-READS-001.md +9 -6
  505. package/templates/blank/docs/errors/CAGE-REG-001.md +13 -12
  506. package/templates/blank/docs/errors/CAGE-REG-002.md +2 -1
  507. package/templates/blank/docs/errors/CAGE-REG-003.md +1 -1
  508. package/templates/blank/docs/errors/CAGE-REL-001.md +14 -14
  509. package/templates/blank/docs/errors/CAGE-ROUTE-001.md +7 -6
  510. package/templates/blank/docs/errors/CAGE-SCOPE-001.md +1 -1
  511. package/templates/blank/docs/errors/CAGE-SCOPE-002.md +2 -2
  512. package/templates/blank/docs/errors/CAGE-SECRET-001.md +2 -2
  513. package/templates/blank/docs/errors/CAGE-SECRET-002.md +1 -1
  514. package/templates/blank/docs/errors/CAGE-SENS-001.md +5 -5
  515. package/templates/blank/docs/errors/CAGE-SQL-001.md +1 -1
  516. package/templates/blank/docs/errors/CAGE-SQL-002.md +1 -1
  517. package/templates/blank/docs/errors/CAGE-STATE-001.md +3 -3
  518. package/templates/blank/docs/errors/CAGE-STATE-002.md +1 -1
  519. package/templates/blank/docs/errors/CAGE-STATE-003.md +1 -1
  520. package/templates/blank/docs/errors/CAGE-STATE-004.md +1 -1
  521. package/templates/blank/docs/errors/CAGE-STATE-005.md +3 -2
  522. package/templates/blank/docs/errors/CAGE-STATE-010.md +5 -5
  523. package/templates/blank/docs/errors/CAGE-STATE-011.md +5 -5
  524. package/templates/blank/docs/errors/CAGE-STRUCT-001.md +1 -1
  525. package/templates/blank/docs/errors/CAGE-STRUCT-002.md +1 -1
  526. package/templates/blank/docs/errors/CAGE-SYNC-001.md +3 -2
  527. package/templates/blank/docs/errors/CAGE-TEST-001.md +1 -1
  528. package/templates/blank/docs/errors/CAGE-TEST-002.md +50 -0
  529. package/templates/blank/docs/errors/CAGE-TEST-003.md +52 -0
  530. package/templates/blank/docs/errors/CAGE-UNSAFE-001.md +3 -2
  531. package/templates/blank/docs/errors/CAGE-UPGRADE-001.md +2 -2
  532. package/templates/blank/docs/errors/CAGE-WORKER-001.md +48 -0
  533. package/templates/blank/docs/errors/CAGE-WORKER-002.md +50 -0
  534. package/templates/blank/docs/errors/CAGE-WORKER-003.md +48 -0
  535. package/templates/blank/docs/errors/README.md +50 -0
  536. package/templates/blank/docs/examples/purchase-admin/apps/api/src/main.ts +5 -1
  537. package/templates/blank/docs/examples/purchase-admin/apps/api/src/worker.ts +3 -0
  538. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/app.tsx +122 -12
  539. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/styles/global.css +88 -8
  540. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/use-session.ts +43 -0
  541. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/workspace-layout.tsx +58 -19
  542. package/templates/blank/docs/examples/purchase-admin/apps/web/src/main.tsx +5 -0
  543. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/hooks/use-approval-tasks.ts +11 -0
  544. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/index.ts +4 -0
  545. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/pages/approval-tasks-page.tsx +20 -1
  546. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/auth/index.ts +4 -0
  547. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/auth/pages/login-page.tsx +12 -0
  548. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/inventory/index.ts +4 -0
  549. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/inventory/pages/inventory-page.tsx +29 -1
  550. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/approval-history.tsx +32 -0
  551. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/order-attachments.tsx +29 -0
  552. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/purchase-assistant-context.tsx +17 -0
  553. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/purchase-order-form.css +6 -0
  554. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/purchase-order-form.tsx +25 -3
  555. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/index.ts +5 -0
  556. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/lib/presentation.ts +20 -0
  557. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-intelligence.css +15 -0
  558. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-order-detail-page.tsx +154 -0
  559. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-orders-page.tsx +52 -22
  560. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/workspace/index.ts +5 -0
  561. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/workspace/pages/home-page.tsx +44 -0
  562. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/hooks/use-command.ts +13 -0
  563. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/lib/error-message.ts +9 -0
  564. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/lib/navigation.ts +21 -0
  565. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/assistant-markdown.tsx +19 -0
  566. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/assistant-panel.css +134 -0
  567. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/assistant-panel.tsx +200 -0
  568. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/assistant-scope.tsx +72 -0
  569. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/attachment-upload.css +28 -0
  570. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/attachment-upload.tsx +163 -0
  571. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/notice.tsx +7 -0
  572. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/page-heading.tsx +7 -0
  573. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/page-state.css +47 -0
  574. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/page-state.tsx +76 -0
  575. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/require-capability.tsx +34 -0
  576. package/templates/blank/docs/examples/purchase-admin/cage.config.json +9 -0
  577. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/dept/index.ts +10 -10
  578. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/inventory/index.ts +5 -5
  579. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/inventory-lock/index.ts +4 -4
  580. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/purchase-order/index.ts +26 -12
  581. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/role/index.ts +15 -15
  582. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/user/index.ts +16 -16
  583. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/index.ts +7 -1
  584. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/queries/index.ts +2 -2
  585. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/index.ts +4 -0
  586. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/integrations/erp.ts +15 -0
  587. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/integrations/intelligence.ts +20 -0
  588. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/inventory/index.ts +1 -0
  589. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/inventory/inventory.ts +12 -0
  590. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/approvals.ts +22 -1
  591. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/index.ts +1 -0
  592. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/intelligence.test.ts +62 -0
  593. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/jobs.ts +5 -0
  594. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/purchase-order.test.ts +9 -0
  595. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/purchase-order.ts +70 -0
  596. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/queries.ts +5 -0
  597. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/workflows/purchase-inventory.ts +6 -0
  598. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/workflows/purchase-process.ts +42 -0
  599. package/templates/blank/package.json +3 -3
  600. package/templates/blank/packages/contracts/package.json +1 -1
  601. package/templates/blank/packages/contracts/src/aggregates/dept/index.ts +10 -10
  602. package/templates/blank/packages/contracts/src/aggregates/role/index.ts +15 -15
  603. package/templates/blank/packages/contracts/src/aggregates/user/index.ts +16 -16
  604. package/templates/blank/packages/contracts/src/index.ts +1 -1
  605. package/templates/blank/packages/contracts/src/queries/index.ts +1 -1
  606. package/templates/blank/packages/domain/package.json +5 -4
  607. package/templates/blank/packages/domain/src/index.ts +2 -1
@@ -1,6 +1,7 @@
1
1
  node_modules/
2
2
  dist/
3
3
  .cage/
4
+ .cage-files/
4
5
  generated/
5
6
  .env
6
7
  .env.*
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "@app/domain": "workspace:*",
13
- "@yss123/cage-http": "0.2.0",
14
- "@yss123/cage-connectors": "0.2.0"
13
+ "@yss123/cage-http": "0.3.0",
14
+ "@yss123/cage-connectors": "0.3.0"
15
15
  }
16
16
  }
@@ -1,9 +1,13 @@
1
1
  // 启动入口只装配框架:认证、业务路由和 /admin 都由 createServer 提供。
2
2
  // WEB_DIR 在部署镜像中指向 Vite 构建产物;本地由 Vite 独立提供前端。
3
+ // 进程启动只建立服务,不迁移结构、不初始化账号;这些操作由受控 CLI 流程提前完成。
4
+ // 声明中启用的 AI、审批与文件接口由框架挂载,后台事件消费仍需要独立 worker 进程。
3
5
  import { createServer } from '@yss123/cage-http';
4
6
  import * as domain from '@app/domain';
5
7
 
6
- const server = createServer({ domain, webDir: process.env.WEB_DIR, title: 'Cage 采购工作台' });
8
+ // 默认不接受转发头;部署在代理后时,仅在这里填写实际可信代理的地址或网段。
9
+ const server = createServer({ domain, webDir: process.env.WEB_DIR, title: 'Cage 采购工作台', trustProxy: false });
10
+ // listen 先等待路由、扩展与授权通知初始化;失败直接拒绝顶层启动,不伪装为已就绪。
7
11
  await server.listen();
8
12
  // 退出时释放数据库池及 LISTEN 连接,部署滚动替换时不会留下旧连接。
9
13
  process.once('SIGINT', () => void server.close());
@@ -1,4 +1,5 @@
1
1
  // API 与 worker 使用相同声明。worker 专门处理审批启动、异步反应和 ERP 推送。
2
+ // 两个进程部署同一版本,消费者依据声明发现工作;事件提交成功不等于这些后台动作已经完成。
2
3
  import { startWorker } from '@yss123/cage-http/worker';
3
4
  import { fakeConnector, stage } from '@yss123/cage-connectors';
4
5
  import * as domain from '@app/domain';
@@ -9,6 +10,8 @@ if (stage() === 'fake') {
9
10
  pushOrder: (request) => ({ erpNo: `DEMO-${request.externalId.slice(0, 8)}` }),
10
11
  });
11
12
  }
13
+ // 框架拥有轮询、重试、调度和连接生命周期;应用只注册本地 fake,不另建数据库池或业务重试循环。
12
14
  const worker = await startWorker({ domain });
15
+ // 停止句柄等待框架在途工作收尾并释放连接,避免进程退出时留下仍在续租的消费者。
13
16
  process.once('SIGINT', () => void worker.stop());
14
17
  process.once('SIGTERM', () => void worker.stop());
@@ -1,4 +1,5 @@
1
1
  <!doctype html>
2
+ <!-- 浏览器文档外壳:提供 React 挂载节点与模块入口;业务路由、会话及数据加载由 src/main.tsx 装配的应用处理。 -->
2
3
  <html lang="zh-CN">
3
4
  <head>
4
5
  <meta charset="UTF-8" />
@@ -10,13 +10,17 @@
10
10
  "dependencies": {
11
11
  "@app/contracts": "workspace:*",
12
12
  "@tanstack/react-query": "^5.87.1",
13
+ "@yss123/cage-client": "0.3.0",
13
14
  "react": "^19.1.1",
14
- "react-dom": "^19.1.1"
15
+ "react-dom": "^19.1.1",
16
+ "react-markdown": "^10.1.0",
17
+ "react-router-dom": "^7.18.5",
18
+ "remark-gfm": "^4.0.1"
15
19
  },
16
20
  "devDependencies": {
17
21
  "@types/react": "^19.1.13",
18
22
  "@types/react-dom": "^19.1.9",
19
- "vite": "^7.1.4",
20
- "typescript": "~5.9.3"
23
+ "typescript": "~5.9.3",
24
+ "vite": "^7.1.4"
21
25
  }
22
26
  }
@@ -1,18 +1,128 @@
1
- // 应用组合层只决定会话与页面的切换;具体业务交给 modules 下的页面。
2
- import { useEffect, useState } from 'react';
3
- import { loadMe } from '@app/contracts';
1
+ /**
2
+ * 采购应用的路由组合层,集中连接认证、工作台、采购、库存和审批模块的公开入口。
3
+ * 会话先恢复,再决定展示页面、跳转登录或保留原地址提示网络故障。
4
+ * 页面身份来自 URL,模块间导航通过 app 注入;前端能力守卫不能代替服务端授权。
5
+ */
6
+ // URL 是页面身份;应用壳只组合路由、会话与模块,不用组件状态模拟多页面导航。
7
+ import { BrowserRouter, Navigate, Route, Routes, useLocation } from 'react-router-dom';
4
8
  import { LoginPage } from '../modules/auth';
9
+ import { HomePage } from '../modules/workspace';
10
+ import { PurchaseOrdersPage, PurchaseOrderDetailPage } from '../modules/purchase';
11
+ import { InventoryPage } from '../modules/inventory';
12
+ import { ApprovalTasksPage, useApprovalTasks } from '../modules/approval';
13
+ import { PageState } from '../shared/ui/page-state';
14
+ import { RequireCapability } from '../shared/ui/require-capability';
15
+ import { loginReturnTo } from '../shared/lib/navigation';
16
+ import { useSession } from './use-session';
5
17
  import { WorkspaceLayout } from './workspace-layout';
6
18
 
19
+ const home = '/workspace';
20
+
21
+ /**
22
+ * 安装 BrowserRouter 并渲染路由树。部署方需为业务深链接提供 SPA 回退,/api 和 /admin 由各自服务处理。
23
+ */
7
24
  export function App() {
8
- const [session, setSession] = useState<'loading' | 'guest' | 'ready'>('loading');
9
- useEffect(() => {
10
- void loadMe().then((result) => setSession(result.ok ? 'ready' : 'guest'));
11
- }, []);
12
- if (session === 'loading') return <div className="loading">正在连接工作台…</div>;
13
- return session === 'guest' ? (
14
- <LoginPage onLogin={() => setSession('ready')} />
15
- ) : (
16
- <WorkspaceLayout onLogout={() => setSession('guest')} />
25
+ return (
26
+ <BrowserRouter>
27
+ <AppRoutes />
28
+ </BrowserRouter>
29
+ );
30
+ }
31
+
32
+ /**
33
+ * 在组合层读取审批待办数量并传给采购列表,使采购模块不依赖审批页面的内部实现。
34
+ * 待办尚未加载或失败时允许数量缺省,页面显示未知而不伪造零。
35
+ */
36
+ function OrdersRoute() {
37
+ const tasks = useApprovalTasks();
38
+ return <PurchaseOrdersPage pendingTasks={tasks.data?.length} />;
39
+ }
40
+
41
+ /**
42
+ * 根据 useSession 的 loading/guest/ready/error 状态组装路由。
43
+ * guest 使用完整路径、查询参数和 hash 构造 returnTo;ready 经 loginReturnTo 校验后回跳。
44
+ * 网络错误保持当前地址以便重试;未知业务地址展示 404 页面,记录读取错误由各页面处理。
45
+ */
46
+ function AppRoutes() {
47
+ const { session, restore, onLogin, onLogout } = useSession();
48
+ const location = useLocation();
49
+ if (session === 'loading')
50
+ return (
51
+ <div className="loading" role="status">
52
+ 正在连接工作台…
53
+ </div>
54
+ );
55
+ if (session === 'error')
56
+ return (
57
+ <PageState
58
+ title="暂时无法连接工作台"
59
+ description="请检查网络和 API 服务,重试后继续访问当前地址。"
60
+ to={home}
61
+ label="返回工作台"
62
+ >
63
+ <button onClick={restore}>重新连接</button>
64
+ </PageState>
65
+ );
66
+ const login = `/login?returnTo=${encodeURIComponent(location.pathname + location.search + location.hash)}`;
67
+ return (
68
+ <Routes>
69
+ <Route
70
+ path="/login"
71
+ element={
72
+ session === 'ready' ? (
73
+ <Navigate to={loginReturnTo(location.search, home)} replace />
74
+ ) : (
75
+ <LoginPage onLogin={onLogin} />
76
+ )
77
+ }
78
+ />
79
+ <Route
80
+ element={
81
+ session === 'ready' ? <WorkspaceLayout onLogout={onLogout} /> : <Navigate to={login} replace />
82
+ }
83
+ >
84
+ <Route index element={<Navigate to={home} replace />} />
85
+ <Route path="workspace" element={<HomePage />} />
86
+ <Route
87
+ path="procurement/orders"
88
+ element={
89
+ <RequireCapability capability="PurchaseOrder.read" home={home}>
90
+ <OrdersRoute />
91
+ </RequireCapability>
92
+ }
93
+ />
94
+ <Route
95
+ path="procurement/orders/:id"
96
+ element={
97
+ <RequireCapability capability="PurchaseOrder.read" home={home}>
98
+ <PurchaseOrderDetailPage />
99
+ </RequireCapability>
100
+ }
101
+ />
102
+ <Route
103
+ path="inventory"
104
+ element={
105
+ <RequireCapability capability="Inventory.read" home={home}>
106
+ <InventoryPage />
107
+ </RequireCapability>
108
+ }
109
+ />
110
+ <Route
111
+ path="approvals"
112
+ element={<ApprovalTasksPage orderUrl={(id) => `/procurement/orders/${encodeURIComponent(id)}`} />}
113
+ />
114
+ <Route
115
+ path="*"
116
+ element={
117
+ <PageState
118
+ title="页面不存在"
119
+ description="请检查地址,或从工作台导航进入已有页面。"
120
+ to={home}
121
+ label="返回工作台"
122
+ />
123
+ }
124
+ />
125
+ </Route>
126
+ </Routes>
17
127
  );
18
128
  }
@@ -1,3 +1,7 @@
1
+ /**
2
+ * 采购应用的全局视觉与布局基础,随浏览器入口加载;依次定义主题、工作台、业务表格、表单及登录页。
3
+ * 模块专用样式在模块附近维护。状态类只映射已有 UI 状态,不承担权限、审批或数据计算。
4
+ */
1
5
  /* 暖白纸面配墨绿导航;用边线、字重和留白建立信息层次,避免装饰压过业务数据。 */
2
6
  :root {
3
7
  font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
@@ -83,6 +87,9 @@ h3 {
83
87
  font-family: Consolas, 'Courier New', monospace;
84
88
  font-size: 12px;
85
89
  }
90
+ /**
91
+ * 固定侧栏与主内容区的桌面组合;窄屏规则在文件后部覆盖布局,保留导航可达性。
92
+ */
86
93
  .workspace {
87
94
  display: flex;
88
95
  min-height: 100vh;
@@ -124,7 +131,7 @@ nav {
124
131
  display: grid;
125
132
  gap: 7px;
126
133
  }
127
- nav button {
134
+ nav a {
128
135
  display: flex;
129
136
  align-items: center;
130
137
  gap: 16px;
@@ -134,22 +141,22 @@ nav button {
134
141
  text-align: left;
135
142
  padding: 14px 13px;
136
143
  }
137
- nav button span {
144
+ nav a span {
138
145
  font-size: 10px;
139
146
  opacity: 0.6;
140
147
  }
141
- nav button b {
148
+ nav a b {
142
149
  margin-left: auto;
143
150
  font-size: 11px;
144
151
  }
145
- nav button.selected {
152
+ nav a.selected {
146
153
  background: var(--accent);
147
154
  color: var(--green);
148
155
  }
149
- nav button:hover {
156
+ nav a:hover {
150
157
  background: #31594e;
151
158
  }
152
- nav button.selected:hover {
159
+ nav a.selected:hover {
153
160
  background: #d9efa9;
154
161
  }
155
162
  .aside-bottom {
@@ -301,6 +308,9 @@ header {
301
308
  .toolbar > button {
302
309
  font-size: 11px;
303
310
  }
311
+ /**
312
+ * 宽表格在容器中横向滚动,避免列内容把页面宽度撑出视口。
313
+ */
304
314
  .table-wrap {
305
315
  overflow: auto;
306
316
  }
@@ -470,6 +480,9 @@ input {
470
480
  input:focus {
471
481
  outline: 2px solid #b2cb8b;
472
482
  }
483
+ /**
484
+ * 创建弹窗的遮罩与居中层;具体采购弹窗高度及内部滚动由模块样式补充。
485
+ */
473
486
  .modal-backdrop {
474
487
  position: fixed;
475
488
  inset: 0;
@@ -560,6 +573,9 @@ input:focus {
560
573
  color: var(--muted);
561
574
  }
562
575
  /* 窄屏将导航转成横向工具栏,表格保留横向滚动,操作列不会挤成不可点击的小按钮。 */
576
+ /**
577
+ * 在九百像素及以下调整导航与表单布局,减少桌面侧栏对内容宽度的挤占。
578
+ */
563
579
  @media (max-width: 900px) {
564
580
  aside {
565
581
  position: static;
@@ -581,11 +597,11 @@ input:focus {
581
597
  display: flex;
582
598
  margin-top: 20px;
583
599
  }
584
- nav button {
600
+ nav a {
585
601
  flex: 1;
586
602
  padding: 10px;
587
603
  }
588
- nav button span {
604
+ nav a span {
589
605
  display: none;
590
606
  }
591
607
  .aside-bottom {
@@ -656,8 +672,72 @@ input:focus {
656
672
  padding: 10px;
657
673
  }
658
674
  }
675
+ /**
676
+ * 尊重系统减少动画偏好,避免将过渡效果作为理解操作反馈的唯一依据。
677
+ */
659
678
  @media (prefers-reduced-motion: reduce) {
660
679
  * {
661
680
  transition: none !important;
662
681
  }
663
682
  }
683
+
684
+ /* 链接保持原生导航语义,单据编号可复制地址或在新标签页打开。 */
685
+ .record-link {
686
+ color: var(--green);
687
+ font-weight: 600;
688
+ text-decoration: underline;
689
+ text-decoration-color: #c6d5b5;
690
+ text-underline-offset: 4px;
691
+ }
692
+ .record-link:hover {
693
+ text-decoration-color: var(--green);
694
+ }
695
+ .record-facts {
696
+ display: grid;
697
+ grid-template-columns: repeat(2, minmax(0, 1fr));
698
+ margin: 0;
699
+ padding: 8px 24px;
700
+ gap: 0 36px;
701
+ }
702
+ .record-facts > div {
703
+ padding: 22px 0;
704
+ border-bottom: 1px solid var(--line);
705
+ }
706
+ .record-facts dt {
707
+ color: var(--muted);
708
+ font-size: 11px;
709
+ margin-bottom: 11px;
710
+ }
711
+ .record-facts dd {
712
+ margin: 0;
713
+ font-size: 14px;
714
+ overflow-wrap: anywhere;
715
+ }
716
+ .entry-grid {
717
+ display: grid;
718
+ grid-template-columns: repeat(3, 1fr);
719
+ gap: 18px;
720
+ }
721
+ .entry-grid > a {
722
+ padding: 30px 25px;
723
+ background: #fff;
724
+ border: 1px solid var(--line);
725
+ border-radius: 6px;
726
+ }
727
+ .entry-grid > a:hover {
728
+ border-color: #99b47f;
729
+ background: #fafdf6;
730
+ }
731
+ .entry-grid small {
732
+ color: var(--muted);
733
+ font-size: 10px;
734
+ letter-spacing: 1px;
735
+ }
736
+ .entry-grid h2 {
737
+ margin: 24px 0 14px;
738
+ }
739
+ .entry-grid p {
740
+ font-size: 12px;
741
+ color: var(--muted);
742
+ line-height: 1.8;
743
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * 应用会话生命周期:首次加载 /me,并把 SDK 的账号退出或失效通知同步到路由状态。
3
+ * 与 URL 路由分离,网络故障不会被误判成未登录;查询缓存不能跨账号继续使用。
4
+ */
5
+ // 应用会话与 URL 导航分别管理:401 才进入登录,网络故障保留原地址并允许重试。
6
+ import { useCallback, useEffect, useState } from 'react';
7
+ import { useQueryClient } from '@tanstack/react-query';
8
+ import { client, loadMe } from '@app/contracts';
9
+
10
+ /**
11
+ * 在 QueryClientProvider 内使用。挂载时恢复用户,卸载时解除 SDK 订阅。
12
+ * 返回 session:loading 为恢复中,guest 为未认证,ready 为已加载身份,error 为其他恢复失败。
13
+ * restore 可重试恢复;onLogin/onLogout 由已完成认证动作的页面调用,只更新应用状态。
14
+ * 账号失效时发起取消查询并清空缓存;这里不负责服务端退出操作,也不保证取消已提交的业务命令。
15
+ */
16
+ export function useSession() {
17
+ const [session, setSession] = useState<'loading' | 'guest' | 'ready' | 'error'>('loading');
18
+ const cache = useQueryClient();
19
+ /**
20
+ * 每次恢复先显示 loading,再按 loadMe 的明确结果分类;只有 UNAUTHENTICATED 进入 guest。
21
+ */
22
+ const restore = useCallback(async () => {
23
+ setSession('loading');
24
+ const result = await loadMe();
25
+ setSession(result.ok ? 'ready' : result.code === 'UNAUTHENTICATED' ? 'guest' : 'error');
26
+ }, []);
27
+
28
+ useEffect(() => {
29
+ const unsubscribe = client.subscribe((_snapshot, reason) => {
30
+ if (reason === 'loaded') return;
31
+ // 先取消在途查询,再清除上一账号的缓存;路由守卫保留 URL 并决定登录回跳。
32
+ void cache.cancelQueries();
33
+ cache.clear();
34
+ setSession('guest');
35
+ });
36
+ void restore();
37
+ return () => {
38
+ unsubscribe();
39
+ };
40
+ }, [cache, restore]);
41
+
42
+ return { session, restore, onLogin: () => setSession('ready'), onLogout: () => setSession('guest') };
43
+ }
@@ -1,35 +1,65 @@
1
+ /**
2
+ * 已登录工作台的公共外壳:导航、当前账号、退出登录、Outlet 和唯一的业务助理。
3
+ * 业务页面经路由模块入口进入 Outlet;系统管理使用独立链接。
4
+ * 助理随页面更新语义快照,账号退出成功后清空查询缓存。
5
+ */
1
6
  // 应用壳组合模块公开入口,只持有导航和会话;表单、筛选、命令留在各业务模块。
2
7
  import { useState } from 'react';
8
+ import { Link, NavLink, Outlet, useLocation } from 'react-router-dom';
3
9
  import { useQueryClient } from '@tanstack/react-query';
4
10
  import { client, currentUser } from '@app/contracts';
5
- import { PurchaseOrdersPage } from '../modules/purchase';
6
- import { InventoryPage } from '../modules/inventory';
7
- import { ApprovalTasksPage, useApprovalTasks } from '../modules/approval';
11
+ import { useApprovalTasks } from '../modules/approval';
12
+ import { errorMessage } from '../shared/lib/error-message';
13
+ import { AssistantScope } from '../shared/ui/assistant-scope';
8
14
 
15
+ /**
16
+ * 渲染工作台公共区域并把子路由放入内容区。
17
+ * @param onLogout SDK 退出成功后通知 app 切换会话状态的回调。
18
+ * 本壳提供固定导航入口;目标路由和服务端分别处理页面访问与真实请求的权限。
19
+ * location.key 标识一次页面导航,用于防止新页面沿用上一张单据的助理上下文。
20
+ */
9
21
  export function WorkspaceLayout({ onLogout }: { onLogout: () => void }) {
10
- const [tab, setTab] = useState<'orders' | 'tasks' | 'stock'>('orders');
22
+ const [error, setError] = useState('');
23
+ const [busy, setBusy] = useState(false);
24
+ const location = useLocation();
25
+ const page = location.pathname.startsWith('/procurement/orders/')
26
+ ? '采购单详情'
27
+ : location.pathname === '/procurement/orders'
28
+ ? '采购单'
29
+ : location.pathname === '/approvals'
30
+ ? '审批待办'
31
+ : location.pathname === '/inventory'
32
+ ? '库存台账'
33
+ : location.pathname === '/workspace'
34
+ ? '工作台'
35
+ : '页面';
11
36
  const tasks = useApprovalTasks();
12
37
  const cache = useQueryClient();
13
38
  return (
39
+ <AssistantScope pageKey={location.key} fallback={{
40
+ context: { page: { id: 'workspace-page', title: page, kind: 'custom', route: location.pathname + location.search } },
41
+ suggestions: ['我在当前页面可以做什么?', '帮我查看待处理的审批'],
42
+ }}>
14
43
  <div className="workspace">
15
44
  <aside>
16
- <a className="brand" href="/">
45
+ <Link className="brand" to="/workspace">
17
46
  cage<span>采购工作台</span>
18
- </a>
47
+ </Link>
19
48
  <span className="nav-caption">工作空间</span>
20
49
  <nav>
21
50
  {(
22
51
  [
23
- ['orders', '01', '采购单'],
24
- ['tasks', '02', '审批待办'],
25
- ['stock', '03', '库存台账'],
52
+ ['/workspace', '00', '工作台'],
53
+ ['/procurement/orders', '01', '采购单'],
54
+ ['/approvals', '02', '审批待办'],
55
+ ['/inventory', '03', '库存台账'],
26
56
  ] as const
27
57
  ).map(([key, no, label]) => (
28
- <button key={key} className={tab === key ? 'selected' : ''} onClick={() => setTab(key)}>
58
+ <NavLink key={key} to={key} className={({ isActive }) => (isActive ? 'selected' : '')}>
29
59
  <span>{no}</span>
30
60
  {label}
31
- {key === 'tasks' && <b>{tasks.data?.length ?? 0}</b>}
32
- </button>
61
+ {key === '/approvals' && <b>{tasks.data?.length ?? 0}</b>}
62
+ </NavLink>
33
63
  ))}
34
64
  </nav>
35
65
  <div className="aside-bottom">
@@ -43,10 +73,15 @@ export function WorkspaceLayout({ onLogout }: { onLogout: () => void }) {
43
73
  </div>
44
74
  <button
45
75
  className="logout"
76
+ disabled={busy}
46
77
  onClick={async () => {
47
- await client.logout();
48
- cache.clear();
49
- onLogout();
78
+ setBusy(true);
79
+ const result = await client.logout();
80
+ setBusy(false);
81
+ if (result.ok) {
82
+ cache.clear();
83
+ onLogout();
84
+ } else setError(errorMessage(result));
50
85
  }}
51
86
  >
52
87
  退出登录
@@ -55,16 +90,20 @@ export function WorkspaceLayout({ onLogout }: { onLogout: () => void }) {
55
90
  </aside>
56
91
  <main className="content">
57
92
  <header>
58
- <span>采购管理 / {tab === 'orders' ? '采购单' : tab === 'tasks' ? '审批待办' : '库存台账'}</span>
93
+ <span>采购管理 / {page}</span>
59
94
  <span className="live-dot">团队工作空间</span>
60
95
  </header>
61
- {tab === 'orders' && <PurchaseOrdersPage pendingTasks={tasks.data?.length} />}
62
- {tab === 'tasks' && <ApprovalTasksPage />}
63
- {tab === 'stock' && <InventoryPage />}
96
+ {error && (
97
+ <p className="error" role="alert">
98
+ {error}
99
+ </p>
100
+ )}
101
+ <Outlet />
64
102
  <div className="page-footer">
65
103
  CAGE / PROCUREMENT WORKSPACE<span>业务操作均受权限与数据范围约束</span>
66
104
  </div>
67
105
  </main>
68
106
  </div>
107
+ </AssistantScope>
69
108
  );
70
109
  }
@@ -1,3 +1,8 @@
1
+ /**
2
+ * 采购 Web 的浏览器启动入口:创建共享查询缓存,将应用路由挂到 root DOM 节点。
3
+ * 契约客户端负责网络与会话协议,页面只在 Provider 内消费 hooks;这里不注册领域或启动后端。
4
+ * 全局样式在此加载,账号切换时的缓存清理由 useSession 和应用壳负责。
5
+ */
1
6
  // 唯一浏览器启动入口:挂载 React、全局 Provider 和样式;业务从 app 组合进入。
2
7
  import { createRoot } from 'react-dom/client';
3
8
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
@@ -1,13 +1,24 @@
1
+ /**
2
+ * 当前账号审批待办的共享查询入口,供审批页及 app 的数量组合复用同一缓存键。
3
+ * 任务分配与实际决策授权均来自服务端,不从角色名称在前端自行推导。
4
+ */
1
5
  import { useQuery } from '@tanstack/react-query';
2
6
  import { client } from '@app/contracts';
3
7
  import { errorMessage } from '../../../shared/lib/error-message';
4
8
 
9
+ /**
10
+ * 待办列表展示所需字段:id 是任务标识,businessKey 是业务记录键,title 为任务标题,createdAt 为创建时间字符串。
11
+ */
5
12
  type Task = { id: string; businessKey: string; title: string; createdAt: string };
6
13
 
7
14
  /**
8
15
  * 审批是框架通用接口,不属于某个聚合的生成方法,因此请求封装在审批模块内。
9
16
  * 待办页面和导航角标复用同一缓存键,调用方不需要了解接口地址或响应形状。
10
17
  */
18
+ /**
19
+ * 在 React Query 中读取审批待办,非 ok 结果转为查询错误。
20
+ * 返回查询状态及 refetch;空数组表示当前结果没有待办,未加载或失败不等同于零条。
21
+ */
11
22
  export function useApprovalTasks() {
12
23
  return useQuery({
13
24
  queryKey: ['tasks'],
@@ -1,2 +1,6 @@
1
+ /**
2
+ * approval 模块的公开入口,对 app 暴露审批待办页与共享待办查询。
3
+ * 外部组合通过本入口导入,页面、组件与内部 helper 的组织由模块自行维护。
4
+ */
1
5
  export { ApprovalTasksPage } from './pages/approval-tasks-page';
2
6
  export { useApprovalTasks } from './hooks/use-approval-tasks';
@@ -1,15 +1,29 @@
1
+ /**
2
+ * 个人审批待办页,展示服务端分配的任务并调用标准审批接口提交结论。
3
+ * 通过 app 注入业务详情链接,避免审批模块直接依赖采购页面文件。
4
+ */
1
5
  // 审批待办独立成页;结论调用框架审批接口,领域约束仍在后端执行。
2
6
  import { client } from '@app/contracts';
7
+ import { Link } from 'react-router-dom';
3
8
  import { useCommand } from '../../../shared/hooks/use-command';
4
9
  import { Notice } from '../../../shared/ui/notice';
5
10
  import { PageHeading } from '../../../shared/ui/page-heading';
6
11
  import { useApprovalTasks } from '../hooks/use-approval-tasks';
12
+ import { AssistantPage } from '../../../shared/ui/assistant-scope';
7
13
 
8
- export function ApprovalTasksPage() {
14
+ /**
15
+ * 查询待办并区分加载、失败与已清空状态;按钮使用 useCommand 共享忙碌及消息反馈。
16
+ * @param orderUrl 由 app 将 businessKey 转为采购详情 URL 的函数。
17
+ * 通过/驳回/退回对应不同后端流程,页面不直接更新单据状态;成功后刷新查询取得真实任务变化。
18
+ */
19
+ export function ApprovalTasksPage({ orderUrl }: { orderUrl: (id: string) => string }) {
9
20
  const tasks = useApprovalTasks();
10
21
  const { run, busy, message, clearMessage } = useCommand();
11
22
  return (
12
23
  <>
24
+ <AssistantPage context={{ page: { id: 'approval-inbox', title: '审批待办', kind: 'list', route: '/approvals' },
25
+ visibleContent: [{ id: 'pending-tasks', text: tasks.data ? `当前待处理审批 ${tasks.data.length} 项,以重新查询的待办为准。` : '审批待办正在读取或暂时不可用。' }],
26
+ }} suggestions={['查看当前待我处理的审批', '通过、驳回和退回修改有什么区别?']} />
13
27
  <PageHeading eyebrow="APPROVAL INBOX" title="审批待办" description="处理分配给你的审批任务。" />
14
28
  {message && <Notice onClose={clearMessage}>{message}</Notice>}
15
29
  <section className="panel">
@@ -26,12 +40,17 @@ export function ApprovalTasksPage() {
26
40
  <p className="mono muted">PO-{task.businessKey.slice(0, 8).toUpperCase()}</p>
27
41
  </div>
28
42
  <div className="actions">
43
+ {/* 单据的页面地址由 app 组合层提供,审批模块不依赖采购页面内部文件。 */}
44
+ <Link className="route-link" to={orderUrl(task.businessKey)}>
45
+ 查看采购单 ↗
46
+ </Link>
29
47
  <button
30
48
  disabled={busy}
31
49
  onClick={() => run(() => client.post(`/api/approval/tasks/${task.id}/reject`), '已驳回')}
32
50
  >
33
51
  驳回
34
52
  </button>
53
+ <button disabled={busy} onClick={() => run(() => client.post(`/api/approval/tasks/${task.id}/return`), '已退回修改')}>退回修改</button>
35
54
  <button
36
55
  disabled={busy}
37
56
  className="primary"
@@ -1 +1,5 @@
1
+ /**
2
+ * auth 模块的公开入口,对 app 暴露登录页。
3
+ * 外部组合通过本入口导入,页面、组件与内部 helper 的组织由模块自行维护。
4
+ */
1
5
  export { LoginPage } from './pages/login-page';