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,105 +0,0 @@
1
- import type { Component } from 'weifuwu/vdom'
2
- import {Title,Paragraph, Anchor, BackTop, Breadcrumb, Button, CodeBlock, Divider, Icon, Tag, Space, } from 'weifuwu/components'
3
-
4
-
5
- // ─────────────────────────────────────────────────────────────
6
- // 模式 2:文档站(Docs Site)
7
- //
8
- // 顶部导航 + 左侧章节目录(Anchor 滚动跟随)+ 右侧正文(prose 排版)。
9
- // 100% 原语 + 组件:wf-row / wf-gap-* / wf-prose / wf-container / wf-border-t
10
- // Anchor(目录)、Breadcrumb(面包屑)、CodeBlock(代码)、Tag(版本)
11
- // ─────────────────────────────────────────────────────────────
12
-
13
- const SECTIONS = [
14
- { id: 'intro', title: '快速开始' },
15
- { id: 'install', title: '安装' },
16
- { id: 'usage', title: '基本用法' },
17
- { id: 'theme', title: '主题定制' },
18
- { id: 'ssr', title: '服务端渲染' },
19
- { id: 'api', title: 'API 参考' },
20
- ]
21
-
22
- export const Docs: Component = async (_init, ctx) => {
23
- let mainEl: HTMLElement | undefined
24
-
25
- return async () => (
26
- <div class="wf-stack wf-gap-none" style={{ minHeight: 'calc(100vh - 48px)' }}>
27
- {/* 顶部导航 */}
28
- <header class="wf-row wf-p-md wf-gap-lg wf-border-b wf-between">
29
- <Space align="center">
30
- <Icon name="book-open" size={18} />
31
- <b class="wf-text-bold">weifuwu 文档</b>
32
- <span class="wf-text-tertiary wf-text-sm">布局原语指南</span>
33
- </Space>
34
- <Space>
35
- <Button size="sm" variant="ghost"><Icon name="github" size={14} /> GitHub</Button>
36
- <Tag variant="primary">v0.69.0</Tag>
37
- </Space>
38
- </header>
39
-
40
- {/* 主体:左目录 + 右正文 */}
41
- <div class="wf-row wf-gap-none wf-fill wf-stretch wf-nowrap">
42
- <aside class="wf-p-lg wf-border-r wf-sticky" style={{ width: 220, flexShrink: 0 }}>
43
- <span class="wf-text-tertiary wf-text-sm wf-block wf-mb-sm">目录</span>
44
- <Anchor
45
- container={() => mainEl ?? window}
46
- items={SECTIONS.map((s) => ({ href: `#${s.id}`, title: s.title }))}
47
- />
48
- </aside>
49
-
50
- <main
51
- ref={(el: any) => { if (el) mainEl = el }}
52
- class="wf-fill wf-p-lg wf-scroll"
53
- >
54
- <Breadcrumb items={[{ label: '首页' }, { label: '文档' }, { label: '布局指南' }]} />
55
- <div class="wf-container wf-prose wf-mt-md" style={{ maxWidth: 720 }}>
56
- <Title level={1}>快速开始</Title>
57
- <Paragraph>
58
- 在 weifuwu 中,布局由原子原语(wf-stack / wf-row / wf-grid / wf-split…)与组件族组合而成。
59
- 原子原语只做一件事:把元素按某一种空间关系排列。组合它们即可搭建任意界面。
60
- </Paragraph>
61
- <CodeBlock lang="html" code={`<div class="wf-stack wf-gap-md">
62
- <h1>标题</h1>
63
- <p>纵向堆叠段落</p>
64
- </div>`} />
65
-
66
- <Divider />
67
-
68
- <Title level={2}>安装</Title>
69
- <Paragraph>安装 weifuwu 并引入布局样式:</Paragraph>
70
- <CodeBlock lang="bash" code={`npm i weifuwu
71
- # server.ts
72
- app.get('/layout.css', (req, ctx) => ctx.ui.css('weifuwu/layout'))`} />
73
-
74
- <Divider />
75
-
76
- <Title level={2}>基本用法</Title>
77
- <Paragraph>
78
- 原子原语可以像乐高一样自由嵌套:外层定空间关系,内层定内容呈现。
79
- 间距、断点、圆角、颜色均以 CSS 变量暴露(--wf-gap-*、--wf-bp-*、--wf-color-*),覆盖变量即换肤。
80
- </Paragraph>
81
-
82
- <Divider />
83
-
84
- <Title level={2}>服务端渲染</Title>
85
- <Paragraph>布局纯 CSS + 无状态组件,天然适配 SSR——路由级渲染时布局零成本。</Paragraph>
86
-
87
- <Divider />
88
-
89
- <Title level={2}>API 参考</Title>
90
- <Paragraph>原子原语按用途分组:排列(stack/row/grid/split)、定位(fixed/sticky/fill)、装饰(surface/prose)等。</Paragraph>
91
- </div>
92
- </main>
93
- </div>
94
-
95
- {/* footer */}
96
- <footer class="wf-cluster wf-p-md wf-border-t">
97
- <span class="wf-text-tertiary wf-text-sm">weifuwu/layout · 58 布局原语 · 136 工具类 · 开源 MIT</span>
98
- </footer>
99
-
100
- {/* 返回顶部(BackTop——组件能力展示:target 指向壳内部滚动容器) */}
101
- <BackTop target={() => ctx.browser?.query('.wf-fill.wf-scroll') as HTMLElement} />
102
- </div>
103
- )
104
- }
105
-
@@ -1,67 +0,0 @@
1
- import type { Component } from 'weifuwu/vdom'
2
- import {Text, Button, Card, Checkbox, Field, Form, Icon, Input, Space, Alert, Divider } from 'weifuwu/components'
3
-
4
-
5
- // ─────────────────────────────────────────────────────────────
6
- // 模式 8:聚焦任务页(Focus Task)
7
- //
8
- // 单任务页面:居中卡片承载表单——登录、注册、支付、审批通用。
9
- // 100% 原语 + 组件:wf-fill + wf-center(视口居中)+ Card 承载
10
- // Form / Field / Input / Checkbox / Button(weifuwu 表单全家桶)
11
- // ─────────────────────────────────────────────────────────────
12
-
13
- export const FocusTask: Component = async (_init, ctx) => {
14
- let ok = false
15
- let errors = {} as Record<string, string>
16
- const rerender = () => ctx.render()
17
-
18
- return async () => (
19
- <div class="wf-fill wf-center wf-p-md wf-bg-secondary" style={{ minHeight: 'calc(100vh - 48px)' }}>
20
- <Card padding="lg" style={{ width: '400px', maxWidth: '100%' }}>
21
- <div class="wf-stack wf-gap-md wf-center">
22
- {/* 品牌区 */}
23
- <Space direction="vertical" size="sm" align="center">
24
- <Icon name="lock" size={32} className="wf-text-primary" />
25
- <b class="wf-text-bold wf-text-lg">登录 weifuwu</b>
26
- <Text type="secondary" className="wf-text-sm">进入你的工作台</Text>
27
- </Space>
28
-
29
- <Form
30
- validation={{
31
- username: [{ required: true, message: '请输入用户名' }],
32
- password: [{ required: true, message: '请输入密码' }],
33
- }}
34
- onError={(e) => { errors = e; rerender() }}
35
- onSubmit={(v) => {
36
- if (v.username === 'admin' && v.password === 'admin') {
37
- ok = true; rerender()
38
- }
39
- }}
40
- >
41
- <div class="wf-stack wf-gap-md">
42
- <Field label="用户名" required error={errors.username}>
43
- <Input name="username" placeholder="请输入用户名" />
44
- </Field>
45
- <Field label="密码" required error={errors.password}>
46
- <Input name="password" type="password" placeholder="请输入密码" />
47
- </Field>
48
- <div class="wf-row wf-between">
49
- <Checkbox label="记住我" />
50
- <Text className="wf-text-primary wf-text-sm wf-pointer">忘记密码?</Text>
51
- </div>
52
- <Button type="submit" variant="primary" block size="lg">登 录</Button>
53
- </div>
54
- </Form>
55
-
56
- {ok && <Alert variant="success">登录成功(demo:admin / admin)</Alert>}
57
- {!ok && (
58
- <Divider>
59
- <Text type="secondary" className="wf-text-sm">没有账号?<Text className="wf-text-primary wf-pointer">立即注册</Text></Text>
60
- </Divider>
61
- )}
62
- </div>
63
- </Card>
64
- </div>
65
- )
66
- }
67
-
@@ -1,90 +0,0 @@
1
- import type { Component } from 'weifuwu/vdom'
2
- import {Title,Paragraph,Text, Badge, BackTop, Button, Card, Divider, Icon, Link, Space, Avatar } from 'weifuwu/components'
3
-
4
-
5
- // ─────────────────────────────────────────────────────────────
6
- // 模式 5:营销落地页(Landing Page)
7
- //
8
- // Hero(全宽居中)+ 特性区(三列网格)+ CTA + Footer。
9
- // 100% 原语 + 组件:wf-center / wf-container / wf-grid / wf-gap-*
10
- // Badge、Card、Button、Tag
11
- // ─────────────────────────────────────────────────────────────
12
-
13
- const FEATURES = [
14
- { icon: 'layers' as const, title: '原子原语', desc: '66 个布局原语 + 156 个工具类组合任意界面,无框架锁定' },
15
- { icon: 'zap' as const, title: '零依赖前端', desc: '纯函数组件 + Proxy 状态驱动,无 npm 运行时依赖' },
16
- { icon: 'globe' as const, title: 'SSR 透明', desc: '路由级服务端渲染,hydration 零决策' },
17
- { icon: 'database' as const, title: '全栈一体', desc: 'DB / Redis / 队列 / AI / WebSocket 一个框架搞定' },
18
- ]
19
-
20
- export const Landing: Component = async (_init, ctx) => (
21
- async () => (
22
- <div class="wf-stack wf-gap-none">
23
- {/* 顶部导航 */}
24
- <header class="wf-row wf-p-md wf-gap-lg wf-container wf-between wf-sticky wf-bg-secondary" style={{ maxWidth: 1100, top: 0 }}>
25
- <Space align="center">
26
- <Icon name="zap" size={20} className="wf-text-primary" />
27
- <b class="wf-text-bold wf-text-lg">weifuwu</b>
28
- </Space>
29
- <Space size="lg" align="center">
30
- <Link href="#features" underline={false} variant="muted">特性</Link>
31
- <Link href="#docs" underline={false} variant="muted">文档</Link>
32
- <Link href="#pricing" underline={false} variant="muted">定价</Link>
33
- </Space>
34
- <Button size="sm" variant="primary">开始使用</Button>
35
- </header>
36
-
37
- {/* Hero:全宽 + 居中 */}
38
- <section class="wf-center wf-p-xl wf-bg-primary">
39
- <div class="wf-stack wf-gap-md wf-text-center" style={{ maxWidth: 640 }}>
40
- <Badge variant="primary">v0.69.0 已发布</Badge>
41
- <Title level={1} className="wf-text-display">
42
- 一个框架,<br />构建完整应用
43
- </Title>
44
- <Paragraph className="wf-text-secondary" style={{ maxWidth: 480 }}>
45
- 后端中间件 + 前端响应式组件 + SSR,从数据库到像素,全程一个心智模型。
46
- </Paragraph>
47
- <div class="wf-cluster wf-gap-md">
48
- <Button size="lg" variant="primary">免费开始</Button>
49
- <Button size="lg" variant="ghost">查看文档 <Icon name="arrow-right" size={14} /></Button>
50
- </div>
51
- </div>
52
- </section>
53
-
54
- {/* 特性区 */}
55
- <section class="wf-container wf-p-xl" style={{ maxWidth: 1100 }}>
56
- <div class="wf-grid" style={{ '--wf-cols': 'repeat(auto-fill, minmax(240px, 1fr))' }}>
57
- {FEATURES.map((f) => (
58
- <Card outlined key={f.title} padding="lg">
59
- <Space direction="vertical" size="md">
60
- <Icon name={f.icon} size={28} className="wf-text-primary" />
61
- <b>{f.title}</b>
62
- <Text type="secondary" className="wf-text-sm">{f.desc}</Text>
63
- </Space>
64
- </Card>
65
- ))}
66
- </div>
67
- </section>
68
-
69
- {/* CTA */}
70
- <section class="wf-center wf-p-xl wf-bg-secondary">
71
- <div class="wf-stack wf-gap-md wf-center wf-text-center">
72
- <Title level={2}>准备构建你的下一个应用?</Title>
73
- <Paragraph className="wf-text-secondary">npm i weifuwu — 5 分钟跑通全栈</Paragraph>
74
- <Button variant="primary" size="lg"><Icon name="zap" size={16} /> 立即上手</Button>
75
- </div>
76
- </section>
77
-
78
- {/* Footer */}
79
- <BackTop target={() => ctx.browser?.query('.wf-fill.wf-scroll') as HTMLElement} />
80
- <footer class="wf-row wf-p-md wf-gap-lg wf-border-t wf-container wf-between" style={{ maxWidth: 1100 }}>
81
- <Text type="secondary" className="wf-text-sm">© 2026 weifuwu</Text>
82
- <Space align="center" size="sm">
83
- <Avatar size="sm" name="W" />
84
- <Text type="secondary" className="wf-text-sm">Made with weifuwu</Text>
85
- </Space>
86
- </footer>
87
- </div>
88
- )
89
- )
90
-
@@ -1,77 +0,0 @@
1
- import type { Component } from 'weifuwu/vdom'
2
- import { PageHeader, SearchInput, Table, Tag, Pagination, Button, Icon, EmptyState, Card } from 'weifuwu/components'
3
-
4
- // ─────────────────────────────────────────────────────────────
5
- // 模式 9:列表页(List Page)
6
- //
7
- // 最常见的业务页面:搜索 + 表格 + 分页 + 状态标签组合。
8
- // 复制此文件即可得到一个标准的"列表页":
9
- // - PageHeader(标题 + 操作区)
10
- // - SearchInput(搜索过滤——客户端即时过滤)
11
- // - Table(列配置 + 状态 Tag 渲染)
12
- // - Pagination(分页——当前为前端分页,接 API 时分页参数同理)
13
- // 改造:换 columns/data → 自己的业务列表。
14
- // ─────────────────────────────────────────────────────────────
15
-
16
- const ORDERS = [
17
- { id: 'SO-1001', customer: '张伟', amount: 1280, status: '已支付', date: '2026-08-10' },
18
- { id: 'SO-1002', customer: '李娜', amount: 560, status: '待支付', date: '2026-08-11' },
19
- { id: 'SO-1003', customer: '王强', amount: 3200, status: '已发货', date: '2026-08-12' },
20
- { id: 'SO-1004', customer: '赵敏', amount: 890, status: '已支付', date: '2026-08-13' },
21
- { id: 'SO-1005', customer: '陈杰', amount: 2100, status: '待支付', date: '2026-08-14' },
22
- { id: 'SO-1006', customer: '刘洋', amount: 450, status: '已支付', date: '2026-08-15' },
23
- { id: 'SO-1007', customer: '孙丽', amount: 1750, status: '已发货', date: '2026-08-16' },
24
- { id: 'SO-1008', customer: '周涛', amount: 980, status: '已支付', date: '2026-08-17' },
25
- ]
26
-
27
- const statusTag = (s: string) =>
28
- s === '已支付' ? <Tag variant="success">{s}</Tag> : s === '已发货' ? <Tag variant="primary">{s}</Tag> : <Tag>{s}</Tag>
29
-
30
- export const ListPage: Component = async (_init: any, ctx: any) => {
31
- let q = ''
32
- let page = 1
33
- const PAGE_SIZE = 5
34
- return async (_p: any) => {
35
- const filtered = ORDERS.filter((o) => !q || o.customer.toLowerCase().includes(q.toLowerCase()) || o.id.toLowerCase().includes(q.toLowerCase()))
36
- const total = filtered.length
37
- const pages = Math.max(1, Math.ceil(total / PAGE_SIZE))
38
- const cur = Math.min(page, pages)
39
- const rows = filtered.slice((cur - 1) * PAGE_SIZE, cur * PAGE_SIZE)
40
- return (
41
- <div class="wf-container wf-stack" style="--wf-max:960px;--wf-gap:16px;padding:24px 16px">
42
- <PageHeader title="订单列表" sub={`共 ${total} 条订单`}>
43
- <div class="wf-row wf-gap-sm">
44
- <SearchInput placeholder="搜索客户/订单号…" value={q}
45
- onInput={(e: any) => { q = (e.target as HTMLInputElement).value; page = 1; ctx.render() }}
46
- onClear={() => { q = ''; page = 1; ctx.render() }} />
47
- <Button variant="primary" onClick={() => ctx.render()}>
48
- <Icon name="plus" size={14} /> 新建订单
49
- </Button>
50
- </div>
51
- </PageHeader>
52
-
53
- {rows.length === 0 ? (
54
- <Card><EmptyState text={q ? `无匹配「${q}」的订单` : '暂无订单'} /></Card>
55
- ) : (
56
- <Table
57
- columns={[
58
- { key: 'id', label: '订单号' },
59
- { key: 'customer', label: '客户' },
60
- { key: 'amount', label: '金额', render: (v: any) => `¥${Number(v).toLocaleString()}` },
61
- { key: 'date', label: '日期' },
62
- { key: 'status', label: '状态', render: (v: any) => statusTag(v) },
63
- { key: 'id', label: '操作', render: () => <a class="wf-link" style="cursor:pointer">查看</a> },
64
- ]}
65
- data={rows}
66
- />
67
- )}
68
-
69
- <div class="wf-row wf-between">
70
- <span class="wf-text-xs wf-text-tertiary">第 {cur}/{pages} 页 · 每页 {PAGE_SIZE} 条</span>
71
- <Pagination total={total} page={cur} pageSize={PAGE_SIZE}
72
- onChange={(p: number) => { page = p; ctx.render() }} />
73
- </div>
74
- </div>
75
- )
76
- }
77
- }
@@ -1,154 +0,0 @@
1
- import type { Component } from 'weifuwu/vdom'
2
- import { Text, Avatar, Badge, Divider, Icon, List, SearchInput, Space, TabBar } from 'weifuwu/components'
3
-
4
-
5
- // ─────────────────────────────────────────────────────────────
6
- // 模式 6:移动端布局(Mobile App Shell)
7
- //
8
- // App 壳:顶部导航(wf-safe-top 避让刘海)+ 内容列表 + 底部 Tab
9
- // (wf-safe-bottom 避让手势条)。固定视口(390px 居中)模拟手机屏。
10
- // 100% 原语 + 组件:wf-safe-top/bottom、wf-fill、wf-row/gap、wf-center
11
- // SearchInput(搜索)、List(消息流)、Badge(未读数)
12
- // ─────────────────────────────────────────────────────────────
13
-
14
- const CONTACTS = [
15
- { name: '张伟', role: '产品经理', online: true },
16
- { name: '李娜', role: '设计师', online: true },
17
- { name: '王强', role: '后端工程师', online: false },
18
- { name: '赵敏', role: '测试', online: true },
19
- { name: '陈晨', role: '运营', online: false },
20
- ]
21
-
22
- const DISCOVER = [
23
- { title: '前端周刊', meta: '12 篇新文章', icon: 'file-text' },
24
- { title: 'AI 助手', meta: '对话式工具', icon: 'zap' },
25
- { title: '设计资源', meta: '图标 / 插画', icon: 'layers' },
26
- { title: '开源项目', meta: 'weifuwu 生态', icon: 'github' },
27
- ]
28
-
29
- const CHATS = [
30
- { name: '产品讨论组', msg: '王强:新的布局原语文档已更新', time: '10:24', unread: 3 },
31
- { name: '张伟', msg: '收到,明天下午评审', time: '09:58', unread: 0 },
32
- { name: '前端小分队', msg: '李娜:PR #128 已合并 🎉', time: '昨天', unread: 12 },
33
- { name: '服务端同学', msg: '部署脚本已就绪', time: '昨天', unread: 0 },
34
- { name: '设计同步', msg: '新图标包已上传 Figma', time: '周一', unread: 5 },
35
- ]
36
-
37
- const TABS = [
38
- { key: '消息', icon: 'message' as const, label: '消息' },
39
- { key: '通讯录', icon: 'users' as const, label: '通讯录' },
40
- { key: '发现', icon: 'grid' as const, label: '发现' },
41
- { key: '我', icon: 'user' as const, label: '我' },
42
- ]
43
-
44
- export const Mobile: Component = async (_init, ctx) => {
45
- let query = ''
46
- let tab = '消息'
47
- const rerender = () => ctx.render()
48
-
49
- return async () => {
50
- const filtered = CHATS.filter((c) => c.name.includes(query) || c.msg.includes(query))
51
- return (
52
- <div class="wf-center wf-p-lg wf-bg-tertiary" style={{ minHeight: 'calc(100vh - 48px)' }}>
53
- {/* 手机视口(390×640 模拟屏——唯一允许的视口容器内联) */}
54
- <div class="wf-stack wf-gap-none wf-border wf-rounded-lg wf-elevate wf-bg-primary" style={{ width: 390, maxWidth: '100%', height: 640, overflow: 'hidden' }}>
55
- {/* 顶部导航(安全区避让) */}
56
- <div class="wf-safe-top wf-row wf-p-md wf-gap-sm wf-border-b wf-between">
57
- <Icon name="chevron-left" size={18} />
58
- <b class="wf-text-bold">消息</b>
59
- <Icon name="plus" size={18} />
60
- </div>
61
-
62
- {/* 搜索(输入过滤列表) */}
63
- <div class="wf-p-md wf-border-b">
64
- <SearchInput
65
- placeholder="搜索会话"
66
- onInput={(e) => { query = (e.target as HTMLInputElement).value; rerender() }}
67
- onClear={() => { query = ''; rerender() }}
68
- />
69
- </div>
70
-
71
- {/* 内容区(按底部 Tab 切换) */}
72
- <div class="wf-fill wf-scroll">
73
- {tab === '消息' && (
74
- <List
75
- divided
76
- items={filtered}
77
- renderItem={(c) => (
78
- <div class="wf-row wf-p-md wf-gap-md">
79
- <Avatar name={c.name[0]} size="md" />
80
- <div class="wf-fill wf-stack wf-gap-none" style={{ minWidth: 0 }}>
81
- <div class="wf-row wf-gap-none wf-between">
82
- <Text className="wf-text-sm" strong>{c.name}</Text>
83
- <Text type="secondary" className="wf-text-xs">{c.time}</Text>
84
- </div>
85
- <Text type="secondary" className="wf-text-sm wf-truncate">{c.msg}</Text>
86
- </div>
87
- {c.unread > 0 && <Badge variant="danger" dot={false}>{c.unread}</Badge>}
88
- </div>
89
- )}
90
- />
91
- )}
92
- {tab === '通讯录' && (
93
- <List
94
- divided
95
- items={CONTACTS}
96
- renderItem={(c) => (
97
- <div class="wf-row wf-p-md wf-gap-md">
98
- <Avatar name={c.name[0]} size="md" />
99
- <div class="wf-fill">
100
- <Text className="wf-text-sm" strong>{c.name}</Text>
101
- <Text type="secondary" className="wf-text-xs wf-block">{c.role}</Text>
102
- </div>
103
- {c.online && <span class="wf-badge-dot wf-badge-dot--success" />}
104
- </div>
105
- )}
106
- />
107
- )}
108
- {tab === '发现' && (
109
- <List
110
- divided
111
- items={DISCOVER}
112
- renderItem={(d) => (
113
- <div class="wf-row wf-p-md wf-gap-md">
114
- <Icon name={d.icon as any} size={20} className="wf-text-primary" />
115
- <div class="wf-fill">
116
- <Text className="wf-text-sm" strong>{d.title}</Text>
117
- <Text type="secondary" className="wf-text-xs wf-block">{d.meta}</Text>
118
- </div>
119
- <Icon name="chevron-right" size={16} className="wf-text-tertiary" />
120
- </div>
121
- )}
122
- />
123
- )}
124
- {tab === '我' && (
125
- <div class="wf-stack wf-gap-md wf-p-md">
126
- <div class="wf-row wf-gap-md">
127
- <Avatar name="我" size="lg" />
128
- <div class="wf-stack wf-gap-none">
129
- <Text strong>管理员</Text>
130
- <Text type="secondary" className="wf-text-xs">ID: 10086</Text>
131
- </div>
132
- </div>
133
- {['账号与安全', '通知设置', '隐私', '关于'].map((item) => (
134
- <div key={item} class="wf-between wf-p-sm wf-border-b">
135
- <Text className="wf-text-sm">{item}</Text>
136
- <Icon name="chevron-right" size={14} className="wf-text-tertiary" />
137
- </div>
138
- ))}
139
- </div>
140
- )}
141
- </div>
142
-
143
- {/* 底部 Tab(TabBar 组件——safe-area 避让 + 受控激活 + 键盘方向键) */}
144
- <TabBar
145
- items={TABS}
146
- activeKey={tab}
147
- onChange={(k: string) => { tab = k; rerender() }}
148
- />
149
- </div>
150
- </div>
151
- )
152
- }
153
- }
154
-
@@ -1,98 +0,0 @@
1
- import type { Component } from 'weifuwu/vdom'
2
- import { PageHeader, Tabs, Form, Field, Input, Switch, Select, Button, Alert, Space } from 'weifuwu/components'
3
-
4
- // ─────────────────────────────────────────────────────────────
5
- // 模式 11:设置页(Settings Page)
6
- //
7
- // 多分区设置:Tabs 分块 + Form 表单 + 开关项 + 保存反馈。
8
- // 复制此文件即可得到一个标准的"设置页":
9
- // - PageHeader(标题 + 保存按钮)
10
- // - Tabs(基本设置 / 通知 / 安全——分区)
11
- // - Form + Field(表单校验)
12
- // - Switch(开关项——通知开关)
13
- // - Alert(保存成功反馈)
14
- // 改造:换分区/字段 → 自己的设置项。
15
- // ─────────────────────────────────────────────────────────────
16
-
17
- export const SettingsPage: Component = async (_init: any, ctx: any) => {
18
- let tab = 'basic'
19
- let saved = false
20
- let saving = false
21
- let name = '团队工作台'
22
- let email = 'admin@acme.cn'
23
- let notifyOrder = true
24
- let notifyDigest = false
25
- let twoFactor = true
26
-
27
- const save = () => {
28
- saving = true
29
- saved = false
30
- ctx.render()
31
- setTimeout(() => { saving = false; saved = true; ctx.render() }, 800)
32
- }
33
-
34
- return async (_p: any) => (
35
- <div class="wf-container wf-stack" style="--wf-max:760px;--wf-gap:16px;padding:24px 16px">
36
- <PageHeader title="系统设置" sub="工作区偏好、通知与安全">
37
- <Button variant="primary" loading={saving} onClick={save}>保存设置</Button>
38
- </PageHeader>
39
-
40
- {saved && <Alert variant="success">设置已保存</Alert>}
41
-
42
- <Tabs
43
- items={[
44
- { key: 'basic', label: '基本设置' },
45
- { key: 'notify', label: '通知' },
46
- { key: 'security', label: '安全' },
47
- ]}
48
- active={tab}
49
- onChange={(k: string) => { tab = k; saved = false; ctx.render() }}
50
- />
51
-
52
- {tab === 'basic' && (
53
- <div class="wf-stack wf-gap-sm" style="max-width:480px">
54
- <Field label="工作区名称" hint="团队成员可见">
55
- <Input value={name} onInput={(e: any) => { name = (e.target as HTMLInputElement).value; ctx.render() }} />
56
- </Field>
57
- <Field label="管理员邮箱" required>
58
- <Input type="email" value={email} onInput={(e: any) => { email = (e.target as HTMLInputElement).value; ctx.render() }} />
59
- </Field>
60
- </div>
61
- )}
62
-
63
- {tab === 'notify' && (
64
- <div class="wf-stack wf-gap-sm" style="max-width:480px">
65
- <div class="wf-surface wf-border wf-rounded-sm wf-p-sm wf-row wf-between">
66
- <div class="wf-stack wf-gap-xs">
67
- <b class="wf-text-sm">订单通知</b>
68
- <span class="wf-text-xs wf-text-secondary">新订单到达时推送</span>
69
- </div>
70
- <Switch checked={notifyOrder} onChange={(v: boolean) => { notifyOrder = v; ctx.render() }} />
71
- </div>
72
- <div class="wf-surface wf-border wf-rounded-sm wf-p-sm wf-row wf-between">
73
- <div class="wf-stack wf-gap-xs">
74
- <b class="wf-text-sm">每日摘要</b>
75
- <span class="wf-text-xs wf-text-secondary">每天早上 9 点发送昨日汇总</span>
76
- </div>
77
- <Switch checked={notifyDigest} onChange={(v: boolean) => { notifyDigest = v; ctx.render() }} />
78
- </div>
79
- </div>
80
- )}
81
-
82
- {tab === 'security' && (
83
- <div class="wf-stack wf-gap-sm" style="max-width:480px">
84
- <div class="wf-surface wf-border wf-rounded-sm wf-p-sm wf-row wf-between">
85
- <div class="wf-stack wf-gap-xs">
86
- <b class="wf-text-sm">两步验证</b>
87
- <span class="wf-text-xs wf-text-secondary">登录时要求验证码</span>
88
- </div>
89
- <Switch checked={twoFactor} onChange={(v: boolean) => { twoFactor = v; ctx.render() }} />
90
- </div>
91
- <Field label="登录密码">
92
- <Input type="password" placeholder="输入新密码(留空不修改)" />
93
- </Field>
94
- </div>
95
- )}
96
- </div>
97
- )
98
- }