node-resource-utils 0.0.0-stage → 1.1.8

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 (229) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +35 -2
  3. package/lib/sync.js +121 -0
  4. package/package.json +14 -4
  5. package/resources/.cache/ref.b64 +1 -0
  6. package/resources/README.md +97 -0
  7. package/resources/_.env +6 -0
  8. package/resources/_.env.example +25 -0
  9. package/resources/_.gitignore +18 -0
  10. package/resources/_.lintstagedrc.json +9 -0
  11. package/resources/_.npmrc +5 -0
  12. package/resources/_.prettierrc +7 -0
  13. package/resources/commitlint.config.mjs +1 -0
  14. package/resources/content/docs/README.md +63 -0
  15. package/resources/content/docs/faq.md +107 -0
  16. package/resources/content/docs/features/_meta.json +5 -0
  17. package/resources/content/docs/features/ai.md +71 -0
  18. package/resources/content/docs/features/appearance.md +47 -0
  19. package/resources/content/docs/features/feedback.md +79 -0
  20. package/resources/content/docs/features/files.md +74 -0
  21. package/resources/content/docs/features/graph.md +66 -0
  22. package/resources/content/docs/features/inbox.md +61 -0
  23. package/resources/content/docs/guide/_meta.json +5 -0
  24. package/resources/content/docs/guide/account.md +76 -0
  25. package/resources/content/docs/guide/data.md +87 -0
  26. package/resources/content/docs/guide/navigation.md +81 -0
  27. package/resources/content/docs/guide/permissions.md +67 -0
  28. package/resources/content/docs/guide/system.md +92 -0
  29. package/resources/content/docs/quick-start.md +70 -0
  30. package/resources/content/docs/shortcuts.md +69 -0
  31. package/resources/eslint.config.mjs +17 -0
  32. package/resources/next-env.d.ts +6 -0
  33. package/resources/next.config.ts +13 -0
  34. package/resources/postcss.config.mjs +7 -0
  35. package/resources/prisma/org.config.ts +98 -0
  36. package/resources/prisma/schema.prisma +336 -0
  37. package/resources/prisma/seed.ts +721 -0
  38. package/resources/prisma/seedSafe.ts +347 -0
  39. package/resources/prisma.config.ts +14 -0
  40. package/resources/scripts/check-config.mjs +773 -0
  41. package/resources/scripts/lib/schema-graph.mjs +410 -0
  42. package/resources/scripts/patch-next-trace.mjs +86 -0
  43. package/resources/scripts/suggest-relations.mjs +105 -0
  44. package/resources/src/app/(admin)/ai/page.tsx +469 -0
  45. package/resources/src/app/(admin)/dashboard/page.tsx +260 -0
  46. package/resources/src/app/(admin)/demo/employees/page.tsx +508 -0
  47. package/resources/src/app/(admin)/demo/files/page.tsx +451 -0
  48. package/resources/src/app/(admin)/demo/loading/page.tsx +513 -0
  49. package/resources/src/app/(admin)/error.tsx +96 -0
  50. package/resources/src/app/(admin)/feedback/page.tsx +573 -0
  51. package/resources/src/app/(admin)/graph/page.tsx +1224 -0
  52. package/resources/src/app/(admin)/inbox/page.tsx +31 -0
  53. package/resources/src/app/(admin)/layout.tsx +58 -0
  54. package/resources/src/app/(admin)/loading.tsx +31 -0
  55. package/resources/src/app/(admin)/system/depts/page.tsx +415 -0
  56. package/resources/src/app/(admin)/system/logs/page.tsx +215 -0
  57. package/resources/src/app/(admin)/system/menus/page.tsx +403 -0
  58. package/resources/src/app/(admin)/system/roles/page.tsx +433 -0
  59. package/resources/src/app/(admin)/system/users/page.tsx +620 -0
  60. package/resources/src/app/api/account-recovery/route.ts +132 -0
  61. package/resources/src/app/api/ai/act/route.ts +70 -0
  62. package/resources/src/app/api/ai/ask/route.ts +82 -0
  63. package/resources/src/app/api/ai/chat/route.ts +404 -0
  64. package/resources/src/app/api/ai/report/route.ts +164 -0
  65. package/resources/src/app/api/auth/[...nextauth]/route.ts +3 -0
  66. package/resources/src/app/api/auth/change-password/route.ts +57 -0
  67. package/resources/src/app/api/auth/forgot/route.ts +98 -0
  68. package/resources/src/app/api/auth/register/route.ts +95 -0
  69. package/resources/src/app/api/auth/register-config/route.ts +51 -0
  70. package/resources/src/app/api/badges/route.ts +39 -0
  71. package/resources/src/app/api/depts/[id]/route.ts +145 -0
  72. package/resources/src/app/api/depts/route.ts +126 -0
  73. package/resources/src/app/api/docs/export/route.ts +87 -0
  74. package/resources/src/app/api/docs/parse/route.ts +57 -0
  75. package/resources/src/app/api/docs/search/route.ts +22 -0
  76. package/resources/src/app/api/employees/[id]/route.ts +147 -0
  77. package/resources/src/app/api/employees/export/route.ts +115 -0
  78. package/resources/src/app/api/employees/import/route.ts +205 -0
  79. package/resources/src/app/api/employees/route.ts +149 -0
  80. package/resources/src/app/api/export/route.ts +254 -0
  81. package/resources/src/app/api/favorites/route.ts +56 -0
  82. package/resources/src/app/api/feedback/ai/route.ts +31 -0
  83. package/resources/src/app/api/feedback/approve/route.ts +67 -0
  84. package/resources/src/app/api/feedback/report/route.ts +213 -0
  85. package/resources/src/app/api/feedback/route.ts +246 -0
  86. package/resources/src/app/api/files/[name]/route.ts +82 -0
  87. package/resources/src/app/api/graph/focus/route.ts +75 -0
  88. package/resources/src/app/api/graph/node/move/route.ts +48 -0
  89. package/resources/src/app/api/graph/node/route.ts +274 -0
  90. package/resources/src/app/api/graph/route.ts +272 -0
  91. package/resources/src/app/api/health/route.ts +11 -0
  92. package/resources/src/app/api/inbox/read/route.ts +36 -0
  93. package/resources/src/app/api/inbox/summary/route.ts +15 -0
  94. package/resources/src/app/api/logs/route.ts +82 -0
  95. package/resources/src/app/api/menus/[id]/route.ts +132 -0
  96. package/resources/src/app/api/menus/mine/route.ts +23 -0
  97. package/resources/src/app/api/menus/route.ts +89 -0
  98. package/resources/src/app/api/roles/[id]/menus/route.ts +73 -0
  99. package/resources/src/app/api/roles/[id]/route.ts +96 -0
  100. package/resources/src/app/api/roles/route.ts +114 -0
  101. package/resources/src/app/api/search/route.ts +22 -0
  102. package/resources/src/app/api/stats/route.ts +92 -0
  103. package/resources/src/app/api/upload/route.ts +38 -0
  104. package/resources/src/app/api/users/[id]/password/route.ts +55 -0
  105. package/resources/src/app/api/users/[id]/route.ts +145 -0
  106. package/resources/src/app/api/users/route.ts +153 -0
  107. package/resources/src/app/api/visits/route.ts +48 -0
  108. package/resources/src/app/change-password/ChangePasswordForm.tsx +174 -0
  109. package/resources/src/app/change-password/page.tsx +19 -0
  110. package/resources/src/app/docs/[[...slug]]/page.tsx +56 -0
  111. package/resources/src/app/docs/layout.tsx +34 -0
  112. package/resources/src/app/docs/loading.tsx +19 -0
  113. package/resources/src/app/docs/not-found.tsx +25 -0
  114. package/resources/src/app/forgot/page.tsx +392 -0
  115. package/resources/src/app/global-error.tsx +75 -0
  116. package/resources/src/app/globals.css +235 -0
  117. package/resources/src/app/layout.tsx +44 -0
  118. package/resources/src/app/login/page.tsx +267 -0
  119. package/resources/src/app/page.tsx +14 -0
  120. package/resources/src/app/register/page.tsx +237 -0
  121. package/resources/src/auth.ts +215 -0
  122. package/resources/src/components/AiPanel.tsx +970 -0
  123. package/resources/src/components/AuthContext.tsx +82 -0
  124. package/resources/src/components/DataTable.tsx +459 -0
  125. package/resources/src/components/EChart.tsx +140 -0
  126. package/resources/src/components/FeedbackAiModal.tsx +476 -0
  127. package/resources/src/components/FeedbackReportModal.tsx +479 -0
  128. package/resources/src/components/Markdown.tsx +532 -0
  129. package/resources/src/components/OntologyGraph.tsx +1196 -0
  130. package/resources/src/components/Providers.tsx +99 -0
  131. package/resources/src/components/VisitTracker.tsx +89 -0
  132. package/resources/src/components/admin/AdminShell.tsx +749 -0
  133. package/resources/src/components/admin/CountBadge.tsx +67 -0
  134. package/resources/src/components/admin/GlobalSearch.tsx +509 -0
  135. package/resources/src/components/admin/InboxBell.tsx +78 -0
  136. package/resources/src/components/admin/VisitStats.tsx +145 -0
  137. package/resources/src/components/admin/menu-icons.tsx +56 -0
  138. package/resources/src/components/ai/AiInputForm.tsx +351 -0
  139. package/resources/src/components/appearance/AppearanceDrawer.tsx +268 -0
  140. package/resources/src/components/appearance/AppearanceProvider.tsx +160 -0
  141. package/resources/src/components/docs/DocArticle.tsx +106 -0
  142. package/resources/src/components/docs/DocToc.tsx +100 -0
  143. package/resources/src/components/docs/DocsChrome.tsx +259 -0
  144. package/resources/src/components/docs/DocsHome.tsx +209 -0
  145. package/resources/src/components/docs/DocsSearch.tsx +365 -0
  146. package/resources/src/components/docs/docs.css +1458 -0
  147. package/resources/src/components/feedback/AsyncButton.tsx +108 -0
  148. package/resources/src/components/feedback/LoadingOverlay.tsx +125 -0
  149. package/resources/src/components/feedback/PressableCard.tsx +92 -0
  150. package/resources/src/components/feedback/README.md +97 -0
  151. package/resources/src/components/feedback/RouteProgress.tsx +108 -0
  152. package/resources/src/components/feedback/Skeleton.tsx +249 -0
  153. package/resources/src/components/feedback/StatCard.tsx +70 -0
  154. package/resources/src/components/feedback/TaskHint.tsx +153 -0
  155. package/resources/src/components/feedback/index.ts +93 -0
  156. package/resources/src/components/feedback/motion.css +204 -0
  157. package/resources/src/components/feedback/motion.ts +63 -0
  158. package/resources/src/components/feedback/useCountUp.ts +110 -0
  159. package/resources/src/components/feedback/usePending.ts +209 -0
  160. package/resources/src/components/feedback/useRowFlash.ts +40 -0
  161. package/resources/src/components/inbox/InboxView.tsx +409 -0
  162. package/resources/src/components/ui/button.tsx +35 -0
  163. package/resources/src/components/ui/card.tsx +37 -0
  164. package/resources/src/components/ui/input.tsx +19 -0
  165. package/resources/src/lib/ai.ts +310 -0
  166. package/resources/src/lib/aiContext.ts +357 -0
  167. package/resources/src/lib/aiForm.test.ts +191 -0
  168. package/resources/src/lib/aiForm.ts +532 -0
  169. package/resources/src/lib/aiFormTypes.ts +83 -0
  170. package/resources/src/lib/aiToken.ts +72 -0
  171. package/resources/src/lib/aiTools.ts +823 -0
  172. package/resources/src/lib/api.ts +160 -0
  173. package/resources/src/lib/appInfo.ts +128 -0
  174. package/resources/src/lib/appearance.ts +643 -0
  175. package/resources/src/lib/badge-count.ts +146 -0
  176. package/resources/src/lib/badges.test.ts +58 -0
  177. package/resources/src/lib/badges.ts +79 -0
  178. package/resources/src/lib/brand-mark.test.ts +87 -0
  179. package/resources/src/lib/brand-mark.ts +45 -0
  180. package/resources/src/lib/docs-shared.test.ts +148 -0
  181. package/resources/src/lib/docs-shared.ts +422 -0
  182. package/resources/src/lib/docs.ts +381 -0
  183. package/resources/src/lib/err-text.ts +21 -0
  184. package/resources/src/lib/excel.ts +152 -0
  185. package/resources/src/lib/favorite-path.ts +60 -0
  186. package/resources/src/lib/favorites.ts +59 -0
  187. package/resources/src/lib/features.ts +69 -0
  188. package/resources/src/lib/feedback-access.ts +17 -0
  189. package/resources/src/lib/feedbackAi.ts +1621 -0
  190. package/resources/src/lib/formRules.ts +76 -0
  191. package/resources/src/lib/format.ts +52 -0
  192. package/resources/src/lib/graph-cascade.ts +304 -0
  193. package/resources/src/lib/graph-focus.ts +301 -0
  194. package/resources/src/lib/graph-link.ts +17 -0
  195. package/resources/src/lib/graph-node-write.ts +150 -0
  196. package/resources/src/lib/graph-schema.ts +475 -0
  197. package/resources/src/lib/graph-scope.test.ts +46 -0
  198. package/resources/src/lib/graph-scope.ts +28 -0
  199. package/resources/src/lib/http.ts +157 -0
  200. package/resources/src/lib/inbox-types.ts +57 -0
  201. package/resources/src/lib/inbox.ts +55 -0
  202. package/resources/src/lib/menu-service.ts +204 -0
  203. package/resources/src/lib/notifications.ts +113 -0
  204. package/resources/src/lib/office.ts +531 -0
  205. package/resources/src/lib/ontology.ts +277 -0
  206. package/resources/src/lib/openaiCompat.ts +257 -0
  207. package/resources/src/lib/pending.ts +98 -0
  208. package/resources/src/lib/prisma.ts +30 -0
  209. package/resources/src/lib/rbac.test.ts +106 -0
  210. package/resources/src/lib/rbac.ts +185 -0
  211. package/resources/src/lib/search-data.ts +158 -0
  212. package/resources/src/lib/security-questions.ts +20 -0
  213. package/resources/src/lib/skin-theme.ts +155 -0
  214. package/resources/src/lib/system-config.ts +55 -0
  215. package/resources/src/lib/theme.ts +96 -0
  216. package/resources/src/lib/todos/feedback.ts +86 -0
  217. package/resources/src/lib/todos/index.ts +73 -0
  218. package/resources/src/lib/todos/types.ts +33 -0
  219. package/resources/src/lib/upload.ts +106 -0
  220. package/resources/src/lib/utils.test.ts +9 -0
  221. package/resources/src/lib/utils.ts +6 -0
  222. package/resources/src/lib/validation.test.ts +297 -0
  223. package/resources/src/lib/validation.ts +658 -0
  224. package/resources/src/lib/visit-stats.ts +109 -0
  225. package/resources/src/lib/visits.ts +111 -0
  226. package/resources/src/lib/zodField.ts +44 -0
  227. package/resources/tsconfig.json +41 -0
  228. package/resources/vitest.config.ts +16 -0
  229. package/resources/vitest.setup.ts +1 -0
