collabdocchat 1.2.13 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +219 -218
  2. package/index.html +2 -0
  3. package/install-and-start.bat +5 -0
  4. package/install-and-start.sh +5 -0
  5. package/package.json +9 -2
  6. package/scripts/pre-publish-check.js +213 -0
  7. package/scripts/start-app.js +15 -15
  8. package/server/index.js +38 -6
  9. package/server/middleware/cache.js +115 -0
  10. package/server/middleware/errorHandler.js +209 -0
  11. package/server/models/Document.js +66 -59
  12. package/server/models/File.js +49 -43
  13. package/server/models/Group.js +6 -0
  14. package/server/models/KnowledgeBase.js +254 -0
  15. package/server/models/Message.js +43 -0
  16. package/server/models/Task.js +87 -55
  17. package/server/models/User.js +67 -60
  18. package/server/models/Workflow.js +249 -0
  19. package/server/routes/ai.js +327 -0
  20. package/server/routes/audit.js +245 -210
  21. package/server/routes/backup.js +108 -0
  22. package/server/routes/chunked-upload.js +343 -0
  23. package/server/routes/export.js +440 -0
  24. package/server/routes/files.js +294 -218
  25. package/server/routes/groups.js +182 -0
  26. package/server/routes/knowledge.js +509 -0
  27. package/server/routes/tasks.js +257 -110
  28. package/server/routes/workflows.js +380 -0
  29. package/server/utils/backup.js +439 -0
  30. package/server/utils/cache.js +223 -0
  31. package/server/utils/workflow-engine.js +479 -0
  32. package/server/websocket/enhanced.js +509 -0
  33. package/server/websocket/index.js +233 -1
  34. package/src/components/knowledge-modal.js +485 -0
  35. package/src/components/optimized-poll-detail.js +724 -0
  36. package/src/main.js +5 -0
  37. package/src/pages/admin-dashboard.js +2248 -44
  38. package/src/pages/optimized-backup-view.js +616 -0
  39. package/src/pages/optimized-knowledge-view.js +803 -0
  40. package/src/pages/optimized-task-detail.js +843 -0
  41. package/src/pages/optimized-workflow-view.js +806 -0
  42. package/src/pages/simplified-workflows.js +651 -0
  43. package/src/pages/user-dashboard.js +677 -58
  44. package/src/services/api.js +65 -1
  45. package/src/services/auth.js +1 -1
  46. package/src/services/websocket.js +124 -16
  47. package/src/styles/collaboration-modern.js +708 -0
  48. package/src/styles/enhancements.css +392 -0
  49. package/src/styles/main.css +620 -1420
  50. package/src/styles/responsive.css +1000 -0
  51. package/src/styles/sidebar-fix.css +60 -0
  52. package/src/utils/ai-assistant.js +1398 -0
  53. package/src/utils/chat-enhancements.js +509 -0
  54. package/src/utils/collaboration-enhancer.js +1151 -0
  55. package/src/utils/feature-integrator.js +1724 -0
  56. package/src/utils/onboarding-guide.js +734 -0
  57. package/src/utils/performance.js +394 -0
  58. package/src/utils/permission-manager.js +890 -0
  59. package/src/utils/responsive-handler.js +491 -0
  60. package/src/utils/theme-manager.js +811 -0
  61. package/src/utils/ui-enhancements-loader.js +329 -0
  62. package/USAGE.md +0 -298
