weifuwu 0.87.0 → 0.89.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 (392) hide show
  1. package/README.md +111 -135
  2. package/dist/client/components/ActionSheet/ActionSheet.d.ts +1 -1
  3. package/dist/client/components/AiChat/AiChat.d.ts +3 -4
  4. package/dist/client/components/ChatInput/ChatInput.d.ts +5 -0
  5. package/dist/client/components/CitationCard/CitationCard.d.ts +1 -1
  6. package/dist/client/components/Command/Command.d.ts +1 -1
  7. package/dist/client/components/ContextMenu/ContextMenu.d.ts +1 -1
  8. package/dist/client/components/DatePicker/DatePicker.d.ts +1 -1
  9. package/dist/client/components/Dropdown/Dropdown.d.ts +1 -1
  10. package/dist/client/components/Editor/model/html.d.ts +10 -0
  11. package/dist/client/components/ImageCropper/ImageCropper.d.ts +6 -2
  12. package/dist/client/components/Menu/Menu.d.ts +1 -1
  13. package/dist/client/components/NavMenu/NavMenu.d.ts +1 -1
  14. package/dist/client/components/Popconfirm/Popconfirm.d.ts +1 -1
  15. package/dist/client/components/SlideCanvas/SlideCanvas.d.ts +1 -1
  16. package/dist/client/components/Tour/Tour.d.ts +1 -1
  17. package/dist/client/components/TreeSelect/TreeSelect.d.ts +1 -1
  18. package/dist/client/components/index.js +41 -41
  19. package/dist/client/components/style.css +298 -644
  20. package/dist/client/layout/weifuwu-layout.css +286 -640
  21. package/dist/client/vdom/browser/Browser.d.ts +2 -0
  22. package/dist/client/vdom/commands.d.ts +4 -1
  23. package/dist/client/vdom/context/UIContext.d.ts +8 -0
  24. package/dist/client/vdom/core/diff/attrs.d.ts +10 -2
  25. package/dist/client/vdom/core/field/attributes.d.ts +12 -0
  26. package/dist/client/vdom/core/field/events.d.ts +8 -0
  27. package/dist/client/vdom/core/field/input-sync.d.ts +14 -0
  28. package/dist/client/vdom/core/field/key.d.ts +3 -0
  29. package/dist/client/vdom/core/field/props.d.ts +13 -1
  30. package/dist/client/vdom/core/field/ref.d.ts +6 -0
  31. package/dist/client/vdom/core/field/style.d.ts +7 -1
  32. package/dist/client/vdom/core/node/component.d.ts +3 -4
  33. package/dist/client/vdom/core/node/native.d.ts +6 -1
  34. package/dist/client/vdom/core/patch/index.d.ts +24 -1
  35. package/dist/client/vdom/core/patch/processors.d.ts +8 -1
  36. package/dist/client/vdom/core/protocol.d.ts +45 -0
  37. package/dist/client/vdom/core/router.d.ts +7 -0
  38. package/dist/client/vdom/core/ssr/absorb.d.ts +31 -4
  39. package/dist/client/vdom/core/transform/index.d.ts +6 -6
  40. package/dist/client/vdom/core/v2/cycle.d.ts +54 -0
  41. package/dist/client/vdom/core/v2/diff.d.ts +80 -0
  42. package/dist/client/vdom/core/v2/integrate.d.ts +24 -0
  43. package/dist/client/vdom/core/v2/render.d.ts +28 -0
  44. package/dist/client/vdom/core/v2/schedule.d.ts +33 -0
  45. package/dist/client/vdom/core/v2/serve.d.ts +4 -0
  46. package/dist/client/vdom/core/v2/spy.d.ts +21 -0
  47. package/dist/client/vdom/core/v2/ssr.d.ts +14 -0
  48. package/dist/client/vdom/core/vnode.d.ts +9 -6
  49. package/dist/client/vdom/dev/error-counter.d.ts +27 -0
  50. package/dist/client/vdom/dev/render-health.d.ts +60 -0
  51. package/dist/client/vdom/hooks/chat.d.ts +32 -5
  52. package/dist/client/vdom/hooks/drag-media.d.ts +3 -1
  53. package/dist/client/vdom/hooks/env.d.ts +32 -0
  54. package/dist/client/vdom/hooks/popup-manager.d.ts +21 -0
  55. package/dist/client/vdom/hooks/popup.d.ts +4 -1
  56. package/dist/client/vdom/hooks/stable.d.ts +4 -0
  57. package/dist/client/vdom/hooks/use-observable.d.ts +13 -0
  58. package/dist/client/vdom/index.d.ts +14 -6
  59. package/dist/client/vdom/index.js +4 -7
  60. package/dist/client/vdom/jsx-runtime.js +1 -1
  61. package/dist/client/vdom/middlewares/api.d.ts +8 -0
  62. package/dist/client/vdom/middlewares/auth-i18n.d.ts +7 -0
  63. package/dist/client/vdom/middlewares/ws.d.ts +41 -1
  64. package/dist/client/vdom/observable/index.d.ts +13 -0
  65. package/dist/client/vdom/observable/observable.d.ts +26 -0
  66. package/dist/client/vdom/observable/operators.d.ts +76 -0
  67. package/dist/client/vdom/observable/sources.d.ts +54 -0
  68. package/dist/client/vdom/observable/types.d.ts +45 -0
  69. package/dist/client/vdom/store.d.ts +17 -2
  70. package/dist/client/vdom/testing.js +2 -2
  71. package/dist/server/ai/agent.d.ts +18 -0
  72. package/dist/server/ai/client.d.ts +14 -2
  73. package/dist/server/ai/contracts.d.ts +2 -2
  74. package/dist/server/ai/sse.d.ts +6 -0
  75. package/dist/server/core/collect.d.ts +31 -0
  76. package/dist/server/core/error-counter.d.ts +11 -0
  77. package/dist/server/core/hub.d.ts +2 -0
  78. package/dist/server/core/router.d.ts +12 -9
  79. package/dist/server/db/contracts.d.ts +24 -0
  80. package/dist/server/db/memory-redis.d.ts +3 -4
  81. package/dist/server/db/memory-sql.d.ts +20 -4
  82. package/dist/server/db/postgres-server.d.ts +2 -0
  83. package/dist/server/db/query.d.ts +21 -0
  84. package/dist/server/db/redis-server.d.ts +4 -2
  85. package/dist/server/db/sql-parser.d.ts +2 -1
  86. package/dist/server/email/index.d.ts +2 -0
  87. package/dist/server/index.d.ts +4 -1
  88. package/dist/server/index.js +3927 -1982
  89. package/dist/server/messager/index.d.ts +21 -2
  90. package/dist/server/middleware/compress.d.ts +25 -0
  91. package/dist/server/ui/index.d.ts +8 -1
  92. package/dist/server/user/index.d.ts +4 -0
  93. package/dist/shared/router/chain.d.ts +9 -0
  94. package/dist/shared/router/context.d.ts +35 -0
  95. package/dist/shared/router/ctx-fields.d.ts +20 -0
  96. package/dist/shared/router/pipeline.d.ts +70 -0
  97. package/dist/shared/router/trie.d.ts +11 -3
  98. package/dist/shared/router/types.d.ts +23 -0
  99. package/docs/style-guide.md +44 -41
  100. package/package.json +13 -10
  101. package/content/apps/admin.md +0 -55
  102. package/content/apps/agent-platform.md +0 -35
  103. package/content/apps/auth.md +0 -49
  104. package/content/apps/multi.md +0 -44
  105. package/content/apps/todo.md +0 -51
  106. package/content/backend/ai.md +0 -28
  107. package/content/backend/auth.md +0 -20
  108. package/content/backend/email.md +0 -23
  109. package/content/backend/graphql.md +0 -23
  110. package/content/backend/http.md +0 -23
  111. package/content/backend/limit.md +0 -23
  112. package/content/backend/middleware.md +0 -17
  113. package/content/backend/queue.md +0 -23
  114. package/content/backend/redis.md +0 -26
  115. package/content/backend/router.md +0 -23
  116. package/content/backend/schedule.md +0 -23
  117. package/content/backend/sql.md +0 -27
  118. package/content/backend/sse.md +0 -26
  119. package/content/backend/ws.md +0 -26
  120. package/content/capabilities/app-node.md +0 -21
  121. package/content/capabilities/data.md +0 -21
  122. package/content/capabilities/events.md +0 -21
  123. package/content/capabilities/hooks.md +0 -22
  124. package/content/capabilities/i18n.md +0 -21
  125. package/content/capabilities/popup.md +0 -21
  126. package/content/capabilities/render-only.md +0 -23
  127. package/content/capabilities/router.md +0 -22
  128. package/content/capabilities/self-id.md +0 -21
  129. package/content/capabilities/store.md +0 -21
  130. package/content/capabilities/theme.md +0 -21
  131. package/content/capabilities/two-phase.md +0 -21
  132. package/content/components/accordion.md +0 -50
  133. package/content/components/actionsheet.md +0 -46
  134. package/content/components/affix.md +0 -51
  135. package/content/components/aichat.md +0 -57
  136. package/content/components/alert.md +0 -52
  137. package/content/components/alertgroup.md +0 -45
  138. package/content/components/anchor.md +0 -52
  139. package/content/components/app.md +0 -37
  140. package/content/components/approvalcard.md +0 -56
  141. package/content/components/appshell.md +0 -50
  142. package/content/components/aspectratio.md +0 -47
  143. package/content/components/authpage.md +0 -61
  144. package/content/components/autocomplete-v2.md +0 -40
  145. package/content/components/autocomplete.md +0 -56
  146. package/content/components/avatar.md +0 -51
  147. package/content/components/avatargroup.md +0 -47
  148. package/content/components/backtop.md +0 -53
  149. package/content/components/badge.md +0 -55
  150. package/content/components/breadcrumb.md +0 -49
  151. package/content/components/button.md +0 -63
  152. package/content/components/calendar-v2.md +0 -40
  153. package/content/components/calendar.md +0 -50
  154. package/content/components/card.md +0 -58
  155. package/content/components/carousel.md +0 -52
  156. package/content/components/cascader-v2.md +0 -39
  157. package/content/components/cascader.md +0 -54
  158. package/content/components/chart.md +0 -53
  159. package/content/components/chatinput.md +0 -63
  160. package/content/components/checkbox.md +0 -51
  161. package/content/components/checkboxgroup.md +0 -52
  162. package/content/components/citationcard.md +0 -48
  163. package/content/components/codeblock.md +0 -48
  164. package/content/components/codeeditor.md +0 -47
  165. package/content/components/collapse.md +0 -49
  166. package/content/components/colorpicker.md +0 -50
  167. package/content/components/command.md +0 -50
  168. package/content/components/confirm.md +0 -57
  169. package/content/components/contextmenu.md +0 -48
  170. package/content/components/copybutton.md +0 -51
  171. package/content/components/datepicker.md +0 -52
  172. package/content/components/descriptions-v2.md +0 -39
  173. package/content/components/descriptions.md +0 -52
  174. package/content/components/diffview-v2.md +0 -39
  175. package/content/components/diffview.md +0 -50
  176. package/content/components/divider.md +0 -48
  177. package/content/components/drawer.md +0 -55
  178. package/content/components/dropdown.md +0 -53
  179. package/content/components/editor.md +0 -49
  180. package/content/components/emptystate.md +0 -51
  181. package/content/components/exportcsv.md +0 -38
  182. package/content/components/field.md +0 -54
  183. package/content/components/filepreview-office.md +0 -37
  184. package/content/components/filepreview.md +0 -49
  185. package/content/components/filetree.md +0 -56
  186. package/content/components/fileupload-v2.md +0 -39
  187. package/content/components/fileupload.md +0 -57
  188. package/content/components/floatbutton.md +0 -52
  189. package/content/components/form-v2.md +0 -41
  190. package/content/components/form.md +0 -60
  191. package/content/components/grid.md +0 -51
  192. package/content/components/highlight-v2.md +0 -39
  193. package/content/components/highlight.md +0 -46
  194. package/content/components/hovercard.md +0 -51
  195. package/content/components/icon.md +0 -50
  196. package/content/components/imagecropper.md +0 -45
  197. package/content/components/img.md +0 -56
  198. package/content/components/infinitescroll-v2.md +0 -40
  199. package/content/components/infinitescroll.md +0 -54
  200. package/content/components/input.md +0 -65
  201. package/content/components/inputnumber.md +0 -58
  202. package/content/components/inview.md +0 -56
  203. package/content/components/jsonschemaform.md +0 -53
  204. package/content/components/jsonviewer-v2.md +0 -39
  205. package/content/components/jsonviewer.md +0 -49
  206. package/content/components/kanban.md +0 -46
  207. package/content/components/label.md +0 -48
  208. package/content/components/layout.md +0 -54
  209. package/content/components/layoutcontent.md +0 -43
  210. package/content/components/layoutheader.md +0 -43
  211. package/content/components/layoutsider.md +0 -43
  212. package/content/components/link.md +0 -52
  213. package/content/components/list.md +0 -44
  214. package/content/components/loading.md +0 -45
  215. package/content/components/logviewer-v2.md +0 -39
  216. package/content/components/logviewer.md +0 -53
  217. package/content/components/markdown.md +0 -51
  218. package/content/components/markdowneditor.md +0 -47
  219. package/content/components/math.md +0 -42
  220. package/content/components/mentions-v2.md +0 -39
  221. package/content/components/mentions.md +0 -52
  222. package/content/components/menu.md +0 -56
  223. package/content/components/menubar.md +0 -44
  224. package/content/components/messagebubble.md +0 -50
  225. package/content/components/modal.md +0 -59
  226. package/content/components/navmenu.md +0 -47
  227. package/content/components/notification.md +0 -51
  228. package/content/components/pageheader.md +0 -53
  229. package/content/components/pagination.md +0 -49
  230. package/content/components/paragraph.md +0 -45
  231. package/content/components/passwordinput.md +0 -57
  232. package/content/components/pininput-v2.md +0 -39
  233. package/content/components/pininput.md +0 -50
  234. package/content/components/pipeline.md +0 -49
  235. package/content/components/popconfirm.md +0 -58
  236. package/content/components/popover.md +0 -61
  237. package/content/components/progressbar.md +0 -50
  238. package/content/components/prompttemplate.md +0 -49
  239. package/content/components/qrcode.md +0 -50
  240. package/content/components/radiogroup.md +0 -53
  241. package/content/components/rate.md +0 -53
  242. package/content/components/reasoningblock.md +0 -47
  243. package/content/components/relationgraph.md +0 -52
  244. package/content/components/resizable.md +0 -53
  245. package/content/components/result.md +0 -49
  246. package/content/components/scrollbar.md +0 -49
  247. package/content/components/searchinput.md +0 -51
  248. package/content/components/segmentedcontrol.md +0 -59
  249. package/content/components/select-searchable.md +0 -47
  250. package/content/components/select.md +0 -66
  251. package/content/components/sessionlist.md +0 -52
  252. package/content/components/sheetgrid.md +0 -44
  253. package/content/components/skeleton.md +0 -55
  254. package/content/components/slidecanvas.md +0 -44
  255. package/content/components/slider.md +0 -62
  256. package/content/components/sortablelist.md +0 -39
  257. package/content/components/space.md +0 -52
  258. package/content/components/sparkline.md +0 -52
  259. package/content/components/statcard-countdown.md +0 -39
  260. package/content/components/statcard.md +0 -56
  261. package/content/components/steps.md +0 -48
  262. package/content/components/switch.md +0 -50
  263. package/content/components/tabbar.md +0 -45
  264. package/content/components/table-v2.md +0 -40
  265. package/content/components/table.md +0 -66
  266. package/content/components/tabs.md +0 -56
  267. package/content/components/tag.md +0 -51
  268. package/content/components/tagsinput-v2.md +0 -39
  269. package/content/components/tagsinput.md +0 -54
  270. package/content/components/text.md +0 -45
  271. package/content/components/textarea.md +0 -57
  272. package/content/components/themeswitch.md +0 -69
  273. package/content/components/timeline.md +0 -50
  274. package/content/components/title.md +0 -45
  275. package/content/components/toast.md +0 -52
  276. package/content/components/toggle-togglegroup.md +0 -52
  277. package/content/components/togglegroup.md +0 -47
  278. package/content/components/toolcallcard.md +0 -51
  279. package/content/components/tooltip.md +0 -50
  280. package/content/components/tour.md +0 -50
  281. package/content/components/transfer.md +0 -52
  282. package/content/components/tree-v2.md +0 -39
  283. package/content/components/tree.md +0 -59
  284. package/content/components/treeselect.md +0 -54
  285. package/content/components/typography.md +0 -51
  286. package/content/components/videoplayer.md +0 -52
  287. package/content/components/virtuallist.md +0 -52
  288. package/content/components/virtualtable-v2.md +0 -39
  289. package/content/components/virtualtable.md +0 -55
  290. package/content/components/watermark.md +0 -53
  291. package/content/components/wave.md +0 -43
  292. package/content/guides/ai-chat-family.md +0 -24
  293. package/content/guides/choose.md +0 -67
  294. package/content/guides/component-model.md +0 -32
  295. package/content/guides/component-standards.md +0 -123
  296. package/content/guides/components-guide.md +0 -813
  297. package/content/guides/custom-component.md +0 -321
  298. package/content/guides/data-guide.md +0 -281
  299. package/content/guides/file-preview-family.md +0 -18
  300. package/content/guides/frontend.md +0 -968
  301. package/content/guides/layout-choice.md +0 -64
  302. package/content/guides/layout-guide.md +0 -241
  303. package/content/guides/middleware.md +0 -459
  304. package/content/guides/mobile-guide.md +0 -105
  305. package/content/guides/page-building.md +0 -98
  306. package/content/guides/production.md +0 -37
  307. package/content/guides/quality.md +0 -60
  308. package/content/guides/realtime-guide.md +0 -296
  309. package/content/guides/render-only.md +0 -44
  310. package/content/guides/saas-guide.md +0 -253
  311. package/content/guides/server-guide.md +0 -359
  312. package/content/guides/start.md +0 -41
  313. package/content/guides/styling.md +0 -154
  314. package/content/guides/ui-dom-guide.md +0 -157
  315. package/content/index.json +0 -4344
  316. package/content/index.md +0 -181
  317. package/content/layout/align.md +0 -20
  318. package/content/layout/anchor.md +0 -19
  319. package/content/layout/app-shell.md +0 -23
  320. package/content/layout/border.md +0 -20
  321. package/content/layout/center.md +0 -19
  322. package/content/layout/cluster.md +0 -19
  323. package/content/layout/container.md +0 -19
  324. package/content/layout/fill.md +0 -19
  325. package/content/layout/grid.md +0 -19
  326. package/content/layout/hidden.md +0 -22
  327. package/content/layout/layer.md +0 -19
  328. package/content/layout/position.md +0 -22
  329. package/content/layout/row.md +0 -23
  330. package/content/layout/safe-area.md +0 -20
  331. package/content/layout/scroll.md +0 -21
  332. package/content/layout/spacing.md +0 -22
  333. package/content/layout/split.md +0 -19
  334. package/content/layout/stack.md +0 -19
  335. package/content/layout/surface.md +0 -23
  336. package/content/layout/text.md +0 -22
  337. package/content/patterns/app-shell.md +0 -34
  338. package/content/patterns/dashboard.md +0 -36
  339. package/content/patterns/data-screen.md +0 -30
  340. package/content/patterns/detail-page.md +0 -31
  341. package/content/patterns/docs.md +0 -34
  342. package/content/patterns/focus-task.md +0 -34
  343. package/content/patterns/landing.md +0 -35
  344. package/content/patterns/list-page.md +0 -32
  345. package/content/patterns/mobile.md +0 -31
  346. package/content/patterns/settings-page.md +0 -33
  347. package/content/patterns/workspace.md +0 -32
  348. package/dist/cli/content-sync.test.d.ts +0 -1
  349. package/dist/cli/docs-cli.test.d.ts +0 -1
  350. package/dist/cli/docs.d.ts +0 -2
  351. package/dist/cli/docs.mjs +0 -10961
  352. package/dist/client/vdom/core/build.d.ts +0 -36
  353. package/dist/client/vdom/core/diff/children.d.ts +0 -29
  354. package/dist/client/vdom/core/diff/index.d.ts +0 -22
  355. package/dist/client/vdom/core/diff/output.d.ts +0 -30
  356. package/dist/client/vdom/core/diff/same.d.ts +0 -22
  357. package/dist/client/vdom/core/serve.d.ts +0 -75
  358. package/dist/client/vdom/core/ssr/index.d.ts +0 -25
  359. package/examples/apps/admin/README.md +0 -23
  360. package/examples/apps/admin/api.ts +0 -27
  361. package/examples/apps/admin/app.tsx +0 -144
  362. package/examples/apps/admin/main.tsx +0 -8
  363. package/examples/apps/admin/server.ts +0 -37
  364. package/examples/apps/auth/README.md +0 -23
  365. package/examples/apps/auth/api.ts +0 -49
  366. package/examples/apps/auth/app.tsx +0 -137
  367. package/examples/apps/auth/main.tsx +0 -8
  368. package/examples/apps/auth/server.ts +0 -37
  369. package/examples/apps/multi/README.md +0 -23
  370. package/examples/apps/multi/app.tsx +0 -83
  371. package/examples/apps/multi/main.tsx +0 -8
  372. package/examples/apps/multi/server.ts +0 -33
  373. package/examples/apps/todo/README.md +0 -23
  374. package/examples/apps/todo/api.ts +0 -26
  375. package/examples/apps/todo/app.tsx +0 -128
  376. package/examples/apps/todo/main.tsx +0 -9
  377. package/examples/apps/todo/server.ts +0 -39
  378. package/examples/hello-world/README.md +0 -9
  379. package/examples/hello-world/client.ts +0 -14
  380. package/examples/hello-world/routes.tsx +0 -26
  381. package/examples/hello-world/server.ts +0 -46
  382. package/examples/patterns/AppShell.tsx +0 -224
  383. package/examples/patterns/Dashboard.tsx +0 -153
  384. package/examples/patterns/DataScreen.tsx +0 -104
  385. package/examples/patterns/DetailPage.tsx +0 -79
  386. package/examples/patterns/Docs.tsx +0 -105
  387. package/examples/patterns/FocusTask.tsx +0 -67
  388. package/examples/patterns/Landing.tsx +0 -90
  389. package/examples/patterns/ListPage.tsx +0 -77
  390. package/examples/patterns/Mobile.tsx +0 -154
  391. package/examples/patterns/SettingsPage.tsx +0 -98
  392. package/examples/patterns/SplitWorkspace.tsx +0 -113