@@ -0,0 +1,99 @@
1
+ 'use client';
2
+
3
+ import { ConfigProvider, App as AntdApp } from 'antd';
4
+ import zhCN from 'antd/locale/zh_CN';
5
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
6
+ import { useEffect, useMemo, useState, type ReactNode } from 'react';
7
+ import dayjs from 'dayjs';
8
+ import 'dayjs/locale/zh-cn';
9
+ import { installRequestTracking } from '@/lib/http';
10
+ import { buildSkinTheme } from '@/lib/skin-theme';
11
+ import RouteProgress from '@/components/feedback/RouteProgress';
12
+ import TaskHint from '@/components/feedback/TaskHint';
13
+ import VisitTracker from '@/components/VisitTracker';
14
+ import { AppearanceProvider, useAppearance } from '@/components/appearance/AppearanceProvider';
15
+ import AppearanceDrawer from '@/components/appearance/AppearanceDrawer';
16
+
17
+ dayjs.locale('zh-cn');
18
+
19
+ /**
20
+ * 全局 Provider。
21
+ *
22
+ * - AppearanceProvider: 皮肤 + 字号(整站,含登录页)。少了它,
23
+ * 页面里的 `var(--wb-*)` 还在,但 antd 组件不会跟着换配色。
24
+ * - ConfigProvider: 中文语言包 + **按当前皮肤实时编译**的主题 token。
25
+ * 换皮肤不是换一份写死的配置,而是 `buildSkinTheme()` 现场算一遍,
26
+ * 所以加一套皮肤只需要在 lib/appearance.ts 里加一条。
27
+ * - AntdApp: 提供 message / modal / notification 的上下文,
28
+ * 这样在任意组件里用 App.useApp() 拿到的弹窗是「跟随主题」的,
29
+ * 比直接 import { message } from 'antd' 更规范(后者不受 ConfigProvider 影响)
30
+ * - QueryClientProvider: 服务端数据缓存,列表页翻页不重复请求
31
+ *
32
+ * ★ 等待反馈的**全局兜底**也挂在这里(所以登录页同样生效):
33
+ * - installRequestTracking(): 给 axios 装拦截器,任何请求超过 3 秒
34
+ * 都会自动出现在右下角浮层里 —— 页面忘了写 loading 也不会没反应
35
+ * - RouteProgress: 跳页面时的顶部细进度条
36
+ * - TaskHint: 右下角「正在处理…已等待 N 秒」小卡片
37
+ *
38
+ * ★ 外观面板也挂在这里(AppearanceDrawer):顶栏、用户菜单、任何页面
39
+ * 只要调 `useAppearance().openPanel()` 就能打开,不用各自渲染一份。
40
+ */
41
+ export default function Providers({ children }: { children: ReactNode }) {
42
+ return (
43
+ <AppearanceProvider>
44
+ <ThemedApp>{children}</ThemedApp>
45
+ </AppearanceProvider>
46
+ );
47
+ }
48
+
49
+ function ThemedApp({ children }: { children: ReactNode }) {
50
+ const { settings } = useAppearance();
51
+
52
+ const [queryClient] = useState(
53
+ () =>
54
+ new QueryClient({
55
+ defaultOptions: {
56
+ queries: {
57
+ staleTime: 30_000,
58
+ retry: 1,
59
+ refetchOnWindowFocus: false,
60
+ },
61
+ },
62
+ })
63
+ );
64
+
65
+ /** 皮肤或字号一变,整套 antd token 重算(只是对象计算,不是重载页面) */
66
+ const theme = useMemo(
67
+ () => buildSkinTheme(settings.skin, settings.font),
68
+ [settings.skin, settings.font]
69
+ );
70
+
71
+ // 只在客户端装:模块顶层执行的话 SSR 也会跑一遍,拦截器会重复注册
72
+ useEffect(() => {
73
+ installRequestTracking();
74
+ }, []);
75
+
76
+ return (
77
+ <ConfigProvider
78
+ locale={zhCN}
79
+ theme={theme}
80
+ // 关掉 antd 的「两字中文按钮自动插空格」:默认会把"登录"渲染成"登 录",
81
+ // 中文界面里这个空格很突兀,也会让自动化测试按按钮文案定位时对不上。
82
+ // ⚠️ 这是 ConfigProvider 的 button 配置,不是 theme.components.Button 的 token ——
83
+ // 写在 components 里是不生效的(踩过)。
84
+ button={{ autoInsertSpace: false }}
85
+ >
86
+ <AntdApp>
87
+ <QueryClientProvider client={queryClient}>
88
+ {children}
89
+ {/* 全站访问埋点:挂在这里,新页面不用再写任何统计代码 */}
90
+ <VisitTracker />
91
+ <RouteProgress />
92
+ <TaskHint />
93
+ {/* 外观面板:全局唯一实例,任何地方 openPanel() 即可 */}
94
+ <AppearanceDrawer />
95
+ </QueryClientProvider>
96
+ </AntdApp>
97
+ </ConfigProvider>
98
+ );
99
+ }
@@ -0,0 +1,89 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useRef } from 'react';
4
+ import { usePathname } from 'next/navigation';
5
+ import {
6
+ VISIT_DEDUPE_MS,
7
+ VISIT_HEARTBEAT_MS,
8
+ VISIT_STATS_EVENT,
9
+ getOrCreateVisitorId,
10
+ normalizeVisitPath,
11
+ } from '@/lib/visits';
12
+
13
+ /**
14
+ * 全站访问埋点(不渲染任何 DOM)。
15
+ *
16
+ * 挂在根 Providers 上,于是登录页、帮助文档、后台各模块自动被统计 ——
17
+ * 新加页面不需要再写一行埋点代码。
18
+ *
19
+ * 两种上报:
20
+ * 页面浏览(带 path)—— 路由变化时发一次,写入 Visit,计入今日 / 总访问量
21
+ * 心跳(不带 path)—— 每 60 秒 + 回到前台时发一次,只刷新在线状态
22
+ *
23
+ * 为什么用原生 fetch 而不是 trackedFetch:
24
+ * 埋点是旁路,绝不能触发「正在处理…」的全局等待浮层,也不会因为失败弹错。
25
+ * 任何异常都吞掉:统计没了可以补,业务被统计拖慢就是本末倒置。
26
+ */
27
+
28
+ async function postVisit(visitorId: string, path?: string): Promise<boolean> {
29
+ try {
30
+ const res = await fetch('/api/visits', {
31
+ method: 'POST',
32
+ headers: { 'Content-Type': 'application/json' },
33
+ body: JSON.stringify(path ? { visitorId, path } : { visitorId }),
34
+ cache: 'no-store',
35
+ });
36
+ if (!res.ok) return false;
37
+ const json = (await res.json()) as { code?: number };
38
+ return json?.code === 0;
39
+ } catch {
40
+ return false;
41
+ }
42
+ }
43
+
44
+ export default function VisitTracker() {
45
+ const pathname = usePathname();
46
+ const visitorIdRef = useRef<string | null>(null);
47
+ const lastViewRef = useRef<{ path: string; at: number } | null>(null);
48
+
49
+ // 心跳:只要页面还开着、标签页可见,就保持"在线"
50
+ useEffect(() => {
51
+ visitorIdRef.current ??= getOrCreateVisitorId();
52
+
53
+ const beat = () => {
54
+ if (document.visibilityState !== 'visible') return;
55
+ const id = visitorIdRef.current;
56
+ if (id) void postVisit(id);
57
+ };
58
+
59
+ const timer = window.setInterval(beat, VISIT_HEARTBEAT_MS);
60
+ document.addEventListener('visibilitychange', beat);
61
+ window.addEventListener('focus', beat);
62
+ return () => {
63
+ window.clearInterval(timer);
64
+ document.removeEventListener('visibilitychange', beat);
65
+ window.removeEventListener('focus', beat);
66
+ };
67
+ }, []);
68
+
69
+ // 页面浏览:路由变化时记一条;同一页面短时间内重复触发只记一次
70
+ useEffect(() => {
71
+ const path = normalizeVisitPath(pathname);
72
+ if (!path) return;
73
+
74
+ visitorIdRef.current ??= getOrCreateVisitorId();
75
+ const id = visitorIdRef.current;
76
+ if (!id) return;
77
+
78
+ const last = lastViewRef.current;
79
+ if (last && last.path === path && Date.now() - last.at < VISIT_DEDUPE_MS) return;
80
+ lastViewRef.current = { path, at: Date.now() };
81
+
82
+ void postVisit(id, path).then((written) => {
83
+ // 让顶栏统计立刻更新:自己的这次访问应该马上出现在"今日 / 在线"里
84
+ if (written) window.dispatchEvent(new Event(VISIT_STATS_EVENT));
85
+ });
86
+ }, [pathname]);
87
+
88
+ return null;
89
+ }