@spacecorexdev/core 0.0.4 → 0.0.5

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 (132) hide show
  1. package/package.json +2 -36
  2. package/src/api/_base.ts +243 -0
  3. package/src/api/index.ts +17 -0
  4. package/src/api/project.ts +1345 -0
  5. package/src/api/user.ts +1174 -0
  6. package/src/contract.ts +50 -0
  7. package/src/hooks/index.ts +2 -0
  8. package/{dist/hooks/index.js → src/hooks/useLongPress.ts} +53 -49
  9. package/src/hooks/useOnlineStatus.ts +22 -0
  10. package/src/index.ts +14 -0
  11. package/src/types/id.ts +2 -0
  12. package/src/types/index.ts +5 -0
  13. package/src/types/project/base.ts +63 -0
  14. package/src/types/project/contract.ts +79 -0
  15. package/src/types/project/contractStatus.tsx +15 -0
  16. package/src/types/project/index.ts +5 -0
  17. package/src/types/project/member.ts +46 -0
  18. package/src/types/project/progress.ts +43 -0
  19. package/src/types/projectRole.ts +17 -0
  20. package/src/types/theme.ts +1 -0
  21. package/src/types/user/index.ts +1 -0
  22. package/src/types/user/role.ts +7 -0
  23. package/src/ui/CommentTimeline/index.tsx +330 -0
  24. package/src/ui/FileManager/FileContextMenu.tsx +628 -0
  25. package/src/ui/FileManager/FileGridView.tsx +529 -0
  26. package/src/ui/FileManager/FileTableView.tsx +405 -0
  27. package/src/ui/FileManager/FileToolbar.tsx +119 -0
  28. package/src/ui/FileManager/FileVersionHistoryModal.tsx +175 -0
  29. package/src/ui/FileManager/MoveCopyToProjectModal.tsx +119 -0
  30. package/src/ui/FileManager/ShareToWechatModal.tsx +419 -0
  31. package/src/ui/FileManager/hooks/useFileManagerActions.ts +2532 -0
  32. package/src/ui/FileManager/hooks/useFileManagerState.ts +419 -0
  33. package/src/ui/FileManager/index.tsx +580 -0
  34. package/src/ui/FileManager/projectFileManagerApi.ts +57 -0
  35. package/src/ui/FileManager/types.ts +184 -0
  36. package/src/ui/FileManager/utils/fileDeltaWorker.ts +193 -0
  37. package/src/ui/FileManager/utils/fileTree.ts +178 -0
  38. package/src/ui/FileManager/utils/fileUpload.ts +714 -0
  39. package/src/ui/FileManager/utils/fileUtils.ts +65 -0
  40. package/src/ui/InvoiceRecordsList/index.tsx +813 -0
  41. package/src/ui/MyFileSelectorModal.tsx +261 -0
  42. package/src/ui/ProjectSelector/index.tsx +472 -0
  43. package/src/ui/ProjectSelector/projectCache.ts +40 -0
  44. package/src/ui/RoleSelector/index.tsx +473 -0
  45. package/src/ui/RoleSelector/roleCache.ts +40 -0
  46. package/src/ui/UIAlert.tsx +399 -0
  47. package/src/ui/UIAlertExample.tsx +129 -0
  48. package/src/ui/UIConfirm.tsx +335 -0
  49. package/src/ui/UIConfirmExample.tsx +165 -0
  50. package/src/ui/UIDatePicker.tsx +146 -0
  51. package/src/ui/UIDateRangePicker.tsx +38 -0
  52. package/src/ui/UIFilePreview/ExcelEditor/index.tsx +617 -0
  53. package/src/ui/UIFilePreview/ExcelEditor/types.ts +24 -0
  54. package/src/ui/UIFilePreview/ExportDropdown.css +85 -0
  55. package/src/ui/UIFilePreview/ExportDropdown.tsx +109 -0
  56. package/src/ui/UIFilePreview/IndexedDBUtils.ts +564 -0
  57. package/src/ui/UIFilePreview/MarkdownEditor/exportMarkdownPdf.ts +576 -0
  58. package/src/ui/UIFilePreview/MarkdownEditor/index.tsx +677 -0
  59. package/src/ui/UIFilePreview/MarkdownEditor/markdownEditor.css +1005 -0
  60. package/src/ui/UIFilePreview/MarkdownEditor/types.ts +15 -0
  61. package/src/ui/UIFilePreview/PPTXEditor/index.tsx +602 -0
  62. package/src/ui/UIFilePreview/RichDocEditor/exportRDocMarkdown.ts +77 -0
  63. package/src/ui/UIFilePreview/RichDocEditor/exportRDocPdf.ts +374 -0
  64. package/src/ui/UIFilePreview/RichDocEditor/index.tsx +730 -0
  65. package/src/ui/UIFilePreview/RichDocEditor/richdoc-editor.css +59 -0
  66. package/src/ui/UIFilePreview/UIFilePreview.tsx +611 -0
  67. package/src/ui/UIFilePreview/WordEditor/index.tsx +3933 -0
  68. package/src/ui/UIFilePreview/WordEditor/style.ts +1213 -0
  69. package/src/ui/UIFilePreview/WordEditor/word-editor.css +999 -0
  70. package/src/ui/UIFilePreview/filePreview.css +193 -0
  71. package/src/ui/UIFilePreview/filetypes/archive.tsx +66 -0
  72. package/src/ui/UIFilePreview/filetypes/cad.tsx +287 -0
  73. package/src/ui/UIFilePreview/filetypes/excel.tsx +355 -0
  74. package/src/ui/UIFilePreview/filetypes/image.tsx +20 -0
  75. package/src/ui/UIFilePreview/filetypes/imageLoader.ts +63 -0
  76. package/src/ui/UIFilePreview/filetypes/pdf.tsx +156 -0
  77. package/src/ui/UIFilePreview/filetypes/ppt.tsx +535 -0
  78. package/src/ui/UIFilePreview/filetypes/pptExportPdf.ts +523 -0
  79. package/src/ui/UIFilePreview/filetypes/video.tsx +482 -0
  80. package/src/ui/UIFilePreview/filetypes/word.tsx +245 -0
  81. package/src/ui/UIFilePreview/filetypes/wordExportMarkdown.ts +86 -0
  82. package/src/ui/UIFilePreview/filetypes/wordExportPdf.tsx +427 -0
  83. package/src/ui/UIFilePreview/index.ts +35 -0
  84. package/src/ui/UIFilePreview/pdfPagination.ts +143 -0
  85. package/src/ui/UIFilePreview/previewUtils.tsx +531 -0
  86. package/src/ui/UIFileUpload.tsx +382 -0
  87. package/src/ui/UIImageUpload.tsx +195 -0
  88. package/src/ui/UILoading.tsx +255 -0
  89. package/src/ui/UILoadingExample.tsx +139 -0
  90. package/src/ui/UISelect.tsx +105 -0
  91. package/src/ui/UIToast.tsx +381 -0
  92. package/src/ui/UIToastExample.tsx +69 -0
  93. package/src/ui/UIToastSingle.tsx +279 -0
  94. package/src/ui/UIViewToggle.tsx +64 -0
  95. package/src/ui/UserSelector/index.tsx +583 -0
  96. package/src/ui/index.ts +84 -0
  97. package/src/ui/upload/image.ts +135 -0
  98. package/src/ui/upload/index.ts +73 -0
  99. package/src/ui/upload/submitFile.ts +106 -0
  100. package/src/ui/upload/submitForm.ts +124 -0
  101. package/src/ui/upload/upload.err.ts +15 -0
  102. package/src/ui/upload/upload.ts +250 -0
  103. package/src/utils/CacheDepartmentInfo.ts +372 -0
  104. package/src/utils/CacheFileContent.ts +315 -0
  105. package/src/utils/CachePermissionInfo.ts +235 -0
  106. package/src/utils/CacheRoleInfo.ts +303 -0
  107. package/src/utils/CacheUserInfo.ts +818 -0
  108. package/src/utils/CacheViewToggleInfo.ts +182 -0
  109. package/src/utils/MessageContentUtils.ts +268 -0
  110. package/src/utils/clipboard.ts +70 -0
  111. package/src/utils/companyEmail.ts +19 -0
  112. package/src/utils/forbidDebugger.ts +59 -0
  113. package/src/utils/formatters.ts +94 -0
  114. package/src/utils/htmlUtils.tsx +59 -0
  115. package/src/utils/index.ts +18 -0
  116. package/src/utils/keyboard.ts +114 -0
  117. package/src/utils/mammothApi.ts +16 -0
  118. package/src/utils/polyfills.ts +928 -0
  119. package/src/utils/regex.ts +14 -0
  120. package/src/utils/storage.ts +95 -0
  121. package/src/utils/workerBootstrap.ts +87 -0
  122. package/dist/api/index.js +0 -1553
  123. package/dist/contract.js +0 -5
  124. package/dist/index.js +0 -4492
  125. package/dist/types/index.js +0 -49
  126. package/dist/ui/index.css +0 -1876
  127. package/dist/ui/index.js +0 -22245
  128. package/dist/utils/index.js +0 -4296
  129. /package/{dist → src}/styles/ant-modal.css +0 -0
  130. /package/{dist → src}/styles/ant-spin.css +0 -0
  131. /package/{dist → src}/styles/ant-table.css +0 -0
  132. /package/{dist → src}/styles/index.css +0 -0
