@hkyhy/marsun-components-core 0.1.2

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 (139) hide show
  1. package/README.md +99 -0
  2. package/dist/components/AgentHub/AgentHubAccessGuard.js +12 -0
  3. package/dist/components/AgentHub/AgentHubAccessGuard.js.map +1 -0
  4. package/dist/components/AgentHub/AgentHubIndexRedirect.js +11 -0
  5. package/dist/components/AgentHub/AgentHubIndexRedirect.js.map +1 -0
  6. package/dist/components/AgentHub/ChatSessionAccessGuard.js +11 -0
  7. package/dist/components/AgentHub/ChatSessionAccessGuard.js.map +1 -0
  8. package/dist/components/Auth/PermissionGuard.js +18 -0
  9. package/dist/components/Auth/PermissionGuard.js.map +1 -0
  10. package/dist/components/Auth/ProtectedRoute.js +21 -0
  11. package/dist/components/Auth/ProtectedRoute.js.map +1 -0
  12. package/dist/components/Auth/hasPermission.js +7 -0
  13. package/dist/components/Auth/hasPermission.js.map +1 -0
  14. package/dist/components/Descriptions/CommonDescriptions.js +14 -0
  15. package/dist/components/Descriptions/CommonDescriptions.js.map +1 -0
  16. package/dist/components/File/FileItem/index.js +82 -0
  17. package/dist/components/File/FileItem/index.js.map +1 -0
  18. package/dist/components/File/FileItem/style.module.scss.js +18 -0
  19. package/dist/components/File/FileItem/style.module.scss.js.map +1 -0
  20. package/dist/components/File/FileLink/index.js +27 -0
  21. package/dist/components/File/FileLink/index.js.map +1 -0
  22. package/dist/components/File/FileLink/style.module.scss.js +10 -0
  23. package/dist/components/File/FileLink/style.module.scss.js.map +1 -0
  24. package/dist/components/File/FilePreview/index.js +49 -0
  25. package/dist/components/File/FilePreview/index.js.map +1 -0
  26. package/dist/components/File/FilePreview/style.module.scss.js +5 -0
  27. package/dist/components/File/FilePreview/style.module.scss.js.map +1 -0
  28. package/dist/components/File/FilePreviewModal/index.js +12 -0
  29. package/dist/components/File/FilePreviewModal/index.js.map +1 -0
  30. package/dist/components/File/fileDisplay.js +67 -0
  31. package/dist/components/File/fileDisplay.js.map +1 -0
  32. package/dist/components/Filter/CommonFilter/index.js +81 -0
  33. package/dist/components/Filter/CommonFilter/index.js.map +1 -0
  34. package/dist/components/Filter/CommonFilter/style.module.scss.js +20 -0
  35. package/dist/components/Filter/CommonFilter/style.module.scss.js.map +1 -0
  36. package/dist/components/Filter/FilterDateRange/index.js +97 -0
  37. package/dist/components/Filter/FilterDateRange/index.js.map +1 -0
  38. package/dist/components/Filter/FilterDateRange/style.module.scss.js +10 -0
  39. package/dist/components/Filter/FilterDateRange/style.module.scss.js.map +1 -0
  40. package/dist/components/Filter/FilterInput/index.js +56 -0
  41. package/dist/components/Filter/FilterInput/index.js.map +1 -0
  42. package/dist/components/Filter/FilterNumberRange/index.js +81 -0
  43. package/dist/components/Filter/FilterNumberRange/index.js.map +1 -0
  44. package/dist/components/Filter/FilterNumberRange/style.module.scss.js +9 -0
  45. package/dist/components/Filter/FilterNumberRange/style.module.scss.js.map +1 -0
  46. package/dist/components/Filter/FilterPanel/index.js +21 -0
  47. package/dist/components/Filter/FilterPanel/index.js.map +1 -0
  48. package/dist/components/Filter/FilterPanel/style.module.scss.js +8 -0
  49. package/dist/components/Filter/FilterPanel/style.module.scss.js.map +1 -0
  50. package/dist/components/Filter/FilterPopover/index.js +52 -0
  51. package/dist/components/Filter/FilterPopover/index.js.map +1 -0
  52. package/dist/components/Filter/FilterSelect/index.js +160 -0
  53. package/dist/components/Filter/FilterSelect/index.js.map +1 -0
  54. package/dist/components/Filter/FilterSelect/style.module.scss.js +16 -0
  55. package/dist/components/Filter/FilterSelect/style.module.scss.js.map +1 -0
  56. package/dist/components/Filter/FilterTreeSelect/index.js +249 -0
  57. package/dist/components/Filter/FilterTreeSelect/index.js.map +1 -0
  58. package/dist/components/Filter/FilterTreeSelect/style.module.scss.js +19 -0
  59. package/dist/components/Filter/FilterTreeSelect/style.module.scss.js.map +1 -0
  60. package/dist/components/Filter/FilterTrigger/index.js +31 -0
  61. package/dist/components/Filter/FilterTrigger/index.js.map +1 -0
  62. package/dist/components/Filter/FilterTrigger/style.module.scss.js +10 -0
  63. package/dist/components/Filter/FilterTrigger/style.module.scss.js.map +1 -0
  64. package/dist/components/Filter/types.js +12 -0
  65. package/dist/components/Filter/types.js.map +1 -0
  66. package/dist/components/Filter/useFilterState.js +35 -0
  67. package/dist/components/Filter/useFilterState.js.map +1 -0
  68. package/dist/components/Form/FetchSelect.js +37 -0
  69. package/dist/components/Form/FetchSelect.js.map +1 -0
  70. package/dist/components/Form/FetchTreeSelect.js +28 -0
  71. package/dist/components/Form/FetchTreeSelect.js.map +1 -0
  72. package/dist/components/Form/PersonOptionRow/index.js +37 -0
  73. package/dist/components/Form/PersonOptionRow/index.js.map +1 -0
  74. package/dist/components/Form/PersonOptionRow/style.module.scss.js +11 -0
  75. package/dist/components/Form/PersonOptionRow/style.module.scss.js.map +1 -0
  76. package/dist/components/Form/StepForm.js +34 -0
  77. package/dist/components/Form/StepForm.js.map +1 -0
  78. package/dist/components/Icons/index.js +245 -0
  79. package/dist/components/Icons/index.js.map +1 -0
  80. package/dist/components/Layout/PageHeaderLayout/index.js +41 -0
  81. package/dist/components/Layout/PageHeaderLayout/index.js.map +1 -0
  82. package/dist/components/Layout/PageHeaderLayout/style.module.scss.js +10 -0
  83. package/dist/components/Layout/PageHeaderLayout/style.module.scss.js.map +1 -0
  84. package/dist/components/Modal/StepModal/index.js +64 -0
  85. package/dist/components/Modal/StepModal/index.js.map +1 -0
  86. package/dist/components/Modal/StepModal/style.module.scss.js +9 -0
  87. package/dist/components/Modal/StepModal/style.module.scss.js.map +1 -0
  88. package/dist/components/Stat/StatCard/index.js +34 -0
  89. package/dist/components/Stat/StatCard/index.js.map +1 -0
  90. package/dist/components/Stat/StatCard/style.module.scss.js +7 -0
  91. package/dist/components/Stat/StatCard/style.module.scss.js.map +1 -0
  92. package/dist/components/Stat/StatCardList.js +20 -0
  93. package/dist/components/Stat/StatCardList.js.map +1 -0
  94. package/dist/components/Stat/StatPendingBreakdown/index.js +38 -0
  95. package/dist/components/Stat/StatPendingBreakdown/index.js.map +1 -0
  96. package/dist/components/Stat/StatPendingBreakdown/style.module.scss.js +9 -0
  97. package/dist/components/Stat/StatPendingBreakdown/style.module.scss.js.map +1 -0
  98. package/dist/components/Tag/FileTags.js +8 -0
  99. package/dist/components/Tag/FileTags.js.map +1 -0
  100. package/dist/components/Tag/SemanticTag.js +92 -0
  101. package/dist/components/Tag/SemanticTag.js.map +1 -0
  102. package/dist/components/Tag/Tags/index.js +32 -0
  103. package/dist/components/Tag/Tags/index.js.map +1 -0
  104. package/dist/components/Tag/Tags/style.module.scss.js +9 -0
  105. package/dist/components/Tag/Tags/style.module.scss.js.map +1 -0
  106. package/dist/components/TooltipInfo/TooltipInfo.js +31 -0
  107. package/dist/components/TooltipInfo/TooltipInfo.js.map +1 -0
  108. package/dist/components/Tour/AppTour/index.js +40 -0
  109. package/dist/components/Tour/AppTour/index.js.map +1 -0
  110. package/dist/components/Tour/AppTour/style.module.scss.js +7 -0
  111. package/dist/components/Tour/AppTour/style.module.scss.js.map +1 -0
  112. package/dist/components/VirtualScrollbar/VirtualScrollbar/index.js +97 -0
  113. package/dist/components/VirtualScrollbar/VirtualScrollbar/index.js.map +1 -0
  114. package/dist/components/VirtualScrollbar/VirtualScrollbar/style.module.scss.js +12 -0
  115. package/dist/components/VirtualScrollbar/VirtualScrollbar/style.module.scss.js.map +1 -0
  116. package/dist/components/VirtualScrollbar/useVirtualScrollbar.js +97 -0
  117. package/dist/components/VirtualScrollbar/useVirtualScrollbar.js.map +1 -0
  118. package/dist/hooks/useFetchData.js +69 -0
  119. package/dist/hooks/useFetchData.js.map +1 -0
  120. package/dist/index.d.ts +28 -0
  121. package/dist/index.js +182 -0
  122. package/dist/index.js.map +1 -0
  123. package/dist/marsun-components-core.css +1 -0
  124. package/dist/provider/MarsunCoreProvider.js +51 -0
  125. package/dist/provider/MarsunCoreProvider.js.map +1 -0
  126. package/dist/provider/context.js +27 -0
  127. package/dist/provider/context.js.map +1 -0
  128. package/dist/theme/constants.js +15 -0
  129. package/dist/theme/constants.js.map +1 -0
  130. package/dist/theme/index.d.ts +2 -0
  131. package/dist/theme/index.js +9 -0
  132. package/dist/theme/index.js.map +1 -0
  133. package/dist/theme/theme.js +286 -0
  134. package/dist/theme/theme.js.map +1 -0
  135. package/dist/utils/format.js +9 -0
  136. package/dist/utils/format.js.map +1 -0
  137. package/dist/utils/resolveMaybeFn.js +11 -0
  138. package/dist/utils/resolveMaybeFn.js.map +1 -0
  139. package/package.json +83 -0