@@ -0,0 +1,491 @@
1
+ /**
2
+ * 响应式处理器
3
+ * 处理不同设备的交互优化
4
+ */
5
+
6
+ export class ResponsiveHandler {
7
+ constructor() {
8
+ this.isMobile = false;
9
+ this.isTablet = false;
10
+ this.isDesktop = false;
11
+ this.orientation = 'portrait';
12
+
13
+ this.init();
14
+ }
15
+
16
+ /**
17
+ * 初始化
18
+ */
19
+ init() {
20
+ this.detectDevice();
21
+ this.setupEventListeners();
22
+ this.optimizeForDevice();
23
+ }
24
+
25
+ /**
26
+ * 检测设备类型
27
+ */
28
+ detectDevice() {
29
+ const width = window.innerWidth;
30
+
31
+ this.isMobile = width < 768;
32
+ this.isTablet = width >= 768 && width < 1024;
33
+ this.isDesktop = width >= 1024;
34
+ this.orientation = window.innerHeight > window.innerWidth ? 'portrait' : 'landscape';
35
+
36
+ // 添加设备类到body
37
+ document.body.classList.remove('mobile', 'tablet', 'desktop', 'portrait', 'landscape');
38
+
39
+ if (this.isMobile) {
40
+ document.body.classList.add('mobile');
41
+ } else if (this.isTablet) {
42
+ document.body.classList.add('tablet');
43
+ } else {
44
+ document.body.classList.add('desktop');
45
+ }
46
+
47
+ document.body.classList.add(this.orientation);
48
+
49
+ console.log('设备检测:', {
50
+ isMobile: this.isMobile,
51
+ isTablet: this.isTablet,
52
+ isDesktop: this.isDesktop,
53
+ orientation: this.orientation,
54
+ width: width
55
+ });
56
+ }
57
+
58
+ /**
59
+ * 设置事件监听
60
+ */
61
+ setupEventListeners() {
62
+ // 窗口大小改变
63
+ let resizeTimeout;
64
+ window.addEventListener('resize', () => {
65
+ clearTimeout(resizeTimeout);
66
+ resizeTimeout = setTimeout(() => {
67
+ this.detectDevice();
68
+ this.optimizeForDevice();
69
+ }, 250);
70
+ });
71
+
72
+ // 方向改变
73
+ window.addEventListener('orientationchange', () => {
74
+ setTimeout(() => {
75
+ this.detectDevice();
76
+ this.optimizeForDevice();
77
+ }, 100);
78
+ });
79
+
80
+ // 移动端菜单切换
81
+ if (this.isMobile) {
82
+ this.setupMobileMenu();
83
+ }
84
+ }
85
+
86
+ /**
87
+ * 根据设备优化
88
+ */
89
+ optimizeForDevice() {
90
+ if (this.isMobile) {
91
+ this.optimizeForMobile();
92
+ } else if (this.isTablet) {
93
+ this.optimizeForTablet();
94
+ } else {
95
+ this.optimizeForDesktop();
96
+ }
97
+ }
98
+
99
+ /**
100
+ * 移动端优化
101
+ */
102
+ optimizeForMobile() {
103
+ console.log('应用移动端优化');
104
+
105
+ // 优化触摸滚动
106
+ this.enableSmoothScrolling();
107
+
108
+ // 优化输入框
109
+ this.optimizeInputs();
110
+
111
+ // 优化模态框
112
+ this.optimizeModals();
113
+
114
+ // 添加返回顶部按钮
115
+ this.addBackToTopButton();
116
+
117
+ // 优化表格显示
118
+ this.optimizeTables();
119
+ }
120
+
121
+ /**
122
+ * 平板优化
123
+ */
124
+ optimizeForTablet() {
125
+ console.log('应用平板优化');
126
+
127
+ // 优化触摸滚动
128
+ this.enableSmoothScrolling();
129
+
130
+ // 优化模态框
131
+ this.optimizeModals();
132
+ }
133
+
134
+ /**
135
+ * 桌面优化
136
+ */
137
+ optimizeForDesktop() {
138
+ console.log('应用桌面优化');
139
+
140
+ // 移除移动端特定元素
141
+ const backToTop = document.getElementById('backToTopBtn');
142
+ if (backToTop) {
143
+ backToTop.remove();
144
+ }
145
+ }
146
+
147
+ /**
148
+ * 启用平滑滚动
149
+ */
150
+ enableSmoothScrolling() {
151
+ document.documentElement.style.scrollBehavior = 'smooth';
152
+
153
+ // 为所有可滚动元素添加平滑滚动
154
+ const scrollableElements = document.querySelectorAll('.main-content, .messages, .nav-menu');
155
+ scrollableElements.forEach(el => {
156
+ el.style.webkitOverflowScrolling = 'touch';
157
+ });
158
+ }
159
+
160
+ /**
161
+ * 优化输入框
162
+ */
163
+ optimizeInputs() {
164
+ // 防止输入框放大
165
+ const inputs = document.querySelectorAll('input, textarea, select');
166
+ inputs.forEach(input => {
167
+ if (!input.style.fontSize || parseInt(input.style.fontSize) < 16) {
168
+ input.style.fontSize = '16px';
169
+ }
170
+ });
171
+ }
172
+
173
+ /**
174
+ * 优化模态框
175
+ */
176
+ optimizeModals() {
177
+ // 监听模态框打开
178
+ const observer = new MutationObserver((mutations) => {
179
+ mutations.forEach((mutation) => {
180
+ mutation.addedNodes.forEach((node) => {
181
+ if (node.classList && node.classList.contains('modal')) {
182
+ this.handleModalOpen(node);
183
+ }
184
+ });
185
+ });
186
+ });
187
+
188
+ observer.observe(document.body, {
189
+ childList: true,
190
+ subtree: false
191
+ });
192
+ }
193
+
194
+ /**
195
+ * 处理模态框打开
196
+ */
197
+ handleModalOpen(modal) {
198
+ if (this.isMobile) {
199
+ // 禁止背景滚动
200
+ document.body.style.overflow = 'hidden';
201
+
202
+ // 模态框关闭时恢复滚动
203
+ const closeModal = () => {
204
+ document.body.style.overflow = '';
205
+ modal.removeEventListener('click', handleClick);
206
+ };
207
+
208
+ const handleClick = (e) => {
209
+ if (e.target === modal || e.target.classList.contains('modal-close') || e.target.classList.contains('close-btn')) {
210
+ closeModal();
211
+ }
212
+ };
213
+
214
+ modal.addEventListener('click', handleClick);
215
+ }
216
+ }
217
+
218
+ /**
219
+ * 添加返回顶部按钮
220
+ */
221
+ addBackToTopButton() {
222
+ // 检查是否已存在
223
+ if (document.getElementById('backToTopBtn')) return;
224
+
225
+ const button = document.createElement('button');
226
+ button.id = 'backToTopBtn';
227
+ button.innerHTML = '↑';
228
+ button.style.cssText = `
229
+ position: fixed;
230
+ bottom: 20px;
231
+ right: 20px;
232
+ width: 50px;
233
+ height: 50px;
234
+ border-radius: 50%;
235
+ background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
236
+ color: white;
237
+ border: none;
238
+ font-size: 24px;
239
+ font-weight: bold;
240
+ cursor: pointer;
241
+ box-shadow: 0 4px 12px rgba(99,102,241,0.4);
242
+ z-index: 1000;
243
+ opacity: 0;
244
+ visibility: hidden;
245
+ transition: all 0.3s ease;
246
+ `;
247
+
248
+ document.body.appendChild(button);
249
+
250
+ // 滚动显示/隐藏
251
+ const mainContent = document.querySelector('.main-content');
252
+ if (mainContent) {
253
+ mainContent.addEventListener('scroll', () => {
254
+ if (mainContent.scrollTop > 300) {
255
+ button.style.opacity = '1';
256
+ button.style.visibility = 'visible';
257
+ } else {
258
+ button.style.opacity = '0';
259
+ button.style.visibility = 'hidden';
260
+ }
261
+ });
262
+ }
263
+
264
+ // 点击返回顶部
265
+ button.addEventListener('click', () => {
266
+ if (mainContent) {
267
+ mainContent.scrollTo({
268
+ top: 0,
269
+ behavior: 'smooth'
270
+ });
271
+ } else {
272
+ window.scrollTo({
273
+ top: 0,
274
+ behavior: 'smooth'
275
+ });
276
+ }
277
+ });
278
+ }
279
+
280
+ /**
281
+ * 优化表格显示
282
+ */
283
+ optimizeTables() {
284
+ // 为表格添加横向滚动容器
285
+ const tables = document.querySelectorAll('.audit-table, .members-table, .backups-table');
286
+ tables.forEach(table => {
287
+ if (!table.parentElement.classList.contains('table-scroll-wrapper')) {
288
+ const wrapper = document.createElement('div');
289
+ wrapper.className = 'table-scroll-wrapper';
290
+ wrapper.style.cssText = `
291
+ overflow-x: auto;
292
+ -webkit-overflow-scrolling: touch;
293
+ margin: 0 -16px;
294
+ padding: 0 16px;
295
+ `;
296
+ table.parentNode.insertBefore(wrapper, table);
297
+ wrapper.appendChild(table);
298
+ }
299
+ });
300
+ }
301
+
302
+ /**
303
+ * 设置移动端菜单
304
+ */
305
+ setupMobileMenu() {
306
+ // 添加菜单切换按钮(如果需要)
307
+ const sidebar = document.querySelector('.sidebar');
308
+ if (!sidebar) return;
309
+
310
+ // 可以添加汉堡菜单按钮等
311
+ // 这里保持简单,使用横向滚动菜单
312
+ }
313
+
314
+ /**
315
+ * 获取设备信息
316
+ */
317
+ getDeviceInfo() {
318
+ return {
319
+ isMobile: this.isMobile,
320
+ isTablet: this.isTablet,
321
+ isDesktop: this.isDesktop,
322
+ orientation: this.orientation,
323
+ width: window.innerWidth,
324
+ height: window.innerHeight,
325
+ userAgent: navigator.userAgent,
326
+ platform: navigator.platform,
327
+ touchSupport: 'ontouchstart' in window
328
+ };
329
+ }
330
+
331
+ /**
332
+ * 检测是否为触摸设备
333
+ */
334
+ isTouchDevice() {
335
+ return 'ontouchstart' in window || navigator.maxTouchPoints > 0;
336
+ }
337
+
338
+ /**
339
+ * 获取视口尺寸
340
+ */
341
+ getViewportSize() {
342
+ return {
343
+ width: window.innerWidth,
344
+ height: window.innerHeight
345
+ };
346
+ }
347
+
348
+ /**
349
+ * 检测网络状态
350
+ */
351
+ getNetworkStatus() {
352
+ if ('connection' in navigator) {
353
+ const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
354
+ return {
355
+ effectiveType: connection.effectiveType,
356
+ downlink: connection.downlink,
357
+ rtt: connection.rtt,
358
+ saveData: connection.saveData
359
+ };
360
+ }
361
+ return null;
362
+ }
363
+
364
+ /**
365
+ * 优化图片加载
366
+ */
367
+ optimizeImages() {
368
+ const images = document.querySelectorAll('img[data-src]');
369
+
370
+ if ('IntersectionObserver' in window) {
371
+ const imageObserver = new IntersectionObserver((entries, observer) => {
372
+ entries.forEach(entry => {
373
+ if (entry.isIntersecting) {
374
+ const img = entry.target;
375
+ img.src = img.dataset.src;
376
+ img.removeAttribute('data-src');
377
+ imageObserver.unobserve(img);
378
+ }
379
+ });
380
+ });
381
+
382
+ images.forEach(img => imageObserver.observe(img));
383
+ } else {
384
+ // 降级方案:直接加载所有图片
385
+ images.forEach(img => {
386
+ img.src = img.dataset.src;
387
+ img.removeAttribute('data-src');
388
+ });
389
+ }
390
+ }
391
+
392
+ /**
393
+ * 添加触摸手势支持
394
+ */
395
+ addSwipeGesture(element, onSwipeLeft, onSwipeRight) {
396
+ let touchStartX = 0;
397
+ let touchEndX = 0;
398
+
399
+ element.addEventListener('touchstart', (e) => {
400
+ touchStartX = e.changedTouches[0].screenX;
401
+ }, { passive: true });
402
+
403
+ element.addEventListener('touchend', (e) => {
404
+ touchEndX = e.changedTouches[0].screenX;
405
+ this.handleSwipe(touchStartX, touchEndX, onSwipeLeft, onSwipeRight);
406
+ }, { passive: true });
407
+ }
408
+
409
+ /**
410
+ * 处理滑动手势
411
+ */
412
+ handleSwipe(startX, endX, onSwipeLeft, onSwipeRight) {
413
+ const threshold = 50; // 最小滑动距离
414
+ const diff = startX - endX;
415
+
416
+ if (Math.abs(diff) > threshold) {
417
+ if (diff > 0 && onSwipeLeft) {
418
+ onSwipeLeft();
419
+ } else if (diff < 0 && onSwipeRight) {
420
+ onSwipeRight();
421
+ }
422
+ }
423
+ }
424
+
425
+ /**
426
+ * 防止双击缩放
427
+ */
428
+ preventDoubleTapZoom() {
429
+ let lastTouchEnd = 0;
430
+ document.addEventListener('touchend', (e) => {
431
+ const now = Date.now();
432
+ if (now - lastTouchEnd <= 300) {
433
+ e.preventDefault();
434
+ }
435
+ lastTouchEnd = now;
436
+ }, { passive: false });
437
+ }
438
+
439
+ /**
440
+ * 显示设备信息(调试用)
441
+ */
442
+ showDeviceInfo() {
443
+ const info = this.getDeviceInfo();
444
+ console.table(info);
445
+
446
+ // 可选:在页面上显示
447
+ const infoDiv = document.createElement('div');
448
+ infoDiv.style.cssText = `
449
+ position: fixed;
450
+ bottom: 80px;
451
+ right: 20px;
452
+ background: rgba(0,0,0,0.8);
453
+ color: white;
454
+ padding: 10px;
455
+ border-radius: 8px;
456
+ font-size: 12px;
457
+ z-index: 9999;
458
+ max-width: 200px;
459
+ `;
460
+ infoDiv.innerHTML = `
461
+ <strong>设备信息</strong><br>
462
+ 类型: ${this.isMobile ? '手机' : this.isTablet ? '平板' : '桌面'}<br>
463
+ 方向: ${this.orientation}<br>
464
+ 尺寸: ${info.width}x${info.height}<br>
465
+ 触摸: ${info.touchSupport ? '是' : '否'}
466
+ `;
467
+
468
+ document.body.appendChild(infoDiv);
469
+
470
+ // 5秒后自动移除
471
+ setTimeout(() => infoDiv.remove(), 5000);
472
+ }
473
+ }
474
+
475
+ // 自动初始化
476
+ let responsiveHandler;
477
+
478
+ if (typeof window !== 'undefined') {
479
+ if (document.readyState === 'loading') {
480
+ document.addEventListener('DOMContentLoaded', () => {
481
+ responsiveHandler = new ResponsiveHandler();
482
+ window.responsiveHandler = responsiveHandler;
483
+ });
484
+ } else {
485
+ responsiveHandler = new ResponsiveHandler();
486
+ window.responsiveHandler = responsiveHandler;
487
+ }
488
+ }
489
+
490
+ export default ResponsiveHandler;
491
+