@@ -0,0 +1,279 @@
1
+ /* eslint-disable react-refresh/only-export-components */
2
+ /**
3
+ * UIToastSingle - 全局唯一消息提示组件
4
+ *
5
+ * 使用示例:
6
+ *
7
+ * 1. 直接调用 API(推荐):
8
+ * import { UIToastSingle } from './UIToastSingle';
9
+ *
10
+ * // 简单消息
11
+ * UIToastSingle.success('操作成功');
12
+ * UIToastSingle.error('操作失败');
13
+ * UIToastSingle.info('提示信息');
14
+ * UIToastSingle.warning('警告信息');
15
+ *
16
+ * // 完整配置
17
+ * UIToastSingle.success({
18
+ * key: 'my-toast', // 唯一标识,用于更新或关闭
19
+ * message: '操作成功',
20
+ * descs: '这是一个详细描述',
21
+ * duration: 5, // 秒,0表示不自动关闭
22
+ * placement: 'topRight',
23
+ * onClose: () => console.log('Toast已关闭')
24
+ * });
25
+ *
26
+ * // 下载进度提示(不自动关闭,手动关闭)
27
+ * UIToastSingle.info({
28
+ * key: 'download-progress',
29
+ * message: '下载进度: 50%',
30
+ * duration: 0 // 不自动关闭
31
+ * });
32
+ * // 下载完成后手动关闭
33
+ * UIToastSingle.close('download-progress');
34
+ *
35
+ * // 销毁所有 toast
36
+ * UIToastSingle.destroy();
37
+ *
38
+ * 特点:
39
+ * - 同一类型的 toast 只会显示一个,新的会替换旧的
40
+ * - 可以通过 key 自定义唯一标识
41
+ * - 可以手动关闭指定 key 的 toast
42
+ */
43
+
44
+ import React from 'react';
45
+ import { notification } from 'antd';
46
+ import { CheckCircleOutlined, CloseCircleOutlined, InfoCircleOutlined, WarningOutlined } from '@ant-design/icons';
47
+
48
+ // Toast 类型定义
49
+ type UIToastSingleType = 'success' | 'error' | 'info' | 'warning';
50
+
51
+ // Singleton Toast 配置选项
52
+ export interface UIToastSingleOptions {
53
+ key?: string;
54
+ message: React.ReactNode;
55
+ descs?: React.ReactNode;
56
+ duration?: number; // 单位:秒
57
+ placement?: 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'top' | 'bottom';
58
+ onClose?: () => void;
59
+ }
60
+
61
+ // 内部使用的完整配置对象
62
+ interface SingletonToastConfig {
63
+ key: string;
64
+ type: UIToastSingleType;
65
+ message: React.ReactNode;
66
+ descs?: React.ReactNode;
67
+ duration: number;
68
+ placement?: 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'top' | 'bottom';
69
+ onClose?: () => void;
70
+ }
71
+
72
+ // 当前活动的 toast 状态
73
+ interface CurrentToastState {
74
+ key: string;
75
+ type: UIToastSingleType;
76
+ message: React.ReactNode;
77
+ descs?: React.ReactNode;
78
+ duration: number;
79
+ placement?: 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'top' | 'bottom';
80
+ }
81
+
82
+ // 图标映射
83
+ const iconMap: Record<UIToastSingleType, React.ReactNode> = {
84
+ success: <CheckCircleOutlined style={{ color: '#52c41a' }} />,
85
+ error: <CloseCircleOutlined style={{ color: '#ff4d4f' }} />,
86
+ info: <InfoCircleOutlined style={{ color: '#1890ff' }} />,
87
+ warning: <WarningOutlined style={{ color: '#faad14' }} />
88
+ };
89
+
90
+ // 全局唯一的 toast 状态管理类
91
+ class SingletonToastManager {
92
+ private currentToast: CurrentToastState | null = null;
93
+ // 由代码主动 destroy/close 的 key 集合:这些关闭属于"编程式替换/关闭",
94
+ // 不能触发调用方传入的 onClose(例如下载进度 toast 的 onClose 是取消下载,
95
+ // 若被其他 toast 替换或同 key 刷新时误触发,会导致下载被意外 abort)。
96
+ private suppressedCloseKeys = new Set<string>();
97
+
98
+ // 编程式销毁通知:抑制该通知的用户 onClose 回调
99
+ private destroySilently(key: string) {
100
+ this.suppressedCloseKeys.add(key);
101
+ notification.destroy(key);
102
+ }
103
+
104
+ // 显示全局唯一Toast
105
+ show(config: SingletonToastConfig) {
106
+ const { key, type, message, descs, duration, placement, onClose } = config;
107
+
108
+ // 如果是同一个 key 的 toast,直接用相同 key 再次 open:
109
+ // antd 5(rc-notification)对相同 key 会原位更新通知内容并重置计时,
110
+ // 不会触发 onClose。绝不能先 destroy 再重建——destroy 会触发旧通知的
111
+ // onClose,导致例如下载进度回调每次刷新都把下载 abort 掉。
112
+ if (this.currentToast && this.currentToast.key === key) {
113
+ this.createNotification({ key, type, message, descs, duration, placement, onClose });
114
+ } else {
115
+ // 不同 key 替换旧 toast 属于编程式关闭,不应执行旧 toast 的 onClose
116
+ if (this.currentToast) {
117
+ this.destroySilently(this.currentToast.key);
118
+ }
119
+
120
+ // 创建新的 toast
121
+ this.createNotification({ key, type, message, descs, duration, placement, onClose });
122
+ }
123
+ }
124
+
125
+ // 创建通知
126
+ private createNotification(config: SingletonToastConfig) {
127
+ const { key, type, message, descs, duration, placement, onClose } = config;
128
+
129
+ // 清除可能残留的编程式关闭标记(destroy 时通知已不存在,onClose 不会触发),
130
+ // 否则该 key 以后真正被用户手动关闭时回调会被错误吞掉
131
+ this.suppressedCloseKeys.delete(key);
132
+
133
+ const notificationMethod = {
134
+ success: notification.success,
135
+ error: notification.error,
136
+ info: notification.info,
137
+ warning: notification.warning
138
+ }[type];
139
+
140
+ notificationMethod({
141
+ key,
142
+ message,
143
+ description: descs,
144
+ duration,
145
+ placement: placement || 'topRight',
146
+ icon: iconMap[type],
147
+ onClose: () => {
148
+ // 编程式关闭(被替换/同 key 刷新/主动 close)直接忽略用户回调,
149
+ // 只有用户手动点关闭按钮才执行 onClose
150
+ if (this.suppressedCloseKeys.has(key)) {
151
+ this.suppressedCloseKeys.delete(key);
152
+ if (this.currentToast?.key === key) {
153
+ this.currentToast = null;
154
+ }
155
+ return;
156
+ }
157
+ if (this.currentToast?.key === key) {
158
+ this.currentToast = null;
159
+ }
160
+ onClose?.();
161
+ }
162
+ });
163
+
164
+ // 保存当前 toast 状态
165
+ this.currentToast = {
166
+ key,
167
+ type,
168
+ message,
169
+ descs,
170
+ duration,
171
+ placement
172
+ };
173
+ }
174
+
175
+ // 关闭当前 toast
176
+ close(toastKey?: string) {
177
+ if (!this.currentToast) {
178
+ // 没有活动单例 toast 时,仅尝试销毁指定 key 的通知本身
179
+ if (toastKey) {
180
+ notification.destroy(toastKey);
181
+ }
182
+ return;
183
+ }
184
+ const key = toastKey || this.currentToast.key;
185
+ if (key !== this.currentToast.key) {
186
+ // 指定关闭的不是当前 toast(例如下载进度 toast 已被其他 toast 替换),
187
+ // 只销毁该通知,不能清空 currentToast,否则会误伤当前活动的 toast
188
+ notification.destroy(toastKey);
189
+ return;
190
+ }
191
+ this.destroySilently(key);
192
+ this.currentToast = null;
193
+ }
194
+
195
+ // 销毁所有 toast
196
+ destroy() {
197
+ if (this.currentToast) {
198
+ this.destroySilently(this.currentToast.key);
199
+ this.currentToast = null;
200
+ }
201
+ // notification.destroy() 不带 key 会销毁所有(包括其他来源的通知),
202
+ // 无法逐个抑制;当前单例自身管理的通知已在上面静默关闭。
203
+ notification.destroy();
204
+ }
205
+ }
206
+
207
+ // 单例实例
208
+ const singletonManager = new SingletonToastManager();
209
+
210
+ // Singleton Toast API
211
+ export const UIToastSingle = {
212
+ success: (options: UIToastSingleOptions | React.ReactNode, duration: number = 3) => {
213
+ const config = buildConfig('success', options, duration);
214
+ singletonManager.show(config);
215
+ },
216
+
217
+ error: (options: UIToastSingleOptions | React.ReactNode, duration: number = 3) => {
218
+ const config = buildConfig('error', options, duration);
219
+ singletonManager.show(config);
220
+ },
221
+
222
+ info: (options: UIToastSingleOptions | React.ReactNode, duration: number = 3) => {
223
+ const config = buildConfig('info', options, duration);
224
+ singletonManager.show(config);
225
+ },
226
+
227
+ warning: (options: UIToastSingleOptions | React.ReactNode, duration: number = 3) => {
228
+ const config = buildConfig('warning', options, duration);
229
+ singletonManager.show(config);
230
+ },
231
+
232
+ custom: (type: UIToastSingleType, options: UIToastSingleOptions | React.ReactNode, duration: number = 3) => {
233
+ const config = buildConfig(type, options, duration);
234
+ singletonManager.show(config);
235
+ },
236
+
237
+ close: (key?: string) => {
238
+ singletonManager.close(key);
239
+ },
240
+
241
+ destroy: () => {
242
+ singletonManager.destroy();
243
+ }
244
+ };
245
+
246
+ // 构建配置对象
247
+ function buildConfig(
248
+ type: UIToastSingleType,
249
+ options: UIToastSingleOptions | React.ReactNode,
250
+ defaultDuration: number
251
+ ): SingletonToastConfig {
252
+ // 如果是字符串或数字等基本类型,转换为 ReactNode
253
+ const config: UIToastSingleOptions = (typeof options === 'object' && options !== null
254
+ ? options
255
+ : { message: options }) as UIToastSingleOptions;
256
+
257
+ // 使用固定 key,基于类型,不基于消息内容
258
+ // 这样同一类型的 toast 只会创建/更新一个
259
+ const key = config.key || `singleton-${type}`;
260
+
261
+ return {
262
+ key,
263
+ type,
264
+ message: config.message,
265
+ descs: config.descs,
266
+ duration: config.duration ?? defaultDuration,
267
+ placement: config.placement,
268
+ onClose: config.onClose
269
+ };
270
+ }
271
+
272
+ // UIToastSingleProvider - 现在只是一个空包装器,用于保持 API 兼容性
273
+ export interface UIToastSingleProviderProps {
274
+ children: React.ReactNode;
275
+ }
276
+
277
+ export const UIToastSingleProvider: React.FC<UIToastSingleProviderProps> = ({ children }) => {
278
+ return <>{children}</>;
279
+ };
@@ -0,0 +1,64 @@
1
+ import React from 'react';
2
+ import { Button } from 'antd';
3
+ import { TableOutlined, AppstoreOutlined } from '@ant-design/icons';
4
+
5
+ interface ViewToggleProps<T extends string> {
6
+ className?: string;
7
+ viewMode: T;
8
+ onToggle: (mode: T) => void;
9
+ options: {
10
+ value: T;
11
+ icon: React.ReactNode;
12
+ tooltip?: string;
13
+ }[];
14
+ }
15
+
16
+ export function UIViewToggle<T extends string>({ className = "", viewMode, onToggle, options = [] }: ViewToggleProps<T>) {
17
+ return (
18
+ <div className={`flex justify-end ${className}`}>
19
+ <div className="bg-gray-100 rounded-button p-1 flex">
20
+ {options.map((option, index) => (
21
+ <Button
22
+ key={option.value}
23
+ type={viewMode === option.value ? 'primary' : 'text'}
24
+ icon={option.icon}
25
+ onClick={() => onToggle(option.value)}
26
+ className={`${index < options.length - 1 ? "mr-1" : ""} rounded-button`}
27
+ size="small"
28
+ title={option.tooltip}
29
+ />
30
+ ))}
31
+ </div>
32
+ </div>
33
+ );
34
+ }
35
+
36
+ export function UITableGridViewToggle({
37
+ viewMode,
38
+ onToggle,
39
+ className = ""
40
+ }: {
41
+ viewMode: 'table' | 'grid';
42
+ onToggle: (mode: 'table' | 'grid') => void;
43
+ className?: string;
44
+ }) {
45
+ return (
46
+ <UIViewToggle<'table' | 'grid'>
47
+ viewMode={viewMode}
48
+ onToggle={onToggle}
49
+ className={className}
50
+ options={[
51
+ {
52
+ value: 'table',
53
+ icon: <TableOutlined />,
54
+ tooltip: '表格视图'
55
+ },
56
+ {
57
+ value: 'grid',
58
+ icon: <AppstoreOutlined />,
59
+ tooltip: '网格视图'
60
+ }
61
+ ]}
62
+ />
63
+ );
64
+ }