@@ -1,46 +0,0 @@
1
- /**
2
- * hello-world——最小可运行起步项目(新手第一步,复制本目录即跑)
3
- *
4
- * 与 README「快速开始」模式 A 对应——三文件落地版:
5
- * server.ts 后端:SPA 外壳 + /api/hello 数据端点
6
- * routes.tsx 路由声明:两阶段异步组件(await ctx.data → 返回视图)
7
- * client.ts 客户端入口:createRouter 接管渲染
8
- *
9
- * 跑起来:node server.ts → http://localhost:3400
10
- */
11
- import { serve, Router, ui, cors } from 'weifuwu'
12
- import { resolve, dirname } from 'node:path'
13
- import { fileURLToPath } from 'node:url'
14
-
15
- const __dirname = dirname(fileURLToPath(import.meta.url))
16
-
17
- const router = new Router()
18
- router.use(cors())
19
- router.use(ui()) // 注入 ctx.ui.html / ctx.ui.js / ctx.ui.css
20
-
21
- // SPA 外壳(空 root + 前端 bundle)
22
- router.get('/', (req, ctx) => ctx.ui.html`
23
- <!doctype html>
24
- <html>
25
- <head>
26
- <meta charset="UTF-8">
27
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
28
- <link rel="stylesheet" href="/components.css">
29
- <title>weifuwu hello-world</title>
30
- </head>
31
- <body>
32
- <div id="root"></div>
33
- <script src="/static/app.js"></script>
34
- </body>
35
- </html>
36
- `)
37
- router.get('/static/app.js', (req, ctx) => ctx.ui.js(resolve(__dirname, 'client.ts')))
38
-
39
- // 样式自托管(node_modules/weifuwu/components/style.css——包内 CSS,零外部依赖/CDN)
40
- router.get('/components.css', (req, ctx) => ctx.ui.css('weifuwu/components/style.css'))
41
-
42
- // 数据端点(ctx.data 消费——SPA 下真 fetch,SSR 下服务端直取)
43
- router.get('/api/hello', () => Response.json({ msg: '你好,weifuwu!' }))
44
-
45
- serve(router, { port: 3400 })
46
- console.log('hello-world → http://localhost:3400')
@@ -1,224 +0,0 @@
1
- import type { Component } from 'weifuwu/vdom'
2
- import { Button, PageHeader, Table, Badge, Icon, Divider, Pagination, StatCard, Space, Card, Text } from 'weifuwu/components'
3
-
4
- // ─────────────────────────────────────────────────────────────
5
- // 模式 1:后台应用壳(App Shell)
6
- //
7
- // 最经典的后台布局:左侧可折叠导航 + 右侧内容区。
8
- // 100% 使用 weifuwu/layout 原语 + weifuwu/components 组件:
9
- // - wf-app-shell / wf-sidebar / wf-nav / wf-nav--collapsed / wf-main
10
- // - 折叠 = --wf-sidebar-width 收窄 + wf-nav--collapsed(原语组合)
11
- // 复制此文件即可得到一个标准后台。
12
- // ─────────────────────────────────────────────────────────────
13
-
14
- const NAV = [
15
- { key: 'dashboard', icon: 'dashboard', label: '仪表盘' },
16
- { key: 'orders', icon: 'box', label: '订单管理' },
17
- { key: 'users', icon: 'users', label: '用户管理' },
18
- { key: 'goods', icon: 'tag', label: '商品管理' },
19
- { key: 'settings', icon: 'settings', label: '系统设置' },
20
- ]
21
-
22
- // 5 个视图内容(导航联动——每视图独立 PageHeader + 内容)
23
- const USERS = [
24
- { id: 'U-001', name: '张伟', role: '管理员', email: 'zhang@acme.cn', v: 'primary' },
25
- { id: 'U-002', name: '李娜', role: '运营', email: 'li@acme.cn', v: 'default' },
26
- { id: 'U-003', name: '王强', role: '开发', email: 'wang@acme.cn', v: 'default' },
27
- { id: 'U-004', name: '赵敏', role: '客服', email: 'zhao@acme.cn', v: 'warning' },
28
- ]
29
-
30
- const GOODS = [
31
- { id: 'G-101', name: '无线键盘', stock: 320, price: '¥199', status: '在售', v: 'success' },
32
- { id: 'G-102', name: '机械鼠标', stock: 58, price: '¥89', status: '补货中', v: 'warning' },
33
- { id: 'G-103', name: '显示器', stock: 12, price: '¥1299', status: '售罄', v: 'danger' },
34
- { id: 'G-104', name: '扩展坞', stock: 200, price: '¥159', status: '在售', v: 'success' },
35
- ]
36
-
37
- export const AppShell: Component = async (_init, ctx) => {
38
- // render-only:内部状态 let + 显式 render(design 归档)
39
- let collapsed = false
40
- let nav = 'dashboard'
41
- let page = 1
42
- const rerender = () => ctx.render()
43
-
44
- // 订单数据(分页演示——12 条 → 每页 5 条)
45
- const ORDERS_ALL = Array.from({ length: 12 }, (_, i) => ({
46
- id: `A-${2000 + i}`,
47
- customer: ['张伟', '李娜', '王强', '赵敏', '陈晨', '刘洋', '孙丽', '周杰', '吴磊', '郑爽', '钱进', '冯刚'][i],
48
- amount: `¥${(Math.round(Math.random() * 300) + 100) * 10}`,
49
- status: ['已支付', '待发货', '已完成', '已取消'][i % 4],
50
- v: (['success', 'warning', 'default', 'danger'] as const)[i % 4],
51
- }))
52
- return async () => (
53
- <div
54
- class="wf-app-shell wf-rounded-lg"
55
- style={{ height: 'calc(100vh - 48px)', overflow: 'hidden', '--wf-sidebar-width': collapsed ? '64px' : '240px' }}
56
- >
57
- {/* ── 左侧导航栏 ── */}
58
- <aside class="wf-sidebar">
59
- <div class="wf-sidebar-header wf-between">
60
- {collapsed ? (
61
- <Icon name="zap" size={18} className="wf-text-primary" />
62
- ) : (
63
- <Space>
64
- <Icon name="zap" size={18} className="wf-text-primary" />
65
- <b class="wf-text-bold">Acme 管理台</b>
66
- </Space>
67
- )}
68
- <Button
69
- size="sm"
70
- variant="ghost"
71
- title={collapsed ? '展开侧栏' : '折叠侧栏'}
72
- onClick={() => { collapsed = !collapsed; rerender() }}
73
- >
74
- <Icon name={collapsed ? 'chevron-right' : 'chevron-left'} size={14} />
75
- </Button>
76
- </div>
77
- <div class="wf-sidebar-body">
78
- <nav class={`wf-nav${collapsed ? ' wf-nav--collapsed' : ''}`}>
79
- {NAV.map((n) => (
80
- <a
81
- key={n.key}
82
- href="#/app-shell"
83
- class={`wf-nav-item wf-pointer${nav === n.key ? ' wf-nav-item--active' : ''}`}
84
- title={collapsed ? n.label : undefined}
85
- onClick={() => { nav = n.key; rerender() }}
86
- >
87
- <span class="wf-nav-icon"><Icon name={n.icon as any} size={16} /></span>
88
- <span class="wf-nav-label">{n.label}</span>
89
- </a>
90
- ))}
91
- </nav>
92
- </div>
93
- <div class="wf-sidebar-footer">
94
- {collapsed
95
- ? <Icon name="shield" size={14} className="wf-text-tertiary" />
96
- : <span class="wf-text-tertiary wf-text-xs">v2.4.0 · 内部系统</span>}
97
- </div>
98
- </aside>
99
-
100
- {/* ── 右侧主区 ── */}
101
- <main class="wf-main">
102
- {/* 顶栏 */}
103
- <div class="wf-between wf-p-md wf-border-b">
104
- <Space>
105
- <Button size="sm" variant="ghost"><Icon name="star" size={14} /> 收藏</Button>
106
- <Button size="sm" variant="ghost"><Icon name="bell" size={14} /> 通知</Button>
107
- </Space>
108
- <Space>
109
- <span class="wf-text-secondary wf-text-sm">管理员</span>
110
- <Badge variant="primary">角色</Badge>
111
- </Space>
112
- </div>
113
-
114
- {/* 内容区(按导航切换) */}
115
- <div class="wf-main wf-p-lg wf-scroll">
116
- {nav === 'dashboard' && (
117
- <>
118
- <PageHeader title="仪表盘" sub="经营概览" display>
119
- <Button variant="primary" onClick={() => { nav = 'orders'; rerender() }}><Icon name="plus" size={14} /> 去下单</Button>
120
- </PageHeader>
121
- <div class="wf-grid" style={{ '--wf-cols': 'repeat(auto-fill, minmax(220px, 1fr))' }}>
122
- <StatCard label="今日订单" value="128" trend="up" trendLabel="+12% 昨日" icon={<Icon name="box" size={24} className="wf-text-primary" />} />
123
- <StatCard label="待发货" value="23" trend="down" trendLabel="-5% 昨日" icon={<Icon name="inbox" size={24} className="wf-text-primary" />} />
124
- <StatCard label="销售额" value="¥42,860" trend="up" trendLabel="+8.6% 昨日" icon={<Icon name="bar-chart" size={24} className="wf-text-primary" />} />
125
- <StatCard label="客户数" value="1,024" trend="up" trendLabel="+3.2% 昨日" icon={<Icon name="users" size={24} className="wf-text-primary" />} />
126
- </div>
127
- </>
128
- )}
129
- {nav === 'orders' && (
130
- <>
131
- <PageHeader title="订单管理" sub="查看和处理所有订单" display>
132
- <Button variant="primary"><Icon name="plus" size={14} /> 新建订单</Button>
133
- </PageHeader>
134
-
135
- <div class="wf-grid wf-mt-md" style={{ '--wf-cols': 'repeat(auto-fill, minmax(220px, 1fr))' }}>
136
- <StatCard label="今日订单" value="128" trend="up" trendLabel="+12% 昨日" icon={<Icon name="box" size={24} className="wf-text-primary" />} />
137
- <StatCard label="待发货" value="23" trend="down" trendLabel="-5% 昨日" icon={<Icon name="inbox" size={24} className="wf-text-primary" />} />
138
- <StatCard label="销售额" value="¥42,860" trend="up" trendLabel="+8.6% 昨日" icon={<Icon name="bar-chart" size={24} className="wf-text-primary" />} />
139
- </div>
140
-
141
- <Divider />
142
-
143
- <Card outlined>
144
- <Table
145
- data={ORDERS_ALL.slice((page - 1) * 5, page * 5)}
146
- columns={[
147
- { key: 'id', label: '订单号' },
148
- { key: 'customer', label: '客户' },
149
- { key: 'amount', label: '金额' },
150
- { key: 'status', label: '状态', render: (v, row) => <Badge variant={row.v}>{v}</Badge> },
151
- ]}
152
- />
153
- <div class="wf-p-md wf-between">
154
- <Text className="wf-text-sm">共 {ORDERS_ALL.length} 条</Text>
155
- <Pagination total={ORDERS_ALL.length} page={page} pageSize={5} onChange={(p) => { page = p; rerender() }} />
156
- </div>
157
- </Card>
158
- </>
159
- )}
160
- {nav === 'users' && (
161
- <>
162
- <PageHeader title="用户管理" sub="平台用户与角色" display>
163
- <Button variant="primary"><Icon name="plus" size={14} /> 邀请用户</Button>
164
- </PageHeader>
165
- <Card outlined>
166
- <Table
167
- data={USERS}
168
- columns={[
169
- { key: 'id', label: '用户 ID' },
170
- { key: 'name', label: '姓名' },
171
- { key: 'role', label: '角色', render: (v, row) => <Badge variant={row.v}>{v}</Badge> },
172
- { key: 'email', label: '邮箱' },
173
- ]}
174
- />
175
- </Card>
176
- </>
177
- )}
178
- {nav === 'goods' && (
179
- <>
180
- <PageHeader title="商品管理" sub="库存与销售状态" display>
181
- <Button variant="primary"><Icon name="plus" size={14} /> 上架商品</Button>
182
- </PageHeader>
183
- <Card outlined>
184
- <Table
185
- data={GOODS}
186
- columns={[
187
- { key: 'id', label: '商品 ID' },
188
- { key: 'name', label: '名称' },
189
- { key: 'stock', label: '库存' },
190
- { key: 'price', label: '价格' },
191
- { key: 'status', label: '状态', render: (v, row) => <Badge variant={row.v}>{v}</Badge> },
192
- ]}
193
- />
194
- </Card>
195
- </>
196
- )}
197
- {nav === 'settings' && (
198
- <>
199
- <PageHeader title="系统设置" sub="基础配置" display>
200
- <Button variant="primary"><Icon name="check" size={14} /> 保存</Button>
201
- </PageHeader>
202
- <Card outlined>
203
- <div class="wf-stack wf-gap-md">
204
- {[
205
- ['站点名称', 'Acme 管理台'],
206
- ['默认语言', '中文(简体)'],
207
- ['数据保留', '90 天'],
208
- ['时区', 'Asia/Shanghai'],
209
- ].map(([k, v]) => (
210
- <div key={k} class="wf-between wf-p-md wf-border-b">
211
- <span class="wf-text-secondary">{k}</span>
212
- <b>{v}</b>
213
- </div>
214
- ))}
215
- </div>
216
- </Card>
217
- </>
218
- )}
219
- </div>
220
- </main>
221
- </div>
222
- )
223
- }
224
-
@@ -1,153 +0,0 @@
1
- import type { Component } from 'weifuwu/vdom'
2
- import { Title, Text, StatCard, PageHeader, ProgressBar, SegmentedControl, Switch, Table, Badge, Card, Divider, Icon, Space } from 'weifuwu/components'
3
-
4
- // ─────────────────────────────────────────────────────────────
5
- // 模式 3:仪表盘(Dashboard)
6
- //
7
- // 响应式卡片网格:KPI 行(StatCard)+ 数据表 + 侧栏概览。
8
- // SegmentedControl 切换时间范围 → KPI/表格数据联动(let + render())。
9
- // 100% 原语 + 组件:wf-grid(--wf-cols 控制列数)窄屏自动单列。
10
- // ─────────────────────────────────────────────────────────────
11
-
12
- interface PeriodData {
13
- kpis: { label: string; value: string; trend: 'up' | 'down'; trendLabel: string; icon: string }[]
14
- rows: { name: string; sales: string; growth: string; status: string; v: 'success' | 'default' | 'warning' | 'danger' }[]
15
- total: string
16
- }
17
-
18
- const DATA: Record<string, PeriodData> = {
19
- '7d': {
20
- kpis: [
21
- { label: '总营收', value: '¥32.4万', trend: 'up' as const, trendLabel: '8.2% 环比', icon: 'bar-chart' },
22
- { label: '活跃用户', value: '2,156', trend: 'up' as const, trendLabel: '5.1% 环比', icon: 'users' },
23
- { label: '转化率', value: '7.4%', trend: 'up' as const, trendLabel: '1.2% 环比', icon: 'trending-up' },
24
- { label: '客单价', value: '¥312', trend: 'up' as const, trendLabel: '3.8% 环比', icon: 'tag' },
25
- ],
26
- rows: [
27
- { name: '新品 B', sales: '¥12.8万', growth: '22.6%', status: '热销', v: 'success' },
28
- { name: '商品 A', sales: '¥10.5万', growth: '15.2%', status: '热销', v: 'success' },
29
- { name: '商品 C', sales: '¥6.3万', growth: '2.4%', status: '稳定', v: 'default' },
30
- ],
31
- total: '¥32,480',
32
- },
33
- '30d': {
34
- kpis: [
35
- { label: '总营收', value: '¥128.6万', trend: 'up' as const, trendLabel: '12.4% 环比', icon: 'bar-chart' },
36
- { label: '活跃用户', value: '8,432', trend: 'up' as const, trendLabel: '3.2% 环比', icon: 'users' },
37
- { label: '转化率', value: '6.8%', trend: 'up' as const, trendLabel: '0.5% 环比', icon: 'trending-up' },
38
- { label: '客单价', value: '¥286', trend: 'down' as const, trendLabel: '2.1% 环比', icon: 'tag' },
39
- ],
40
- rows: [
41
- { name: '商品 A', sales: '¥42.8万', growth: '18.2%', status: '热销', v: 'success' },
42
- { name: '商品 B', sales: '¥36.5万', growth: '9.7%', status: '稳定', v: 'default' },
43
- { name: '商品 C', sales: '¥21.3万', growth: '-4.1%', status: '下滑', v: 'warning' },
44
- { name: '商品 D', sales: '¥15.9万', growth: '22.6%', status: '热销', v: 'success' },
45
- ],
46
- total: '¥1,286,400',
47
- },
48
- '90d': {
49
- kpis: [
50
- { label: '总营收', value: '¥356.2万', trend: 'up' as const, trendLabel: '18.6% 环比', icon: 'bar-chart' },
51
- { label: '活跃用户', value: '24,680', trend: 'up' as const, trendLabel: '9.8% 环比', icon: 'users' },
52
- { label: '转化率', value: '6.1%', trend: 'down' as const, trendLabel: '0.3% 环比', icon: 'trending-up' },
53
- { label: '客单价', value: '¥268', trend: 'down' as const, trendLabel: '4.2% 环比', icon: 'tag' },
54
- ],
55
- rows: [
56
- { name: '商品 B', sales: '¥98.5万', growth: '31.4%', status: '热销', v: 'success' },
57
- { name: '商品 A', sales: '¥86.2万', growth: '12.8%', status: '稳定', v: 'default' },
58
- { name: '新品 D', sales: '¥52.1万', growth: '45.2%', status: '热销', v: 'success' },
59
- { name: '商品 C', sales: '¥38.9万', growth: '-6.3%', status: '下滑', v: 'warning' },
60
- ],
61
- total: '¥3,562,000',
62
- },
63
- }
64
-
65
- export const Dashboard: Component = async (_init, ctx) => {
66
- let period = '30d'
67
- let showGoal = true
68
- const rerender = () => ctx.render()
69
-
70
- return async () => {
71
- const data = DATA[period] ?? DATA['30d']
72
- return (
73
- <div class="wf-stack wf-gap-lg wf-p-lg wf-scroll" style={{ minHeight: 'calc(100vh - 48px)' }}>
74
- {/* 页头 + 时间范围切换(wf-row 提供 wrap——窄屏切换器折行,不挤压标题) */}
75
- <div class="wf-row wf-between">
76
- <PageHeader title="经营仪表盘" sub="实时经营数据 · 自动刷新" />
77
- <SegmentedControl
78
- value={period}
79
- onChange={(v) => { period = v; rerender() }}
80
- options={[
81
- { value: '7d', label: '近 7 天' },
82
- { value: '30d', label: '近 30 天' },
83
- { value: '90d', label: '近 90 天' },
84
- ]}
85
- />
86
- </div>
87
-
88
- {/* KPI 行:wf-grid 自适应(窄屏自动单列) */}
89
- <div class="wf-grid" style={{ '--wf-cols': 'repeat(auto-fill, minmax(240px, 1fr))' }}>
90
- {data.kpis.map((k) => (
91
- <StatCard key={k.label} label={k.label} value={k.value} trend={k.trend} trendLabel={k.trendLabel} icon={<Icon name={k.icon as any} size={24} className="wf-text-primary" />} />
92
- ))}
93
- </div>
94
-
95
- {/* 内容区:销售排行 + 侧栏 */}
96
- <div class="wf-grid" style={{ '--wf-cols': '2fr 1fr', alignItems: 'start' }}>
97
- <Card outlined>
98
- <Space direction="vertical">
99
- <Title level={4}>商品销售排行 · {period}</Title>
100
- <Table
101
- data={data.rows}
102
- columns={[
103
- { key: 'name', label: '商品' },
104
- { key: 'sales', label: '销售额' },
105
- { key: 'growth', label: '增长率' },
106
- { key: 'status', label: '状态', render: (v, row) => <Badge variant={row.v}>{v}</Badge> },
107
- ]}
108
- />
109
- </Space>
110
- </Card>
111
-
112
- {/* 侧栏概览 */}
113
- <div class="wf-stack wf-gap-md">
114
- <Card outlined>
115
- <Space direction="vertical" size="sm">
116
- <Text type="secondary" className="wf-text-sm">本期总额</Text>
117
- <Text strong className="wf-text-lg">{data.total}</Text>
118
- <Text type="success" className="wf-text-sm">↑ 18.6% vs 上一期</Text>
119
- </Space>
120
- </Card>
121
- <Card outlined>
122
- <Space direction="vertical" size="sm">
123
- <div class="wf-between">
124
- <Text type="secondary" className="wf-text-sm">季度目标</Text>
125
- <Switch
126
- label="展示"
127
- checked={showGoal}
128
- onChange={(v) => { showGoal = v; rerender() }}
129
- />
130
- </div>
131
- {showGoal && (
132
- <Space direction="vertical" size="sm">
133
- <ProgressBar value={78} max={100} label="达成率" showValue />
134
- <Text type="secondary" className="wf-text-xs">距离 ¥150 万目标还差 ¥21.4 万</Text>
135
- </Space>
136
- )}
137
- </Space>
138
- </Card>
139
- <Card outlined>
140
- <Space direction="vertical" size="sm">
141
- <Text type="secondary" className="wf-text-sm">数据刷新</Text>
142
- <Text className="wf-text-sm">切换时间范围观察数据联动(let + render() 状态)</Text>
143
- </Space>
144
- </Card>
145
- <Divider />
146
- <Text type="secondary" className="wf-text-sm">本页展示了 wf-grid + StatCard + $ 状态组合——无需任何媒体查询即可响应式。</Text>
147
- </div>
148
- </div>
149
- </div>
150
- )
151
- }
152
- }
153
-
@@ -1,104 +0,0 @@
1
- import type { Component } from 'weifuwu/vdom'
2
- import {Text, Badge, Card, Icon, Sparkline, StatCard, Space } from 'weifuwu/components'
3
-
4
-
5
- // ─────────────────────────────────────────────────────────────
6
- // 模式 7:数据大屏(Data Screen)
7
- //
8
- // 全屏网格 + 固定角标(标题/时间/状态灯)。
9
- // 100% 原语 + 组件:wf-fill(撑满)、wf-layer + wf-pop(容器内角标——
10
- // 嵌进任意父容器不错位;全屏使用等价 wf-pin)、wf-grid(大屏格)
11
- // Sparkline(曲线)、StatCard、Badge dot(状态灯)
12
- // ─────────────────────────────────────────────────────────────
13
-
14
- const SERIES = {
15
- cpu: [42, 45, 38, 52, 48, 61, 55, 72, 68, 75, 70, 66, 78, 82],
16
- mem: [30, 32, 35, 33, 38, 42, 40, 45, 43, 48, 52, 50, 55, 58],
17
- net: [20, 28, 25, 40, 35, 52, 48, 44, 60, 55, 68, 62, 74, 80],
18
- qps: [120, 145, 138, 162, 158, 190, 175, 210, 198, 235, 220, 245, 260, 280],
19
- latency: [38, 42, 35, 48, 52, 45, 58, 62, 55, 68, 72, 65, 74, 70],
20
- disk: [45, 46, 48, 47, 50, 52, 51, 55, 58, 57, 62, 64, 66, 68],
21
- }
22
-
23
- const CARDS = [
24
- { title: 'CPU 使用率', key: 'cpu', unit: '%' },
25
- { title: '内存占用', key: 'mem', unit: '%' },
26
- { title: '网络吞吐', key: 'net', unit: 'MB/s' },
27
- { title: '请求 QPS', key: 'qps', unit: '/s' },
28
- { title: '接口延迟', key: 'latency', unit: 'ms' },
29
- { title: '磁盘使用', key: 'disk', unit: '%' },
30
- ]
31
-
32
- const tick = (series: number[]) => {
33
- const base = series[series.length - 1]
34
- const next = Math.max(5, Math.min(95, base + (Math.random() * 8 - 4)))
35
- return [...series.slice(1), Math.round(next)]
36
- }
37
-
38
- export const DataScreen: Component = async (_init, ctx) => {
39
- // render-only:内部状态 let + 显式 render(实时曲线数据 + 时间)
40
- const series: Record<string, number[]> = {}
41
- for (const c of CARDS) series[c.key] = [...SERIES[c.key as keyof typeof SERIES]]
42
- let time = new Date().toTimeString().slice(0, 8)
43
- const today = new Date().toISOString().slice(0, 10)
44
- // 实时刷新:2 秒滚动更新全部曲线 + 时间(布局蓝本演示实时监控)
45
- const timer = setInterval(() => {
46
- for (const c of CARDS) series[c.key] = tick(series[c.key])
47
- time = new Date().toTimeString().slice(0, 8)
48
- ctx.render()
49
- }, 2000)
50
-
51
- // ref 纪律:稳定引用定义在 mount 作用域——ref(null) 只在真正卸载时调用
52
- // (内联 ref 每次渲染新引用 → 反复 clearInterval → 数据永不更新)
53
- const rootRef = (el: any) => { if (!el) clearInterval(timer) }
54
-
55
- return async () => (
56
- <div ref={rootRef} class="wf-fill wf-layer wf-stack wf-gap-md wf-p-md wf-bg-tertiary" style={{ height: 'calc(100vh - 48px)' }}>
57
- {/* 顶部标题(容器内角标——wf-layer + wf-pop) */}
58
- <div class="wf-pop wf-center" style={{ top: 16, left: 0, right: 0 }}>
59
- <Space size="sm" align="center">
60
- <Icon name="zap" size={18} className="wf-text-primary" />
61
- <b class="wf-text-lg wf-text-bold wf-tracking-wider">实时运维监控中心</b>
62
- </Space>
63
- </div>
64
- {/* 右上时间(实时) */}
65
- <div class="wf-pop" style={{ top: 16, right: 24 }}>
66
- <Text type="secondary" className="wf-text-sm wf-nums">{today} {time}</Text>
67
- </div>
68
- {/* 左上状态灯 */}
69
- <div class="wf-pop wf-row wf-gap-sm" style={{ top: 16, left: 24, alignItems: 'center' }}>
70
- <Badge variant="success" dot />
71
- <Text type="secondary" className="wf-text-sm">运行正常</Text>
72
- </div>
73
-
74
- {/* 主体:指标网格 */}
75
- <div class="wf-grid wf-fill wf-p-lg" style={{ '--wf-cols': 'repeat(auto-fill, minmax(280px, 1fr))', alignContent: 'center', paddingTop: 60 }}>
76
- {CARDS.map((m) => (
77
- <Card outlined key={m.title} padding="lg">
78
- <Space direction="vertical" size="md">
79
- <div class="wf-row wf-between">
80
- <Text strong>{m.title}</Text>
81
- <Space size="sm" align="center">
82
- <Badge variant="success" dot />
83
- <Text type="success" className="wf-text-sm">实时</Text>
84
- </Space>
85
- </div>
86
- <Sparkline data={series[m.key]} width={280} height={64} />
87
- <StatCard label="当前值" value={`${series[m.key][series[m.key].length - 1]}${m.unit}`} trend="up" trendLabel="最近采样" />
88
- </Space>
89
- </Card>
90
- ))}
91
- </div>
92
-
93
- {/* 底部滚动信息 */}
94
- <div class="wf-pop wf-p-sm wf-border-t" style={{ bottom: 12, left: 24, right: 24 }}>
95
- <Space size="lg">
96
- <Text type="secondary" className="wf-text-xs">[INFO] 集群 12 节点健康 · 2s 实时刷新</Text>
97
- <Text type="secondary" className="wf-text-xs">[INFO] 自动扩容已触发(us-east-1)</Text>
98
- <Text type="warning" className="wf-text-xs">[WARN] 磁盘余量 18%</Text>
99
- </Space>
100
- </div>
101
- </div>
102
- )
103
- }
104
-
@@ -1,79 +0,0 @@
1
- import type { Component } from 'weifuwu/vdom'
2
- import { PageHeader, Descriptions, Timeline, Tag, Button, Space, Card, Divider } from 'weifuwu/components'
3
-
4
- // ─────────────────────────────────────────────────────────────
5
- // 模式 10:详情页(Detail Page)
6
- //
7
- // 业务对象详情:标题栏 + 描述列表 + 状态时间线 + 操作区。
8
- // 复制此文件即可得到一个标准的"详情页":
9
- // - PageHeader(对象名 + 状态 Tag + 操作按钮)
10
- // - Descriptions(label/value 栅格——详情字段)
11
- // - Timeline(执行历史/审批流)
12
- // - Card 分区(补充信息块)
13
- // 改造:换 data 字段 → 自己的业务对象。
14
- // ─────────────────────────────────────────────────────────────
15
-
16
- const ORDER = {
17
- id: 'SO-1003',
18
- customer: '王强',
19
- amount: 3200,
20
- status: '已发货',
21
- date: '2026-08-12',
22
- address: '杭州市西湖区文三路 138 号',
23
- note: '加急——客户要求周五前送达',
24
- }
25
-
26
- const HISTORY = [
27
- { title: '订单创建', time: '2026-08-12 09:12', tone: 'success' as const },
28
- { title: '已支付', time: '2026-08-12 09:15' },
29
- { title: '仓库发货', time: '2026-08-12 16:40' },
30
- { title: '运输中', time: '2026-08-13 08:05' },
31
- ]
32
-
33
- export const DetailPage: Component = async (_init: any, ctx: any) => {
34
- let cancelled = false
35
- return async (_p: any) => (
36
- <div class="wf-container wf-stack" style="--wf-max:960px;--wf-gap:16px;padding:24px 16px">
37
- <PageHeader title={`订单 ${ORDER.id}`} sub={`客户:${ORDER.customer} · 下单时间:${ORDER.date}`}>
38
- <Space size="md">
39
- <Tag variant="primary">{ORDER.status}</Tag>
40
- <Button variant="ghost" onClick={() => ctx.render()}>
41
- <Icon name="copy" size={14} /> 导出
42
- </Button>
43
- <Button variant="danger" disabled={cancelled} onClick={() => { cancelled = true; ctx.render() }}>
44
- {cancelled ? '已取消' : '取消订单'}
45
- </Button>
46
- </Space>
47
- </PageHeader>
48
-
49
- <Descriptions
50
- items={[
51
- { label: '订单号', value: ORDER.id },
52
- { label: '客户', value: ORDER.customer },
53
- { label: '金额', value: `¥${ORDER.amount.toLocaleString()}` },
54
- { label: '状态', value: ORDER.status },
55
- { label: '收货地址', value: ORDER.address, span: 2 },
56
- { label: '备注', value: cancelled ? '(已取消)' : ORDER.note, span: 2 },
57
- ]}
58
- bordered
59
- />
60
-
61
- <div class="wf-grid" style="--wf-cols:2fr 1fr;--wf-gap:16px">
62
- <Card>
63
- <div class="wf-text-bold wf-mb-sm">补充信息</div>
64
- <div class="wf-text-secondary wf-text-sm wf-stack wf-gap-xs">
65
- <span>支付方式:对公转账</span>
66
- <span>发票:已开具(¥3,200.00)</span>
67
- <span>业务员:陈晨</span>
68
- </div>
69
- </Card>
70
- <Card>
71
- <div class="wf-text-bold wf-mb-sm">执行历史</div>
72
- <Timeline items={HISTORY.map((h, i) => ({ ...h, key: String(i) }))} />
73
- </Card>
74
- </div>
75
- </div>
76
- )
77
- }
78
-
79
- import { Icon } from 'weifuwu/components'