@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,330 @@
1
+
2
+ import React from 'react';
3
+ import { Timeline, Avatar, Button, Dropdown, DatePicker } from 'antd';
4
+ import { formatDatetime } from '../../utils/formatters';
5
+ import { Modal, Form, Input } from 'antd';
6
+ import { EllipsisOutlined, EditOutlined, DeleteOutlined, CommentOutlined } from '@ant-design/icons';
7
+ import { htmlNoData, useEffectResize } from '../../utils/htmlUtils';
8
+ import uiToast from '../UIToast';
9
+ import dayjs from 'dayjs';
10
+ import { CacheUserInfo, UserInfo } from '../../utils/CacheUserInfo';
11
+
12
+ export interface CommentItem {
13
+ id: string;
14
+ commentCount: number;
15
+ descs: string;
16
+ progressTime: Date; // 评论的title时间.
17
+ createTime: Date;
18
+ updateTime: Date;
19
+ createBy: string;
20
+ updateBy: string;
21
+ }
22
+
23
+ export interface CommentSubItem {
24
+ id: string;
25
+ parentId: string;
26
+ comment: string;
27
+ createTime: Date;
28
+ updateTime: Date;
29
+ createBy: string;
30
+ updateBy: string;
31
+ }
32
+
33
+ export interface CommentTimelineProps {
34
+ // 评论列表
35
+ commentList: CommentItem[];
36
+ // 评论以及子评论
37
+ commentListMap: Record<string, { comments: CommentSubItem[], expanded: boolean }>;
38
+
39
+ // 是否在左侧显示瀑布流title(仅桌面端显示)
40
+ showTitle?: boolean;
41
+ // 新增评论时,是否显示时间的选择.
42
+ showTimePicker?: boolean;
43
+
44
+ onDeleteComment?: (commentId: string) => void;
45
+ // 加载子评论
46
+ onLoadSubComments?: (commentId: string) => void;
47
+ // 保存评论
48
+ onSaveSubComment?: (params: { commentId: string, comment: string }) => Promise<boolean>;
49
+ onSaveComment?: (params: { commentItem: CommentItem | null, comment: string, time: Date }) => Promise<boolean>;
50
+ }
51
+
52
+ /**
53
+ * @desc 评论组件.
54
+ */
55
+ export const CommentTimeline: React.FC<CommentTimelineProps> = ({
56
+ commentList, showTitle, showTimePicker, onDeleteComment, onLoadSubComments, commentListMap, onSaveComment, onSaveSubComment
57
+ }) => {
58
+ const [isMobile, setIsMobile] = React.useState(window.innerWidth < 768);
59
+ const [userMap, setUserMap] = React.useState<Map<string, UserInfo>>(new Map());
60
+
61
+ const [commentModalVisible, setCommentModalVisible] = React.useState(false);
62
+ const [commentingProgress, setCommentingProgress] = React.useState<CommentItem | null>(null);
63
+ const [commentForm] = Form.useForm();
64
+
65
+ const [progressModalVisible, setProgressModalVisible] = React.useState(false);
66
+ const [editingProgress, setEditingProgress] = React.useState<CommentItem | null>(null);
67
+ const [progressForm] = Form.useForm();
68
+
69
+ const commentUserIds = React.useMemo(() => {
70
+ const userIds = new Set<string>();
71
+ commentList.forEach((item) => {
72
+ if (item.createBy) {
73
+ userIds.add(item.createBy);
74
+ }
75
+ commentListMap[item.id]?.comments.forEach((comment) => {
76
+ if (comment.createBy) {
77
+ userIds.add(comment.createBy);
78
+ }
79
+ });
80
+ });
81
+ return Array.from(userIds);
82
+ }, [commentList, commentListMap]);
83
+
84
+ React.useEffect(() => {
85
+ if (commentUserIds.length === 0) {
86
+ return;
87
+ }
88
+
89
+ let isMounted = true;
90
+ CacheUserInfo.getUserInfos({ userIds: commentUserIds }).then((users) => {
91
+ if (!isMounted) {
92
+ return;
93
+ }
94
+ setUserMap((prev) => new Map([...prev, ...users]));
95
+ }).catch((error) => {
96
+ console.error('加载评论用户信息失败:', error);
97
+ });
98
+
99
+ return () => {
100
+ isMounted = false;
101
+ };
102
+ }, [commentUserIds]);
103
+
104
+ // 添加响应式布局,小屏幕默认使用卡片视图
105
+ useEffectResize(() => {
106
+ setIsMobile(true);
107
+ }, () => {
108
+ setIsMobile(false);
109
+ }, 768);
110
+
111
+ const openSubCommentModal = async (comment: CommentItem) => {
112
+ setCommentingProgress(comment);
113
+ commentForm.resetFields();
114
+ setCommentModalVisible(true);
115
+ };
116
+
117
+ const openCommentModal = (comment?: CommentItem) => {
118
+ if (comment) {
119
+ setEditingProgress(comment);
120
+ progressForm.setFieldsValue({
121
+ descs: comment.descs,
122
+ progressTime2: dayjs(comment.progressTime),
123
+ });
124
+ } else {
125
+ setEditingProgress(null);
126
+ progressForm.resetFields();
127
+ progressForm.setFieldsValue({ progressTime2: dayjs() });
128
+ }
129
+ setProgressModalVisible(true);
130
+ };
131
+
132
+ const handleSaveComment = async () => {
133
+ try {
134
+ if (!commentingProgress) {
135
+ return;
136
+ }
137
+ const values = await commentForm.validateFields();
138
+ if (!values) {
139
+ return;
140
+ }
141
+ if (await onSaveSubComment?.({ commentId: commentingProgress.id, comment: values.comment })) {
142
+ uiToast.success('回复已提交');
143
+ setCommentModalVisible(false);
144
+ onLoadSubComments?.(commentingProgress.id);
145
+ }
146
+ } catch (error) {
147
+ console.error(error);
148
+ uiToast.error('提交回复失败');
149
+ }
150
+ };
151
+
152
+ const handleSaveProgress = async () => {
153
+ try {
154
+ const values = await progressForm.validateFields();
155
+ if (editingProgress) {
156
+ await onSaveComment?.({ commentItem: editingProgress, comment: values.descs, time: values.progressTime2.toDate() });
157
+ uiToast.success('更新成功');
158
+ } else {
159
+ await onSaveComment?.({ commentItem: null, comment: values.descs, time: values.progressTime2.toDate() });
160
+ uiToast.success('新增成功');
161
+ }
162
+ setProgressModalVisible(false);
163
+ setEditingProgress(null);
164
+
165
+ } catch (error) {
166
+ console.error(error);
167
+ uiToast.error('保存失败');
168
+ }
169
+ };
170
+
171
+ return (<>
172
+ <div className="flex justify-end items-center mb-5 ml-4">
173
+ <Button
174
+ type="primary"
175
+ onClick={() => openCommentModal()}
176
+ className="px-4 py-2 btn-primary flex items-center"
177
+ >新增</Button>
178
+ </div>
179
+ {
180
+ commentList.length ?
181
+ (<Timeline
182
+ mode="left"
183
+ className="ml-5 md:pr-[200px]"
184
+ items={commentList.map((item) => ({
185
+ key: item.id,
186
+ color: 'blue',
187
+ label: (isMobile && showTitle) ? null : formatDatetime(new Date(item.progressTime)),
188
+ style: { paddingBottom: '5px' },
189
+ children: (
190
+ <>
191
+ {(isMobile && showTitle) && <div className="mt-2 mb-1 font-bold">{formatDatetime(new Date(item.progressTime))}</div>}
192
+ <div className="rounded border border-gray-100 bg-gray-50 p-2">
193
+ <div className="flex justify-between items-start mb-2 ">
194
+ <div className="flex items-center space-x-2">
195
+ <Avatar
196
+ src={userMap.get(item.createBy)?.avatar?.avatar_small || null}
197
+ size={40}
198
+ >
199
+ {userMap.get(item.createBy)?.nickname?.[0]}
200
+ </Avatar>
201
+ <div>
202
+ <div className="">{userMap.get(item.createBy)?.nickname}</div>
203
+ <div className="text-xs font-thin">{formatDatetime(new Date(item.updateTime))}</div>
204
+ </div>
205
+ </div>
206
+ <div className="mt-4 flex justify-end absolute right-1 top-1">
207
+ <Dropdown
208
+ menu={{
209
+ items: [
210
+ {
211
+ key: 'edit',
212
+ icon: <EditOutlined />,
213
+ label: '编辑',
214
+ onClick: (e: any) => { openCommentModal?.(item); e.domEvent.stopPropagation(); },
215
+ },
216
+ {
217
+ key: 'delete',
218
+ icon: <DeleteOutlined />,
219
+ label: '删除',
220
+ danger: true,
221
+ onClick: (e: any) => { onDeleteComment?.(item.id); e.domEvent.stopPropagation(); },
222
+ },
223
+ ]
224
+ }}
225
+ trigger={['click']}
226
+ >
227
+ <Button type="text" icon={<EllipsisOutlined />} onClick={e=>e.stopPropagation()} />
228
+ </Dropdown>
229
+ </div>
230
+ </div>
231
+ <div className="whitespace-pre-wrap ml-2" style={{ whiteSpace: 'pre-wrap' }}>{item.descs}</div>
232
+ <div className="flex items-center space-x-1 mt-1">
233
+ <Button type="text" icon={<CommentOutlined />} className="font-thin text-xs" size="small" style={{ color: '#666' }} onClick={() => openSubCommentModal(item)}>
234
+ 回复
235
+ </Button>
236
+ <Button type="text" size="small" style={{ color: '#666' }} className="font-thin text-xs" onClick={() => onLoadSubComments?.(item.id)}>
237
+ {commentListMap[item.id] && commentListMap[item.id].expanded ? '收起' : '展开' + item.commentCount + '条'}回复
238
+ </Button>
239
+ </div>
240
+ </div>
241
+ <div className="border-l border-gray-200 pl-3">
242
+ {commentListMap[item.id] && commentListMap[item.id].expanded && commentListMap[item.id].comments.length > 0 ? (
243
+ commentListMap[item.id].comments.map((comment) => (
244
+ <div key={comment.id} className="p-1 text-sm">
245
+ <div className="flex items-center space-y-2 mb-1 mt-1">
246
+ <div className="flex items-center space-x-2">
247
+ <Avatar
248
+ src={userMap.get(comment.createBy)?.avatar?.avatar_small || null}
249
+ size={40}
250
+ className="self-start"
251
+ >
252
+ {userMap.get(comment.createBy)?.nickname?.[0]}
253
+ </Avatar>
254
+ <div>
255
+ <div className="text-gray-600 text-xs">{userMap.get(comment.createBy)?.nickname}</div>
256
+ {/* <div className="text-xs text-gray-400">{formatDatetime(new Date(comment.createTime))}</div> */}
257
+ <div className="text-gray-700">{comment.comment}</div>
258
+ <div className="text-xs mt-1 font-thin">{formatDatetime(new Date(comment.createTime))}</div>
259
+
260
+ </div>
261
+ </div>
262
+ </div>
263
+ </div>
264
+ ))
265
+ ) : (
266
+ <></>
267
+ )}
268
+ </div>
269
+ </>
270
+ ),
271
+ }))}
272
+ />) : (
273
+ htmlNoData())
274
+ }
275
+
276
+ <Modal
277
+ open={commentModalVisible}
278
+ onCancel={() => {
279
+ setCommentingProgress(null);
280
+ setCommentModalVisible(false);
281
+ }}
282
+ className="ant-modal-nofull"
283
+ onOk={handleSaveComment}
284
+ okText="提交"
285
+ cancelText="取消"
286
+ >
287
+ <Form form={commentForm} layout="horizontal" className="mt-6">
288
+ <Form.Item
289
+ name="comment"
290
+ rules={[{ required: true, message: '请输入回复内容' }]}
291
+ >
292
+ <Input.TextArea rows={4} placeholder="请输入你的回复" />
293
+ </Form.Item>
294
+ </Form>
295
+ </Modal>
296
+
297
+ {/* 编辑项目模态框 */}
298
+ <Modal
299
+ title={editingProgress ? '编辑' : '新增'}
300
+ open={progressModalVisible}
301
+ className="ant-modal-nofull"
302
+ onCancel={() => {
303
+ setProgressModalVisible(false);
304
+ setEditingProgress(null);
305
+ }}
306
+ onOk={handleSaveProgress}
307
+ okText="保存"
308
+ cancelText="取消"
309
+ >
310
+ <Form form={progressForm} layout="horizontal" >
311
+ {showTimePicker && (
312
+ <Form.Item
313
+ name="progressTime2"
314
+ label="时间"
315
+ rules={[{ required: true, message: '请选择时间' }]}
316
+ >
317
+ <DatePicker showTime style={{ width: '100%' }} />
318
+ </Form.Item>
319
+ )}
320
+ <Form.Item
321
+ name="descs"
322
+ label="内容"
323
+ rules={[{ required: true, message: '请输入内容' }]}
324
+ >
325
+ <Input.TextArea rows={4} placeholder="请输入内容" />
326
+ </Form.Item>
327
+ </Form>
328
+ </Modal>
329
+ </>);
330
+ };