package/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # @hkyhy/marsun-components-core
2
+
3
+ Marsun 纯 UI 组件库(React 19 + antd 6)。从 `maoyang_data-asset-system` 的 Common / AgentHub 拆分,**不含业务数据**。
4
+
5
+ [![CI](https://github.com/hkyhy/MARSUN_components-core/actions/workflows/ci.yml/badge.svg)](https://github.com/hkyhy/MARSUN_components-core/actions/workflows/ci.yml)
6
+ [![GitHub Pages](https://img.shields.io/badge/docs-GitHub%20Pages-blue)](https://hkyhy.github.io/MARSUN_components-core/)
7
+
8
+ **远程仓库**:`git@github.com:hkyhy/MARSUN_components-core.git`
9
+
10
+ **组件 Showcase**:https://hkyhy.github.io/MARSUN_components-core/
11
+
12
+ ## 安装
13
+
14
+ ```bash
15
+ npm install @hkyhy/marsun-components-core antd react react-dom
16
+ ```
17
+
18
+ > 发布至 [npm](https://www.npmjs.com/package/@hkyhy/marsun-components-core)(GitHub Secret `HKYHY_PACKAGE_PUBLISH` + tag `v*` 触发,见「发布版本」)。
19
+
20
+ ## 快速开始
21
+
22
+ ```tsx
23
+ import { MarsunCoreProvider, SemanticTag, FetchTreeSelect } from '@hkyhy/marsun-components-core';
24
+
25
+ <MarsunCoreProvider
26
+ auth={{
27
+ isAuthenticated: true,
28
+ hasPermission: (p) => permissions.includes(p),
29
+ hasAnyRole: (roles) => roles.some((r) => userRoles.includes(r)),
30
+ }}
31
+ fetch={{ baseUrl: '/api', headers: { Authorization: `Bearer ${token}` } }}
32
+ >
33
+ <SemanticTag color="primary">标签</SemanticTag>
34
+ <FetchTreeSelect
35
+ treeData={treeData}
36
+ // 或 fetch 模式:
37
+ // fetchUrl="/departments/tree"
38
+ // transformData={(raw) => raw.data}
39
+ />
40
+ </MarsunCoreProvider>
41
+ ```
42
+
43
+ ## 设计原则
44
+
45
+ - **零业务依赖**:无 `departmentPath`、`personOption` 等领域工具;`transformData` 由消费方实现
46
+ - **双模式数据**:props 传 `data`/`treeData`/`options` 优先;或 `fetchUrl` + `transformData`
47
+ - **MaybeFn 参数**:`display` / `hidden` / `disabled` 等支持 `boolean | (ctx) => boolean`
48
+ - **Mock 数据**:各组件 `doc/*.mock.json`,仅 dev showcase 使用,不打入 npm 产物
49
+
50
+ ## 目录
51
+
52
+ ```
53
+ src/components/
54
+ Auth/ Filter/ Form/ File/ Tag/ Icons/ ... # Common 拍平
55
+ AgentHub/ # Chat + KnowledgeBase
56
+ ```
57
+
58
+ ## Dev
59
+
60
+ ```bash
61
+ npm install
62
+ npm run dev # 本地 showcase :5175
63
+ npm run build # 库产物 dist/
64
+ npm run build:showcase # 静态 showcase → dist-showcase/(GitHub Pages)
65
+ npm run preview:showcase # 预览 showcase 构建结果
66
+ npm run typecheck
67
+ ```
68
+
69
+ ### GitHub Pages
70
+
71
+ - 推送 `main` 后由 `.github/workflows/pages.yml` 自动部署
72
+ - 项目页 base path:`/MARSUN_components-core/`
73
+ - 本地模拟 Pages 构建:`VITE_BASE_PATH=/MARSUN_components-core/ npm run build:showcase && npm run preview:showcase`
74
+
75
+ ### 发布版本(npm)
76
+
77
+ 包名为 **`@hkyhy/marsun-components-core`**(npm scope 与 GitHub 发布账号 `hkyhy` 对齐;若需 `@marsun` 须先在 npm 创建该组织)。
78
+
79
+ 1. 在 GitHub 仓库 **Settings → Secrets → Actions** 配置 `HKYHY_PACKAGE_PUBLISH`(npm Automation Token,对 `@hkyhy` 有 publish 权限)
80
+ 2. 更新 `package.json` 的 `version`,提交后打 tag 并推送:
81
+
82
+ ```bash
83
+ npm version patch # 或 minor / major
84
+ git push origin main --tags
85
+ ```
86
+
87
+ 推送 `v*` tag 后 `.github/workflows/publish.yml` 自动执行 `npm publish`(仅发布 `dist/`,不含 dev showcase)。
88
+
89
+ 也可在 Actions 中手动运行 **Publish npm**,填写已有 tag(如 `v0.1.2`)。
90
+
91
+ ## 后续接入 maoyang
92
+
93
+ 发布 npm 后,在 `maoyang_data-asset-system` 批量替换:
94
+
95
+ ```ts
96
+ import { SemanticTag, FetchTreeSelect } from '@hkyhy/marsun-components-core';
97
+ // 业务 wrapper 留在 maoyang
98
+ import { DepartmentSelect } from '@/components/Common/Form/DepartmentSelect';
99
+ ```
@@ -0,0 +1,12 @@
1
+ import { jsx as r, Fragment as e } from "react/jsx-runtime";
2
+ import { Navigate as u } from "react-router-dom";
3
+ const s = ({
4
+ mode: t,
5
+ isAdmin: n = !1,
6
+ redirectTo: o = "/",
7
+ children: a
8
+ }) => n ? /* @__PURE__ */ r(e, { children: a }) : t === "admin-only" || t === "chat-manage" ? /* @__PURE__ */ r(u, { to: o, replace: !0 }) : /* @__PURE__ */ r(e, { children: a });
9
+ export {
10
+ s as default
11
+ };
12
+ //# sourceMappingURL=AgentHubAccessGuard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentHubAccessGuard.js","sources":["../../../src/components/AgentHub/AgentHubAccessGuard.tsx"],"sourcesContent":["import React from 'react';\nimport { Navigate } from 'react-router-dom';\n\nexport interface AgentHubAccessGuardProps {\n mode: 'admin-only' | 'chat-manage';\n /** 是否管理员 */\n isAdmin?: boolean;\n /** 无权限时重定向路径 */\n redirectTo?: string;\n children: React.ReactNode;\n}\n\nconst AgentHubAccessGuard: React.FC<AgentHubAccessGuardProps> = ({\n mode,\n isAdmin = false,\n redirectTo = '/',\n children,\n}) => {\n if (isAdmin) return <>{children}</>;\n if (mode === 'admin-only' || mode === 'chat-manage') {\n return <Navigate to={redirectTo} replace />;\n }\n return <>{children}</>;\n};\n\nexport default AgentHubAccessGuard;\n"],"names":["AgentHubAccessGuard","mode","isAdmin","redirectTo","children","jsx","Fragment","Navigate"],"mappings":";;AAYA,MAAMA,IAA0D,CAAC;AAAA,EAC/D,MAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,YAAAC,IAAa;AAAA,EACb,UAAAC;AACF,MACMF,IAAgB,gBAAAG,EAAAC,GAAA,EAAG,UAAAF,EAAA,CAAS,IAC5BH,MAAS,gBAAgBA,MAAS,gBAC7B,gBAAAI,EAACE,GAAA,EAAS,IAAIJ,GAAY,SAAO,IAAC,2BAEjC,UAAAC,GAAS;"}
@@ -0,0 +1,11 @@
1
+ import { jsx as r } from "react/jsx-runtime";
2
+ import { Navigate as o } from "react-router-dom";
3
+ const u = ({
4
+ isAdmin: t = !1,
5
+ adminPath: e = "/agent-hub/chat",
6
+ userPath: a = "/agent-hub/chat"
7
+ }) => /* @__PURE__ */ r(o, { to: t ? e : a, replace: !0 });
8
+ export {
9
+ u as default
10
+ };
11
+ //# sourceMappingURL=AgentHubIndexRedirect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentHubIndexRedirect.js","sources":["../../../src/components/AgentHub/AgentHubIndexRedirect.tsx"],"sourcesContent":["import React from 'react';\nimport { Navigate } from 'react-router-dom';\n\nexport interface AgentHubIndexRedirectProps {\n isAdmin?: boolean;\n adminPath?: string;\n userPath?: string;\n}\n\nconst AgentHubIndexRedirect: React.FC<AgentHubIndexRedirectProps> = ({\n isAdmin = false,\n adminPath = '/agent-hub/chat',\n userPath = '/agent-hub/chat',\n}) => <Navigate to={isAdmin ? adminPath : userPath} replace />;\n\nexport default AgentHubIndexRedirect;\n"],"names":["AgentHubIndexRedirect","isAdmin","adminPath","userPath","Navigate"],"mappings":";;AASA,MAAMA,IAA8D,CAAC;AAAA,EACnE,SAAAC,IAAU;AAAA,EACV,WAAAC,IAAY;AAAA,EACZ,UAAAC,IAAW;AACb,wBAAOC,GAAA,EAAS,IAAIH,IAAUC,IAAYC,GAAU,SAAO,GAAA,CAAC;"}
@@ -0,0 +1,11 @@
1
+ import { jsx as t, Fragment as o } from "react/jsx-runtime";
2
+ import { Navigate as u } from "react-router-dom";
3
+ const c = ({
4
+ hasAccess: e = !0,
5
+ redirectTo: r = "/agent-hub/chat",
6
+ children: a
7
+ }) => e ? /* @__PURE__ */ t(o, { children: a }) : /* @__PURE__ */ t(u, { to: r, replace: !0 });
8
+ export {
9
+ c as default
10
+ };
11
+ //# sourceMappingURL=ChatSessionAccessGuard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatSessionAccessGuard.js","sources":["../../../src/components/AgentHub/ChatSessionAccessGuard.tsx"],"sourcesContent":["import React from 'react';\nimport { Navigate } from 'react-router-dom';\n\nexport interface AgentHubSessionAccessGuardProps {\n hasAccess?: boolean;\n redirectTo?: string;\n children: React.ReactNode;\n}\n\nconst AgentHubSessionAccessGuard: React.FC<AgentHubSessionAccessGuardProps> = ({\n hasAccess = true,\n redirectTo = '/agent-hub/chat',\n children,\n}) => {\n if (!hasAccess) return <Navigate to={redirectTo} replace />;\n return <>{children}</>;\n};\n\nexport default AgentHubSessionAccessGuard;\n"],"names":["AgentHubSessionAccessGuard","hasAccess","redirectTo","children","jsx","Navigate"],"mappings":";;AASA,MAAMA,IAAwE,CAAC;AAAA,EAC7E,WAAAC,IAAY;AAAA,EACZ,YAAAC,IAAa;AAAA,EACb,UAAAC;AACF,MACOF,2BACK,UAAAE,GAAS,IADI,gBAAAC,EAACC,KAAS,IAAIH,GAAY,SAAO,IAAC;"}
@@ -0,0 +1,18 @@
1
+ import { jsx as r, Fragment as n } from "react/jsx-runtime";
2
+ import { resolveVisible as h } from "../../utils/resolveMaybeFn.js";
3
+ import { useMarsunAuth as x } from "../../provider/context.js";
4
+ const s = ({
5
+ roles: t,
6
+ permission: u,
7
+ display: d,
8
+ hidden: f,
9
+ fallback: e = null,
10
+ children: m
11
+ }) => {
12
+ const { hasAnyRole: i, isAuthenticated: o, hasPermission: c } = x();
13
+ return h(d, f, { roles: t, permission: u }) ? o ? u && !(c != null && c(u)) ? /* @__PURE__ */ r(n, { children: e }) : t && t.length > 0 && !(i != null && i(t)) ? /* @__PURE__ */ r(n, { children: e }) : /* @__PURE__ */ r(n, { children: m }) : /* @__PURE__ */ r(n, { children: e }) : null;
14
+ };
15
+ export {
16
+ s as default
17
+ };
18
+ //# sourceMappingURL=PermissionGuard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PermissionGuard.js","sources":["../../../src/components/Auth/PermissionGuard.tsx"],"sourcesContent":["import { useMarsunAuth } from '@/provider';\nimport type { MaybeFn } from '@/utils/resolveMaybeFn';\nimport { resolveVisible } from '@/utils/resolveMaybeFn';\nimport React from 'react';\n\nexport type PermissionGuardContext = {\n roles?: string[];\n permission?: string;\n};\n\nexport interface PermissionGuardProps {\n /** 允许访问的角色列表 */\n roles?: string[];\n /** 允许访问的权限 key */\n permission?: string;\n /** 展示控制 */\n display?: MaybeFn<boolean, PermissionGuardContext>;\n hidden?: MaybeFn<boolean, PermissionGuardContext>;\n fallback?: React.ReactNode;\n children: React.ReactNode;\n}\n\nconst PermissionGuard: React.FC<PermissionGuardProps> = ({\n roles,\n permission,\n display,\n hidden,\n fallback = null,\n children,\n}) => {\n const { hasAnyRole, isAuthenticated, hasPermission } = useMarsunAuth();\n const ctx: PermissionGuardContext = { roles, permission };\n\n if (!resolveVisible(display, hidden, ctx)) return null;\n if (!isAuthenticated) return <>{fallback}</>;\n if (permission && !hasPermission?.(permission)) return <>{fallback}</>;\n if (roles && roles.length > 0 && !hasAnyRole?.(roles)) return <>{fallback}</>;\n\n return <>{children}</>;\n};\n\nexport default PermissionGuard;\n"],"names":["PermissionGuard","roles","permission","display","hidden","fallback","children","hasAnyRole","isAuthenticated","hasPermission","useMarsunAuth","resolveVisible","jsx","Fragment"],"mappings":";;;AAsBA,MAAMA,IAAkD,CAAC;AAAA,EACvD,OAAAC;AAAA,EACA,YAAAC;AAAA,EACA,SAAAC;AAAA,EACA,QAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,UAAAC;AACF,MAAM;AACJ,QAAM,EAAE,YAAAC,GAAY,iBAAAC,GAAiB,eAAAC,EAAA,IAAkBC,EAAA;AAGvD,SAAKC,EAAeR,GAASC,GAFO,EAAE,OAAAH,GAAO,YAAAC,EAAA,CAEL,IACnCM,IACDN,KAAc,EAACO,KAAA,QAAAA,EAAgBP,6BAAuB,UAAAG,GAAS,IAC/DJ,KAASA,EAAM,SAAS,KAAK,EAACM,KAAA,QAAAA,EAAaN,MAAe,gBAAAW,EAAAC,GAAA,EAAG,UAAAR,EAAA,CAAS,2BAEhE,UAAAC,GAAS,IAJU,gBAAAM,EAAAC,GAAA,EAAG,UAAAR,GAAS,IADS;AAMpD;"}
@@ -0,0 +1,21 @@
1
+ import { jsx as t, Fragment as f } from "react/jsx-runtime";
2
+ import { useLocation as $, Navigate as c } from "react-router-dom";
3
+ import { useMarsunAuth as g } from "../../provider/context.js";
4
+ const x = ({
5
+ roles: e,
6
+ permission: u,
7
+ loginPath: i = "/login",
8
+ fallbackPath: a = "/",
9
+ children: p
10
+ }) => {
11
+ const { isAuthenticated: m, hasAnyRole: r, hasPermission: o } = g(), n = $();
12
+ if (!m) {
13
+ const d = encodeURIComponent(`${n.pathname}${n.search}${n.hash}`);
14
+ return /* @__PURE__ */ t(c, { to: `${i}?redirect=${d}`, replace: !0 });
15
+ }
16
+ return e && e.length > 0 && !(r != null && r(e)) ? /* @__PURE__ */ t(c, { to: a, replace: !0 }) : u && !(o != null && o(u)) ? /* @__PURE__ */ t(c, { to: a, replace: !0 }) : /* @__PURE__ */ t(f, { children: p });
17
+ };
18
+ export {
19
+ x as default
20
+ };
21
+ //# sourceMappingURL=ProtectedRoute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProtectedRoute.js","sources":["../../../src/components/Auth/ProtectedRoute.tsx"],"sourcesContent":["import { useMarsunAuth } from '@/provider';\nimport React from 'react';\nimport { Navigate, useLocation } from 'react-router-dom';\n\nexport interface ProtectedRouteProps {\n roles?: string[];\n permission?: string;\n loginPath?: string;\n fallbackPath?: string;\n children: React.ReactNode;\n}\n\nconst ProtectedRoute: React.FC<ProtectedRouteProps> = ({\n roles,\n permission,\n loginPath = '/login',\n fallbackPath = '/',\n children,\n}) => {\n const { isAuthenticated, hasAnyRole, hasPermission } = useMarsunAuth();\n const location = useLocation();\n\n if (!isAuthenticated) {\n const redirect = encodeURIComponent(`${location.pathname}${location.search}${location.hash}`);\n return <Navigate to={`${loginPath}?redirect=${redirect}`} replace />;\n }\n\n if (roles && roles.length > 0 && !hasAnyRole?.(roles)) {\n return <Navigate to={fallbackPath} replace />;\n }\n\n if (permission && !hasPermission?.(permission)) {\n return <Navigate to={fallbackPath} replace />;\n }\n\n return <>{children}</>;\n};\n\nexport default ProtectedRoute;\n"],"names":["ProtectedRoute","roles","permission","loginPath","fallbackPath","children","isAuthenticated","hasAnyRole","hasPermission","useMarsunAuth","location","useLocation","redirect","jsx","Navigate"],"mappings":";;;AAYA,MAAMA,IAAgD,CAAC;AAAA,EACrD,OAAAC;AAAA,EACA,YAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,cAAAC,IAAe;AAAA,EACf,UAAAC;AACF,MAAM;AACJ,QAAM,EAAE,iBAAAC,GAAiB,YAAAC,GAAY,eAAAC,EAAA,IAAkBC,EAAA,GACjDC,IAAWC,EAAA;AAEjB,MAAI,CAACL,GAAiB;AACpB,UAAMM,IAAW,mBAAmB,GAAGF,EAAS,QAAQ,GAAGA,EAAS,MAAM,GAAGA,EAAS,IAAI,EAAE;AAC5F,WAAO,gBAAAG,EAACC,KAAS,IAAI,GAAGX,CAAS,aAAaS,CAAQ,IAAI,SAAO,GAAA,CAAC;AAAA,EACpE;AAEA,SAAIX,KAASA,EAAM,SAAS,KAAK,EAACM,KAAA,QAAAA,EAAaN,MACtC,gBAAAY,EAACC,GAAA,EAAS,IAAIV,GAAc,SAAO,IAAC,IAGzCF,KAAc,EAACM,KAAA,QAAAA,EAAgBN,MAC1B,gBAAAW,EAACC,GAAA,EAAS,IAAIV,GAAc,SAAO,IAAC,2BAGnC,UAAAC,GAAS;AACrB;"}
@@ -0,0 +1,7 @@
1
+ function e(r, n) {
2
+ return r ? r(n) : !1;
3
+ }
4
+ export {
5
+ e as hasPermission
6
+ };
7
+ //# sourceMappingURL=hasPermission.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hasPermission.js","sources":["../../../src/components/Auth/hasPermission.ts"],"sourcesContent":["/** 通过 Provider 注入的 hasPermission 回调检查权限 */\nexport function hasPermission(\n check: ((permission: string) => boolean) | undefined,\n perm: string,\n): boolean {\n if (!check) return false;\n return check(perm);\n}\n"],"names":["hasPermission","check","perm"],"mappings":"AACO,SAASA,EACdC,GACAC,GACS;AACT,SAAKD,IACEA,EAAMC,CAAI,IADE;AAErB;"}
@@ -0,0 +1,14 @@
1
+ import { jsx as o } from "react/jsx-runtime";
2
+ import { Descriptions as r } from "antd";
3
+ const d = ({
4
+ content: s,
5
+ column: a = 2,
6
+ bordered: e = !0,
7
+ size: n = "small",
8
+ title: p,
9
+ extra: m
10
+ }) => /* @__PURE__ */ o(r, { column: a, bordered: e, size: n, title: p, extra: m, children: s.map((l, t) => /* @__PURE__ */ o(r.Item, { label: l.label, span: l.span, children: l.value }, t)) });
11
+ export {
12
+ d as default
13
+ };
14
+ //# sourceMappingURL=CommonDescriptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommonDescriptions.js","sources":["../../../src/components/Descriptions/CommonDescriptions.tsx"],"sourcesContent":["import { Descriptions } from 'antd';\nimport React from 'react';\n\nexport interface DescriptionItem {\n label: string;\n value: React.ReactNode;\n span?: number;\n}\n\nexport interface CommonDescriptionsProps {\n content: DescriptionItem[];\n column?:\n | number\n | { xs?: number; sm?: number; md?: number; lg?: number; xl?: number; xxl?: number };\n bordered?: boolean;\n size?: 'small' | 'default' | 'middle';\n title?: React.ReactNode;\n extra?: React.ReactNode;\n}\n\nconst CommonDescriptions: React.FC<CommonDescriptionsProps> = ({\n content,\n column = 2,\n bordered = true,\n size = 'small',\n title,\n extra,\n}) => (\n <Descriptions column={column} bordered={bordered} size={size} title={title} extra={extra}>\n {content.map((item, index) => (\n <Descriptions.Item key={index} label={item.label} span={item.span}>\n {item.value}\n </Descriptions.Item>\n ))}\n </Descriptions>\n);\n\nexport default CommonDescriptions;\n"],"names":["CommonDescriptions","content","column","bordered","size","title","extra","jsx","Descriptions","item","index"],"mappings":";;AAoBA,MAAMA,IAAwD,CAAC;AAAA,EAC7D,SAAAC;AAAA,EACA,QAAAC,IAAS;AAAA,EACT,UAAAC,IAAW;AAAA,EACX,MAAAC,IAAO;AAAA,EACP,OAAAC;AAAA,EACA,OAAAC;AACF,MACE,gBAAAC,EAACC,GAAA,EAAa,QAAAN,GAAgB,UAAAC,GAAoB,MAAAC,GAAY,OAAAC,GAAc,OAAAC,GACzE,UAAAL,EAAQ,IAAI,CAACQ,GAAMC,MAClB,gBAAAH,EAACC,EAAa,MAAb,EAA8B,OAAOC,EAAK,OAAO,MAAMA,EAAK,MAC1D,UAAAA,EAAK,MAAA,GADgBC,CAExB,CACD,EAAA,CACH;"}
@@ -0,0 +1,82 @@
1
+ import { jsxs as o, Fragment as C, jsx as i } from "react/jsx-runtime";
2
+ import { Eye as T, Download as z, Trash2 as x } from "../../Icons/index.js";
3
+ import { formatFileSize as b } from "../../../utils/format.js";
4
+ import { Tooltip as I, Button as P } from "antd";
5
+ import { useState as j } from "react";
6
+ import A from "../FilePreviewModal/index.js";
7
+ import { normalizeFileDisplayItem as O, getFileTypeName as S, getFileIcon as B } from "../fileDisplay.js";
8
+ import l from "./style.module.scss.js";
9
+ import t from "classnames";
10
+ import D from "../../Tag/FileTags.js";
11
+ const R = ({
12
+ file: a,
13
+ status: s,
14
+ showDownload: d = !0,
15
+ showDelete: h = !1,
16
+ showPreview: w = !0,
17
+ actions: N,
18
+ onDownload: n,
19
+ onDelete: c,
20
+ onPreview: f
21
+ }) => {
22
+ const [u, p] = j(!1), e = O(a), y = () => {
23
+ if (n) {
24
+ n(e);
25
+ return;
26
+ }
27
+ e.url && window.open(e.url, "_blank");
28
+ }, g = () => {
29
+ f ? f(e) : p(!0);
30
+ }, m = [];
31
+ w && m.push({
32
+ key: "preview",
33
+ icon: /* @__PURE__ */ i(T, {}),
34
+ tooltip: "预览",
35
+ onClick: () => g()
36
+ }), d && m.push({
37
+ key: "download",
38
+ icon: /* @__PURE__ */ i(z, {}),
39
+ tooltip: "下载",
40
+ onClick: () => y()
41
+ }), h && c && m.push({
42
+ key: "delete",
43
+ icon: /* @__PURE__ */ i(x, {}),
44
+ tooltip: "删除",
45
+ onClick: () => c(e)
46
+ });
47
+ const v = [...m, ...N ?? []], k = S(e.name, e.mimeType);
48
+ return /* @__PURE__ */ o(C, { children: [
49
+ /* @__PURE__ */ i("div", { className: t("file-item-root", l["file-item-root"]), children: /* @__PURE__ */ o("div", { className: t("file-item-container", l["file-item-container"]), children: [
50
+ /* @__PURE__ */ o("div", { className: t("file-item-wrapper", l["file-item-wrapper"]), children: [
51
+ /* @__PURE__ */ i("span", { className: t("file-item-inner", l["file-item-inner"]), children: B(e.name, e.mimeType) }),
52
+ /* @__PURE__ */ o("div", { className: t("file-item-header", l["file-item-header"]), children: [
53
+ /* @__PURE__ */ o("div", { className: t("file-item-body", l["file-item-body"]), children: [
54
+ /* @__PURE__ */ i("span", { className: t("file-item-footer", l["file-item-footer"]), title: e.name, children: e.name }),
55
+ /* @__PURE__ */ i("span", { className: t("file-item-row", l["file-item-row"]), children: k }),
56
+ e.size != null && /* @__PURE__ */ i("span", { className: t("file-item-row", l["file-item-row"]), children: b(e.size) })
57
+ ] }),
58
+ e.tags && e.tags.length > 0 && /* @__PURE__ */ i(D, { tags: e.tags, className: t("file-item-col", l["file-item-col"]) })
59
+ ] })
60
+ ] }),
61
+ /* @__PURE__ */ o("div", { className: t("file-item-wrap", l["file-item-wrap"]), children: [
62
+ s && /* @__PURE__ */ i("span", { className: t("file-item-panel", l["file-item-panel"]), children: s }),
63
+ /* @__PURE__ */ i("div", { className: t("file-item-action-group", l["file-item-action-group"]), children: v.map((r) => /* @__PURE__ */ i(I, { title: r.tooltip, children: /* @__PURE__ */ i(
64
+ P,
65
+ {
66
+ type: "text",
67
+ size: "small",
68
+ icon: r.icon,
69
+ onClick: (F) => {
70
+ F.stopPropagation(), r.onClick(a);
71
+ }
72
+ }
73
+ ) }, r.key)) })
74
+ ] })
75
+ ] }) }),
76
+ /* @__PURE__ */ i(A, { open: u, file: e, onClose: () => p(!1) })
77
+ ] });
78
+ };
79
+ export {
80
+ R as FileItem
81
+ };
82
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../../src/components/File/FileItem/index.tsx"],"sourcesContent":["import { FileTags } from '@/components/Tag';\nimport { Trash2, Download, Eye } from '@/components/Icons';\nimport { formatFileSize } from '@/utils/format';\nimport { Button, Tooltip } from 'antd';\nimport React, { useState } from 'react';\nimport FilePreviewModal from '../FilePreviewModal';\nimport { getFileIcon, getFileTypeName, normalizeFileDisplayItem } from '../fileDisplay';\nimport type { FileDisplayItem } from '../types';\nimport styles from './style.module.scss';\nimport classNames from 'classnames';\n\nexport interface FileItemAction {\n key: string;\n icon: React.ReactNode;\n tooltip: string;\n onClick: (file: FileDisplayItem) => void;\n}\n\nexport interface FileItemProps {\n file: FileDisplayItem;\n status?: React.ReactNode;\n showDownload?: boolean;\n showDelete?: boolean;\n showPreview?: boolean;\n actions?: FileItemAction[];\n onDownload?: (file: FileDisplayItem) => void;\n onDelete?: (file: FileDisplayItem) => void;\n onPreview?: (file: FileDisplayItem) => void;\n}\n\nconst FileItem: React.FC<FileItemProps> = ({\n file,\n status,\n showDownload = true,\n showDelete = false,\n showPreview = true,\n actions,\n onDownload,\n onDelete,\n onPreview,\n}) => {\n const [previewOpen, setPreviewOpen] = useState(false);\n const resolvedFile = normalizeFileDisplayItem(file);\n\n const handleDownload = () => {\n if (onDownload) {\n onDownload(resolvedFile);\n return;\n }\n if (resolvedFile.url) window.open(resolvedFile.url, '_blank');\n };\n\n const handlePreview = () => {\n if (onPreview) onPreview(resolvedFile);\n else setPreviewOpen(true);\n };\n\n const defaultActions: FileItemAction[] = [];\n if (showPreview) {\n defaultActions.push({\n key: 'preview',\n icon: <Eye />,\n tooltip: '预览',\n onClick: () => handlePreview(),\n });\n }\n if (showDownload) {\n defaultActions.push({\n key: 'download',\n icon: <Download />,\n tooltip: '下载',\n onClick: () => handleDownload(),\n });\n }\n if (showDelete && onDelete) {\n defaultActions.push({\n key: 'delete',\n icon: <Trash2 />,\n tooltip: '删除',\n onClick: () => onDelete(resolvedFile),\n });\n }\n\n const allActions = [...defaultActions, ...(actions ?? [])];\n const typeName = getFileTypeName(resolvedFile.name, resolvedFile.mimeType);\n\n return (\n <>\n <div className={classNames('file-item-root', styles['file-item-root'])}>\n <div className={classNames('file-item-container', styles['file-item-container'])}>\n <div className={classNames('file-item-wrapper', styles['file-item-wrapper'])}>\n <span className={classNames('file-item-inner', styles['file-item-inner'])}>\n {getFileIcon(resolvedFile.name, resolvedFile.mimeType)}\n </span>\n <div className={classNames('file-item-header', styles['file-item-header'])}>\n <div className={classNames('file-item-body', styles['file-item-body'])}>\n <span className={classNames('file-item-footer', styles['file-item-footer'])} title={resolvedFile.name}>\n {resolvedFile.name}\n </span>\n <span className={classNames('file-item-row', styles['file-item-row'])}>{typeName}</span>\n {resolvedFile.size != null && (\n <span className={classNames('file-item-row', styles['file-item-row'])}>\n {formatFileSize(resolvedFile.size)}\n </span>\n )}\n </div>\n {resolvedFile.tags && resolvedFile.tags.length > 0 && (\n <FileTags tags={resolvedFile.tags} className={classNames('file-item-col', styles['file-item-col'])} />\n )}\n </div>\n </div>\n\n <div className={classNames('file-item-wrap', styles['file-item-wrap'])}>\n {status && <span className={classNames('file-item-panel', styles['file-item-panel'])}>{status}</span>}\n <div className={classNames('file-item-action-group', styles['file-item-action-group'])}>\n {allActions.map((action) => (\n <Tooltip key={action.key} title={action.tooltip}>\n <Button\n type=\"text\"\n size=\"small\"\n icon={action.icon}\n onClick={(e) => {\n e.stopPropagation();\n action.onClick(file);\n }}\n />\n </Tooltip>\n ))}\n </div>\n </div>\n </div>\n </div>\n <FilePreviewModal open={previewOpen} file={resolvedFile} onClose={() => setPreviewOpen(false)} />\n </>\n );\n};\n\nexport { FileItem };\nexport default FileItem;\n"],"names":["FileItem","file","status","showDownload","showDelete","showPreview","actions","onDownload","onDelete","onPreview","previewOpen","setPreviewOpen","useState","resolvedFile","normalizeFileDisplayItem","handleDownload","handlePreview","defaultActions","Eye","Download","Trash2","allActions","typeName","getFileTypeName","jsxs","Fragment","jsx","classNames","styles","getFileIcon","formatFileSize","FileTags","action","Tooltip","Button","e","FilePreviewModal"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ const i = {
2
+ "file-item-root": "_file-item-root_lmij6_1",
3
+ "file-item-container": "_file-item-container_lmij6_8",
4
+ "file-item-wrapper": "_file-item-wrapper_lmij6_18",
5
+ "file-item-inner": "_file-item-inner_lmij6_25",
6
+ "file-item-header": "_file-item-header_lmij6_29",
7
+ "file-item-body": "_file-item-body_lmij6_34",
8
+ "file-item-footer": "_file-item-footer_lmij6_40",
9
+ "file-item-row": "_file-item-row_lmij6_47",
10
+ "file-item-col": "_file-item-col_lmij6_53",
11
+ "file-item-wrap": "_file-item-wrap_lmij6_18",
12
+ "file-item-panel": "_file-item-panel_lmij6_66",
13
+ "file-item-action-group": "_file-item-action-group_lmij6_71"
14
+ };
15
+ export {
16
+ i as default
17
+ };
18
+ //# sourceMappingURL=style.module.scss.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;"}
@@ -0,0 +1,27 @@
1
+ import { jsxs as n, jsx as a } from "react/jsx-runtime";
2
+ import { normalizeFileDisplayItem as r, getFileIcon as t, getFileTypeName as o } from "../fileDisplay.js";
3
+ import l from "./style.module.scss.js";
4
+ import p from "classnames";
5
+ const h = ({ file: s, onClick: i }) => {
6
+ const e = r(s);
7
+ return /* @__PURE__ */ n(
8
+ "a",
9
+ {
10
+ className: p("file-link-actions", l["file-link-actions"]),
11
+ onClick: (m) => {
12
+ m.preventDefault(), i == null || i(e);
13
+ },
14
+ href: e.url ?? "#",
15
+ title: e.name,
16
+ children: [
17
+ /* @__PURE__ */ a("span", { className: l["file-link-inner"], children: t(e.name, e.mimeType) }),
18
+ /* @__PURE__ */ a("span", { className: l["file-link-toolbar"], children: e.name }),
19
+ /* @__PURE__ */ a("span", { className: l["file-link-row"], children: o(e.name, e.mimeType) })
20
+ ]
21
+ }
22
+ );
23
+ };
24
+ export {
25
+ h as default
26
+ };
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../../src/components/File/FileLink/index.tsx"],"sourcesContent":["import type { FileDisplayItem } from '../types';\nimport { getFileIcon, getFileTypeName, normalizeFileDisplayItem } from '../fileDisplay';\nimport React from 'react';\nimport styles from './style.module.scss';\nimport classNames from 'classnames';\n\nexport interface FileLinkProps {\n file: FileDisplayItem;\n onClick?: (file: FileDisplayItem) => void;\n}\n\nconst FileLink: React.FC<FileLinkProps> = ({ file, onClick }) => {\n const resolvedFile = normalizeFileDisplayItem(file);\n\n return (\n <a\n className={classNames('file-link-actions', styles['file-link-actions'])}\n onClick={(e) => { e.preventDefault(); onClick?.(resolvedFile); }}\n href={resolvedFile.url ?? '#'}\n title={resolvedFile.name}\n >\n <span className={styles['file-link-inner']}>{getFileIcon(resolvedFile.name, resolvedFile.mimeType)}</span>\n <span className={styles['file-link-toolbar']}>{resolvedFile.name}</span>\n <span className={styles['file-link-row']}>{getFileTypeName(resolvedFile.name, resolvedFile.mimeType)}</span>\n </a>\n );\n};\n\nexport default FileLink;\n"],"names":["FileLink","file","onClick","resolvedFile","normalizeFileDisplayItem","jsxs","classNames","styles","e","jsx","getFileTypeName"],"mappings":";;;;AAWA,MAAMA,IAAoC,CAAC,EAAE,MAAAC,GAAM,SAAAC,QAAc;AAC/D,QAAMC,IAAeC,EAAyBH,CAAI;AAElD,SACA,gBAAAI;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC,EAAW,qBAAqBC,EAAO,mBAAmB,CAAC;AAAA,MACtE,SAAS,CAACC,MAAM;AAAE,QAAAA,EAAE,eAAA,GAAkBN,KAAA,QAAAA,EAAUC;AAAA,MAAe;AAAA,MAC/D,MAAMA,EAAa,OAAO;AAAA,MAC1B,OAAOA,EAAa;AAAA,MAEpB,UAAA;AAAA,QAAA,gBAAAM,EAAC,QAAA,EAAK,WAAWF,EAAO,iBAAiB,GAAI,YAAYJ,EAAa,MAAMA,EAAa,QAAQ,EAAA,CAAE;AAAA,0BAClG,QAAA,EAAK,WAAWI,EAAO,mBAAmB,GAAI,YAAa,MAAK;AAAA,QACjE,gBAAAE,EAAC,QAAA,EAAK,WAAWF,EAAO,eAAe,GAAI,UAAAG,EAAgBP,EAAa,MAAMA,EAAa,QAAQ,EAAA,CAAE;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGzG;"}
@@ -0,0 +1,10 @@
1
+ const i = {
2
+ "file-link-inner": "_file-link-inner_uetzp_1",
3
+ "file-link-row": "_file-link-row_uetzp_5",
4
+ "file-link-actions": "_file-link-actions_uetzp_11",
5
+ "file-link-toolbar": "_file-link-toolbar_uetzp_22"
6
+ };
7
+ export {
8
+ i as default
9
+ };
10
+ //# sourceMappingURL=style.module.scss.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -0,0 +1,49 @@
1
+ import { jsxs as a, jsx as i, Fragment as f } from "react/jsx-runtime";
2
+ import { formatFileSize as d } from "../../../utils/format.js";
3
+ import { CloudDownload as v } from "../../Icons/index.js";
4
+ import { Button as w, Empty as h, Image as u } from "antd";
5
+ import { normalizeFileDisplayItem as g, getFileIcon as N, getFileTypeName as y } from "../fileDisplay.js";
6
+ import r from "./style.module.scss.js";
7
+ import p from "classnames";
8
+ function F(l, t) {
9
+ return t ?? l.url ?? l.thumbnailUrl;
10
+ }
11
+ function o(l) {
12
+ var n;
13
+ if ((l.mimeType ?? "").startsWith("image/")) return !0;
14
+ const s = ((n = (l.name ?? "").split(".").pop()) == null ? void 0 : n.toLowerCase()) ?? "";
15
+ return ["png", "jpg", "jpeg", "gif", "webp", "svg"].includes(s);
16
+ }
17
+ const k = ({
18
+ file: l,
19
+ url: t,
20
+ unsupportedMessage: s = "暂不支持预览此文件类型",
21
+ title: n,
22
+ extra: c
23
+ }) => {
24
+ const e = g(l), m = F(e, t);
25
+ return /* @__PURE__ */ a("div", { className: p("file-preview", r["file-preview"]), children: [
26
+ /* @__PURE__ */ a("div", { className: p("file-preview-header", r["file-preview-header"]), children: [
27
+ /* @__PURE__ */ i("div", { className: p("file-preview-title", r["file-preview-title"]), children: n ?? /* @__PURE__ */ a(f, { children: [
28
+ /* @__PURE__ */ i("span", { className: r["file-preview-icon"], children: N(e.name, e.mimeType) }),
29
+ /* @__PURE__ */ i("span", { children: e.name }),
30
+ /* @__PURE__ */ a("span", { className: r["file-preview-meta"], children: [
31
+ y(e.name, e.mimeType),
32
+ e.size != null && ` · ${d(e.size)}`
33
+ ] })
34
+ ] }) }),
35
+ c,
36
+ m && /* @__PURE__ */ i(w, { type: "link", icon: /* @__PURE__ */ i(v, {}), href: m, target: "_blank", rel: "noreferrer", children: "下载" })
37
+ ] }),
38
+ /* @__PURE__ */ a("div", { className: p("file-preview-body", r["file-preview-body"]), children: [
39
+ !m && /* @__PURE__ */ i(h, { description: "无可预览地址" }),
40
+ m && o(e) && /* @__PURE__ */ i(u, { src: m, alt: e.name, className: r["file-preview-image"] }),
41
+ m && !o(e) && /* @__PURE__ */ i("iframe", { src: m, title: e.name, className: r["file-preview-iframe"] }),
42
+ m && !o(l) && s && /* @__PURE__ */ i("p", { className: r["file-preview-unsupported"], children: s })
43
+ ] })
44
+ ] });
45
+ };
46
+ export {
47
+ k as default
48
+ };
49
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../../src/components/File/FilePreview/index.tsx"],"sourcesContent":["import { formatFileSize } from '@/utils/format';\nimport { CloudDownload } from '@/components/Icons';\nimport { Button, Empty, Image } from 'antd';\nimport React from 'react';\nimport { getFileIcon, getFileTypeName, normalizeFileDisplayItem } from '../fileDisplay';\nimport type { FileDisplayItem } from '../types';\nimport styles from './style.module.scss';\nimport classNames from 'classnames';\n\nexport interface FilePreviewProps {\n file: FileDisplayItem;\n url?: string;\n unsupportedMessage?: string;\n title?: React.ReactNode;\n extra?: React.ReactNode;\n}\n\nfunction resolvePreviewUrl(file: FileDisplayItem, url?: string): string | undefined {\n return url ?? file.url ?? file.thumbnailUrl;\n}\n\nfunction isImage(file: FileDisplayItem): boolean {\n const mime = file.mimeType ?? '';\n if (mime.startsWith('image/')) return true;\n const ext = (file.name ?? '').split('.').pop()?.toLowerCase() ?? '';\n return ['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg'].includes(ext);\n}\n\nconst FilePreview: React.FC<FilePreviewProps> = ({\n file,\n url,\n unsupportedMessage = '暂不支持预览此文件类型',\n title,\n extra,\n}) => {\n const resolvedFile = normalizeFileDisplayItem(file);\n const previewUrl = resolvePreviewUrl(resolvedFile, url);\n\n return (\n <div className={classNames('file-preview', styles['file-preview'])}>\n <div className={classNames('file-preview-header', styles['file-preview-header'])}>\n <div className={classNames('file-preview-title', styles['file-preview-title'])}>\n {title ?? (\n <>\n <span className={styles['file-preview-icon']}>{getFileIcon(resolvedFile.name, resolvedFile.mimeType)}</span>\n <span>{resolvedFile.name}</span>\n <span className={styles['file-preview-meta']}>\n {getFileTypeName(resolvedFile.name, resolvedFile.mimeType)}\n {resolvedFile.size != null && ` · ${formatFileSize(resolvedFile.size)}`}\n </span>\n </>\n )}\n </div>\n {extra}\n {previewUrl && (\n <Button type=\"link\" icon={<CloudDownload />} href={previewUrl} target=\"_blank\" rel=\"noreferrer\">\n 下载\n </Button>\n )}\n </div>\n <div className={classNames('file-preview-body', styles['file-preview-body'])}>\n {!previewUrl && <Empty description=\"无可预览地址\" />}\n {previewUrl && isImage(resolvedFile) && (\n <Image src={previewUrl} alt={resolvedFile.name} className={styles['file-preview-image']} />\n )}\n {previewUrl && !isImage(resolvedFile) && (\n <iframe src={previewUrl} title={resolvedFile.name} className={styles['file-preview-iframe']} />\n )}\n {previewUrl && !isImage(file) && unsupportedMessage && (\n <p className={styles['file-preview-unsupported']}>{unsupportedMessage}</p>\n )}\n </div>\n </div>\n );\n};\n\nexport default FilePreview;\n"],"names":["resolvePreviewUrl","file","url","isImage","ext","_a","FilePreview","unsupportedMessage","title","extra","resolvedFile","normalizeFileDisplayItem","previewUrl","jsxs","classNames","styles","jsx","Fragment","getFileTypeName","formatFileSize","Button","CloudDownload","Empty","Image"],"mappings":";;;;;;;AAiBA,SAASA,EAAkBC,GAAuBC,GAAkC;AAClF,SAAOA,KAAOD,EAAK,OAAOA,EAAK;AACjC;AAEA,SAASE,EAAQF,GAAgC;;AAE/C,OADaA,EAAK,YAAY,IACrB,WAAW,QAAQ,EAAG,QAAO;AACtC,QAAMG,MAAOC,KAAAJ,EAAK,QAAQ,IAAI,MAAM,GAAG,EAAE,UAA5B,gBAAAI,EAAmC,kBAAiB;AACjE,SAAO,CAAC,OAAO,OAAO,QAAQ,OAAO,QAAQ,KAAK,EAAE,SAASD,CAAG;AAClE;AAEA,MAAME,IAA0C,CAAC;AAAA,EAC/C,MAAAL;AAAA,EACA,KAAAC;AAAA,EACA,oBAAAK,IAAqB;AAAA,EACrB,OAAAC;AAAA,EACA,OAAAC;AACF,MAAM;AACJ,QAAMC,IAAeC,EAAyBV,CAAI,GAC5CW,IAAaZ,EAAkBU,GAAcR,CAAG;AAEtD,SACE,gBAAAW,EAAC,SAAI,WAAWC,EAAW,gBAAgBC,EAAO,cAAc,CAAC,GAC/D,UAAA;AAAA,IAAA,gBAAAF,EAAC,SAAI,WAAWC,EAAW,uBAAuBC,EAAO,qBAAqB,CAAC,GAC7E,UAAA;AAAA,MAAA,gBAAAC,EAAC,OAAA,EAAI,WAAWF,EAAW,sBAAsBC,EAAO,oBAAoB,CAAC,GAC1E,UAAAP,KACC,gBAAAK,EAAAI,GAAA,EACE,UAAA;AAAA,QAAA,gBAAAD,EAAC,QAAA,EAAK,WAAWD,EAAO,mBAAmB,GAAI,YAAYL,EAAa,MAAMA,EAAa,QAAQ,EAAA,CAAE;AAAA,QACrG,gBAAAM,EAAC,QAAA,EAAM,UAAAN,EAAa,KAAA,CAAK;AAAA,QACzB,gBAAAG,EAAC,QAAA,EAAK,WAAWE,EAAO,mBAAmB,GACxC,UAAA;AAAA,UAAAG,EAAgBR,EAAa,MAAMA,EAAa,QAAQ;AAAA,UACxDA,EAAa,QAAQ,QAAQ,MAAMS,EAAeT,EAAa,IAAI,CAAC;AAAA,QAAA,EAAA,CACvE;AAAA,MAAA,EAAA,CACF,EAAA,CAEJ;AAAA,MACCD;AAAA,MACAG,KACC,gBAAAI,EAACI,GAAA,EAAO,MAAK,QAAO,MAAM,gBAAAJ,EAACK,GAAA,CAAA,CAAc,GAAI,MAAMT,GAAY,QAAO,UAAS,KAAI,cAAa,UAAA,KAAA,CAEhG;AAAA,IAAA,GAEJ;AAAA,IACA,gBAAAC,EAAC,SAAI,WAAWC,EAAW,qBAAqBC,EAAO,mBAAmB,CAAC,GACxE,UAAA;AAAA,MAAA,CAACH,KAAc,gBAAAI,EAACM,GAAA,EAAM,aAAY,SAAA,CAAS;AAAA,MAC3CV,KAAcT,EAAQO,CAAY,uBAChCa,GAAA,EAAM,KAAKX,GAAY,KAAKF,EAAa,MAAM,WAAWK,EAAO,oBAAoB,GAAG;AAAA,MAE1FH,KAAc,CAACT,EAAQO,CAAY,KAClC,gBAAAM,EAAC,UAAA,EAAO,KAAKJ,GAAY,OAAOF,EAAa,MAAM,WAAWK,EAAO,qBAAqB,GAAG;AAAA,MAE9FH,KAAc,CAACT,EAAQF,CAAI,KAAKM,KAC/B,gBAAAS,EAAC,KAAA,EAAE,WAAWD,EAAO,0BAA0B,GAAI,UAAAR,EAAA,CAAmB;AAAA,IAAA,EAAA,CAE1E;AAAA,EAAA,GACF;AAEJ;"}
@@ -0,0 +1,5 @@
1
+ const s = {};
2
+ export {
3
+ s as default
4
+ };
5
+ //# sourceMappingURL=style.module.scss.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -0,0 +1,12 @@
1
+ import { jsx as o } from "react/jsx-runtime";
2
+ import { Modal as m } from "antd";
3
+ import n from "../FilePreview/index.js";
4
+ import { normalizeFileDisplayItem as d } from "../fileDisplay.js";
5
+ const c = ({ open: r, file: i, url: l, onClose: t }) => {
6
+ const e = d(i);
7
+ return /* @__PURE__ */ o(m, { open: r, onCancel: t, footer: null, width: 900, destroyOnHidden: !0, title: e.name, children: /* @__PURE__ */ o(n, { file: e, url: l }) });
8
+ };
9
+ export {
10
+ c as default
11
+ };
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../../src/components/File/FilePreviewModal/index.tsx"],"sourcesContent":["import { Modal } from 'antd';\nimport React from 'react';\nimport FilePreview from '../FilePreview';\nimport { normalizeFileDisplayItem } from '../fileDisplay';\nimport type { FileDisplayItem } from '../types';\n\nexport interface FilePreviewModalProps {\n open: boolean;\n file: FileDisplayItem;\n url?: string;\n onClose: () => void;\n}\n\nconst FilePreviewModal: React.FC<FilePreviewModalProps> = ({ open, file, url, onClose }) => {\n const resolvedFile = normalizeFileDisplayItem(file);\n\n return (\n <Modal open={open} onCancel={onClose} footer={null} width={900} destroyOnHidden title={resolvedFile.name}>\n <FilePreview file={resolvedFile} url={url} />\n </Modal>\n );\n};\n\nexport default FilePreviewModal;\n"],"names":["FilePreviewModal","open","file","url","onClose","resolvedFile","normalizeFileDisplayItem","Modal","jsx","FilePreview"],"mappings":";;;;AAaA,MAAMA,IAAoD,CAAC,EAAE,MAAAC,GAAM,MAAAC,GAAM,KAAAC,GAAK,SAAAC,QAAc;AAC1F,QAAMC,IAAeC,EAAyBJ,CAAI;AAElD,2BACCK,GAAA,EAAM,MAAAN,GAAY,UAAUG,GAAS,QAAQ,MAAM,OAAO,KAAK,iBAAe,IAAC,OAAOC,EAAa,MAClG,UAAA,gBAAAG,EAACC,KAAY,MAAMJ,GAAc,KAAAF,GAAU,EAAA,CAC7C;AAEF;"}
@@ -0,0 +1,67 @@
1
+ import { jsx as m } from "react/jsx-runtime";
2
+ import { FileArchive as p, FileImage as r, Presentation as l, FileSpreadsheet as i, FileText as c, File as u } from "../Icons/index.js";
3
+ const x = {
4
+ pdf: c,
5
+ doc: c,
6
+ docx: c,
7
+ txt: c,
8
+ md: c,
9
+ xls: i,
10
+ xlsx: i,
11
+ csv: i,
12
+ ppt: l,
13
+ pptx: l,
14
+ png: r,
15
+ jpg: r,
16
+ jpeg: r,
17
+ gif: r,
18
+ webp: r,
19
+ zip: p,
20
+ rar: p,
21
+ "7z": p
22
+ };
23
+ function s(e) {
24
+ const t = e.lastIndexOf(".");
25
+ return t >= 0 ? e.slice(t + 1).toLowerCase() : "";
26
+ }
27
+ function F(e) {
28
+ const t = e.trim();
29
+ if (!t) return "未命名文件";
30
+ try {
31
+ const d = new URL(t, "http://placeholder.local").pathname.split("/").filter(Boolean).pop() ?? "", a = decodeURIComponent(d);
32
+ if (a) return a;
33
+ } catch {
34
+ }
35
+ const n = t.split(/[/?#]/).filter(Boolean).pop() ?? "";
36
+ try {
37
+ return decodeURIComponent(n) || "未命名文件";
38
+ } catch {
39
+ return n || "未命名文件";
40
+ }
41
+ }
42
+ function g(e) {
43
+ var o;
44
+ const t = ((o = e.name) == null ? void 0 : o.trim()) || (e.url ? F(e.url) : "未命名文件"), n = e.extension ?? s(t);
45
+ return {
46
+ ...e,
47
+ name: t,
48
+ extension: n || e.extension
49
+ };
50
+ }
51
+ function h(e, t) {
52
+ const n = s(e), o = x[n] ?? u;
53
+ return /* @__PURE__ */ m(o, {});
54
+ }
55
+ function C(e, t) {
56
+ var o;
57
+ const n = s(e);
58
+ return n ? n.toUpperCase() : t ? ((o = t.split("/").pop()) == null ? void 0 : o.toUpperCase()) ?? "FILE" : "FILE";
59
+ }
60
+ export {
61
+ s as getFileExtension,
62
+ h as getFileIcon,
63
+ C as getFileTypeName,
64
+ g as normalizeFileDisplayItem,
65
+ F as parseFileNameFromUrl
66
+ };
67
+ //# sourceMappingURL=fileDisplay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileDisplay.js","sources":["../../../src/components/File/fileDisplay.tsx"],"sourcesContent":["import React from 'react';\nimport {\n File,\n FileArchive,\n FileImage,\n FileSpreadsheet,\n FileText,\n Presentation,\n} from '@/components/Icons';\nimport type { FileDisplayItem } from './types';\n\nconst EXT_ICON_MAP: Record<string, React.FC<{ className?: string }>> = {\n pdf: FileText,\n doc: FileText,\n docx: FileText,\n txt: FileText,\n md: FileText,\n xls: FileSpreadsheet,\n xlsx: FileSpreadsheet,\n csv: FileSpreadsheet,\n ppt: Presentation,\n pptx: Presentation,\n png: FileImage,\n jpg: FileImage,\n jpeg: FileImage,\n gif: FileImage,\n webp: FileImage,\n zip: FileArchive,\n rar: FileArchive,\n '7z': FileArchive,\n};\n\nexport function getFileExtension(name: string): string {\n const dot = name.lastIndexOf('.');\n return dot >= 0 ? name.slice(dot + 1).toLowerCase() : '';\n}\n\n/** 从 URL 路径解析文件名(decodeURIComponent,失败时回退为「未命名文件」) */\nexport function parseFileNameFromUrl(url: string): string {\n const trimmed = url.trim();\n if (!trimmed) return '未命名文件';\n\n try {\n const pathname = new URL(trimmed, 'http://placeholder.local').pathname;\n const segment = pathname.split('/').filter(Boolean).pop() ?? '';\n const decoded = decodeURIComponent(segment);\n if (decoded) return decoded;\n } catch {\n // fall through\n }\n\n const fallback = trimmed.split(/[/?#]/).filter(Boolean).pop() ?? '';\n try {\n const decoded = decodeURIComponent(fallback);\n return decoded || '未命名文件';\n } catch {\n return fallback || '未命名文件';\n }\n}\n\n/** 补全 name / extension:name 缺省时从 url 解析 */\nexport function normalizeFileDisplayItem(file: FileDisplayItem): FileDisplayItem & { name: string } {\n const name = file.name?.trim() || (file.url ? parseFileNameFromUrl(file.url) : '未命名文件');\n const extension = file.extension ?? getFileExtension(name);\n\n return {\n ...file,\n name,\n extension: extension || file.extension,\n };\n}\n\nexport function getFileIcon(name: string, _mimeType?: string): React.ReactNode {\n const ext = getFileExtension(name);\n const Icon = EXT_ICON_MAP[ext] ?? File;\n return <Icon />;\n}\n\nexport function getFileTypeName(name: string, mimeType?: string): string {\n const ext = getFileExtension(name);\n if (ext) return ext.toUpperCase();\n if (mimeType) return mimeType.split('/').pop()?.toUpperCase() ?? 'FILE';\n return 'FILE';\n}\n"],"names":["EXT_ICON_MAP","FileText","FileSpreadsheet","Presentation","FileImage","FileArchive","getFileExtension","name","dot","parseFileNameFromUrl","url","trimmed","segment","decoded","fallback","normalizeFileDisplayItem","file","_a","extension","getFileIcon","_mimeType","ext","Icon","File","getFileTypeName","mimeType"],"mappings":";;AAWA,MAAMA,IAAiE;AAAA,EACrE,KAAKC;AAAA,EACL,KAAKA;AAAA,EACL,MAAMA;AAAA,EACN,KAAKA;AAAA,EACL,IAAIA;AAAA,EACJ,KAAKC;AAAA,EACL,MAAMA;AAAA,EACN,KAAKA;AAAA,EACL,KAAKC;AAAA,EACL,MAAMA;AAAA,EACN,KAAKC;AAAA,EACL,KAAKA;AAAA,EACL,MAAMA;AAAA,EACN,KAAKA;AAAA,EACL,MAAMA;AAAA,EACN,KAAKC;AAAA,EACL,KAAKA;AAAA,EACL,MAAMA;AACR;AAEO,SAASC,EAAiBC,GAAsB;AACrD,QAAMC,IAAMD,EAAK,YAAY,GAAG;AAChC,SAAOC,KAAO,IAAID,EAAK,MAAMC,IAAM,CAAC,EAAE,gBAAgB;AACxD;AAGO,SAASC,EAAqBC,GAAqB;AACxD,QAAMC,IAAUD,EAAI,KAAA;AACpB,MAAI,CAACC,EAAS,QAAO;AAErB,MAAI;AAEF,UAAMC,IADW,IAAI,IAAID,GAAS,0BAA0B,EAAE,SACrC,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAA,KAAS,IACvDE,IAAU,mBAAmBD,CAAO;AAC1C,QAAIC,EAAS,QAAOA;AAAA,EACtB,QAAQ;AAAA,EAER;AAEA,QAAMC,IAAWH,EAAQ,MAAM,OAAO,EAAE,OAAO,OAAO,EAAE,IAAA,KAAS;AACjE,MAAI;AAEF,WADgB,mBAAmBG,CAAQ,KACzB;AAAA,EACpB,QAAQ;AACN,WAAOA,KAAY;AAAA,EACrB;AACF;AAGO,SAASC,EAAyBC,GAA2D;;AAClG,QAAMT,MAAOU,IAAAD,EAAK,SAAL,gBAAAC,EAAW,YAAWD,EAAK,MAAMP,EAAqBO,EAAK,GAAG,IAAI,UACzEE,IAAYF,EAAK,aAAaV,EAAiBC,CAAI;AAEzD,SAAO;AAAA,IACL,GAAGS;AAAA,IACH,MAAAT;AAAA,IACA,WAAWW,KAAaF,EAAK;AAAA,EAAA;AAEjC;AAEO,SAASG,EAAYZ,GAAca,GAAqC;AAC7E,QAAMC,IAAMf,EAAiBC,CAAI,GAC3Be,IAAOtB,EAAaqB,CAAG,KAAKE;AAClC,2BAAQD,GAAA,EAAK;AACf;AAEO,SAASE,EAAgBjB,GAAckB,GAA2B;;AACvE,QAAMJ,IAAMf,EAAiBC,CAAI;AACjC,SAAIc,IAAYA,EAAI,YAAA,IAChBI,MAAiBR,IAAAQ,EAAS,MAAM,GAAG,EAAE,IAAA,MAApB,gBAAAR,EAA2B,kBAAiB,SAC1D;AACT;"}