collabdocchat 1.2.13 → 2.0.1

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 (63) 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/generate-docs.js +448 -0
  7. package/scripts/pre-publish-check.js +213 -0
  8. package/scripts/start-app.js +15 -15
  9. package/server/index.js +38 -6
  10. package/server/middleware/cache.js +115 -0
  11. package/server/middleware/errorHandler.js +209 -0
  12. package/server/models/Document.js +66 -59
  13. package/server/models/File.js +49 -43
  14. package/server/models/Group.js +6 -0
  15. package/server/models/KnowledgeBase.js +254 -0
  16. package/server/models/Message.js +43 -0
  17. package/server/models/Task.js +87 -55
  18. package/server/models/User.js +67 -60
  19. package/server/models/Workflow.js +249 -0
  20. package/server/routes/ai.js +327 -0
  21. package/server/routes/audit.js +245 -210
  22. package/server/routes/backup.js +108 -0
  23. package/server/routes/chunked-upload.js +343 -0
  24. package/server/routes/export.js +440 -0
  25. package/server/routes/files.js +294 -218
  26. package/server/routes/groups.js +182 -0
  27. package/server/routes/knowledge.js +509 -0
  28. package/server/routes/tasks.js +257 -110
  29. package/server/routes/workflows.js +380 -0
  30. package/server/utils/backup.js +439 -0
  31. package/server/utils/cache.js +223 -0
  32. package/server/utils/workflow-engine.js +479 -0
  33. package/server/websocket/enhanced.js +509 -0
  34. package/server/websocket/index.js +233 -1
  35. package/src/components/knowledge-modal.js +485 -0
  36. package/src/components/optimized-poll-detail.js +724 -0
  37. package/src/main.js +5 -0
  38. package/src/pages/admin-dashboard.js +2248 -44
  39. package/src/pages/optimized-backup-view.js +616 -0
  40. package/src/pages/optimized-knowledge-view.js +803 -0
  41. package/src/pages/optimized-task-detail.js +843 -0
  42. package/src/pages/optimized-workflow-view.js +806 -0
  43. package/src/pages/simplified-workflows.js +651 -0
  44. package/src/pages/user-dashboard.js +677 -58
  45. package/src/services/api.js +64 -0
  46. package/src/services/auth.js +1 -1
  47. package/src/services/websocket.js +124 -16
  48. package/src/styles/collaboration-modern.js +708 -0
  49. package/src/styles/enhancements.css +392 -0
  50. package/src/styles/main.css +620 -1420
  51. package/src/styles/responsive.css +1000 -0
  52. package/src/styles/sidebar-fix.css +60 -0
  53. package/src/utils/ai-assistant.js +1398 -0
  54. package/src/utils/chat-enhancements.js +509 -0
  55. package/src/utils/collaboration-enhancer.js +1151 -0
  56. package/src/utils/feature-integrator.js +1724 -0
  57. package/src/utils/onboarding-guide.js +734 -0
  58. package/src/utils/performance.js +394 -0
  59. package/src/utils/permission-manager.js +890 -0
  60. package/src/utils/responsive-handler.js +491 -0
  61. package/src/utils/theme-manager.js +811 -0
  62. package/src/utils/ui-enhancements-loader.js +329 -0
  63. package/USAGE.md +0 -298
@@ -0,0 +1,890 @@
1
+ /**
2
+ * 权限管理系统
3
+ * 提供细粒度的权限控制
4
+ */
5
+
6
+ export class PermissionManager {
7
+ constructor() {
8
+ this.permissions = {
9
+ // 文档权限
10
+ document: {
11
+ create: ['admin', 'user'],
12
+ read: ['admin', 'user', 'guest'],
13
+ update: ['admin', 'user'],
14
+ delete: ['admin'],
15
+ share: ['admin', 'user'],
16
+ export: ['admin', 'user']
17
+ },
18
+ // 群组权限
19
+ group: {
20
+ create: ['admin'],
21
+ read: ['admin', 'user'],
22
+ update: ['admin'],
23
+ delete: ['admin'],
24
+ invite: ['admin'],
25
+ remove: ['admin']
26
+ },
27
+ // 任务权限
28
+ task: {
29
+ create: ['admin', 'user'],
30
+ read: ['admin', 'user'],
31
+ update: ['admin', 'user'],
32
+ delete: ['admin'],
33
+ assign: ['admin']
34
+ },
35
+ // 文件权限
36
+ file: {
37
+ upload: ['admin', 'user'],
38
+ download: ['admin', 'user', 'guest'],
39
+ delete: ['admin', 'user']
40
+ },
41
+ // 聊天权限
42
+ chat: {
43
+ send: ['admin', 'user'],
44
+ recall: ['admin', 'user'],
45
+ delete: ['admin'],
46
+ mute: ['admin']
47
+ },
48
+ // 系统权限
49
+ system: {
50
+ viewLogs: ['admin'],
51
+ manageUsers: ['admin'],
52
+ settings: ['admin']
53
+ }
54
+ };
55
+
56
+ // 自定义权限
57
+ this.customPermissions = this.loadCustomPermissions();
58
+ }
59
+
60
+ /**
61
+ * 检查权限
62
+ */
63
+ hasPermission(userRole, resource, action) {
64
+ // 检查基础权限
65
+ if (this.permissions[resource] && this.permissions[resource][action]) {
66
+ if (this.permissions[resource][action].includes(userRole)) {
67
+ return true;
68
+ }
69
+ }
70
+
71
+ // 检查自定义权限
72
+ const customKey = `${resource}.${action}`;
73
+ if (this.customPermissions[customKey]) {
74
+ return this.customPermissions[customKey].includes(userRole);
75
+ }
76
+
77
+ return false;
78
+ }
79
+
80
+ /**
81
+ * 检查文档权限
82
+ */
83
+ canAccessDocument(user, document) {
84
+ // 管理员可以访问所有文档
85
+ if (user.role === 'admin') {
86
+ return true;
87
+ }
88
+
89
+ // 文档创建者可以访问
90
+ if (document.creator === user.id) {
91
+ return true;
92
+ }
93
+
94
+ // 检查文档权限设置
95
+ if (document.permission === 'public') {
96
+ return true;
97
+ }
98
+
99
+ if (document.permission === 'readonly') {
100
+ return this.hasPermission(user.role, 'document', 'read');
101
+ }
102
+
103
+ // 检查是否在允许的用户列表中
104
+ if (document.allowedUsers && document.allowedUsers.includes(user.id)) {
105
+ return true;
106
+ }
107
+
108
+ return false;
109
+ }
110
+
111
+ /**
112
+ * 检查文档编辑权限
113
+ */
114
+ canEditDocument(user, document) {
115
+ // 管理员可以编辑所有文档
116
+ if (user.role === 'admin') {
117
+ return true;
118
+ }
119
+
120
+ // 文档创建者可以编辑
121
+ if (document.creator === user.id) {
122
+ return true;
123
+ }
124
+
125
+ // 只读文档不能编辑
126
+ if (document.permission === 'readonly') {
127
+ return false;
128
+ }
129
+
130
+ // 检查是否在编辑者列表中
131
+ if (document.editors && document.editors.includes(user.id)) {
132
+ return true;
133
+ }
134
+
135
+ return false;
136
+ }
137
+
138
+ /**
139
+ * 检查群组权限
140
+ */
141
+ canAccessGroup(user, group) {
142
+ // 管理员可以访问所有群组
143
+ if (user.role === 'admin') {
144
+ return true;
145
+ }
146
+
147
+ // 检查是否是群组成员
148
+ if (group.members && group.members.includes(user.id)) {
149
+ return true;
150
+ }
151
+
152
+ // 检查是否是公开群组
153
+ if (group.visibility === 'public') {
154
+ return true;
155
+ }
156
+
157
+ return false;
158
+ }
159
+
160
+ /**
161
+ * 检查是否是群组管理员
162
+ */
163
+ isGroupAdmin(user, group) {
164
+ return user.role === 'admin' || group.admin === user.id;
165
+ }
166
+
167
+ /**
168
+ * 添加自定义权限
169
+ */
170
+ addCustomPermission(resource, action, roles) {
171
+ const key = `${resource}.${action}`;
172
+ this.customPermissions[key] = roles;
173
+ this.saveCustomPermissions();
174
+ }
175
+
176
+ /**
177
+ * 移除自定义权限
178
+ */
179
+ removeCustomPermission(resource, action) {
180
+ const key = `${resource}.${action}`;
181
+ delete this.customPermissions[key];
182
+ this.saveCustomPermissions();
183
+ }
184
+
185
+ /**
186
+ * 保存自定义权限
187
+ */
188
+ saveCustomPermissions() {
189
+ localStorage.setItem('customPermissions', JSON.stringify(this.customPermissions));
190
+ }
191
+
192
+ /**
193
+ * 加载自定义权限
194
+ */
195
+ loadCustomPermissions() {
196
+ const saved = localStorage.getItem('customPermissions');
197
+ return saved ? JSON.parse(saved) : {};
198
+ }
199
+
200
+ /**
201
+ * 获取用户权限列表
202
+ */
203
+ getUserPermissions(userRole) {
204
+ const permissions = [];
205
+
206
+ Object.entries(this.permissions).forEach(([resource, actions]) => {
207
+ Object.entries(actions).forEach(([action, roles]) => {
208
+ if (roles.includes(userRole)) {
209
+ permissions.push(`${resource}.${action}`);
210
+ }
211
+ });
212
+ });
213
+
214
+ // 添加自定义权限
215
+ Object.entries(this.customPermissions).forEach(([key, roles]) => {
216
+ if (roles.includes(userRole)) {
217
+ permissions.push(key);
218
+ }
219
+ });
220
+
221
+ return permissions;
222
+ }
223
+
224
+ /**
225
+ * 渲染权限管理界面(优化后)
226
+ */
227
+ renderPermissionManager(container, currentUser) {
228
+ if (currentUser.role !== 'admin') {
229
+ container.innerHTML = '<div class="error-state">只有管理员可以管理权限</div>';
230
+ return;
231
+ }
232
+
233
+ const roles = ['admin', 'user', 'guest'];
234
+
235
+ container.innerHTML = `
236
+ <div class="permission-manager-modern">
237
+ <div class="settings-header-modern">
238
+ <div class="settings-icon-large">🔒</div>
239
+ <h2>权限管理</h2>
240
+ <p>配置不同角色的系统访问权限</p>
241
+ </div>
242
+
243
+ <div class="permission-tabs-modern">
244
+ ${Object.keys(this.permissions).map((resource, index) => `
245
+ <button class="permission-tab-btn ${index === 0 ? 'active' : ''}"
246
+ data-resource="${resource}">
247
+ <span class="tab-icon">${this.getResourceIcon(resource)}</span>
248
+ <span class="tab-label">${this.getResourceName(resource)}</span>
249
+ </button>
250
+ `).join('')}
251
+ </div>
252
+
253
+ <div class="permission-content-modern">
254
+ ${Object.entries(this.permissions).map(([resource, actions], index) => `
255
+ <div class="permission-tab-panel ${index === 0 ? 'active' : ''}"
256
+ data-resource="${resource}">
257
+ <div class="permission-section-header">
258
+ <h3>${this.getResourceIcon(resource)} ${this.getResourceName(resource)}权限</h3>
259
+ <p class="section-description">${this.getResourceDescription(resource)}</p>
260
+ </div>
261
+
262
+ <div class="permission-cards-grid">
263
+ ${Object.entries(actions).map(([action, allowedRoles]) => `
264
+ <div class="permission-card">
265
+ <div class="permission-card-header">
266
+ <div class="action-icon">${this.getActionIcon(action)}</div>
267
+ <div class="action-info">
268
+ <h4>${this.getActionName(action)}</h4>
269
+ <p>${this.getActionDescription(action)}</p>
270
+ </div>
271
+ </div>
272
+ <div class="permission-card-body">
273
+ <div class="role-permissions">
274
+ ${roles.map(role => `
275
+ <div class="role-permission-item ${allowedRoles.includes(role) ? 'active' : ''}">
276
+ <label class="permission-checkbox-label">
277
+ <input type="checkbox"
278
+ class="permission-checkbox"
279
+ data-resource="${resource}"
280
+ data-action="${action}"
281
+ data-role="${role}"
282
+ ${allowedRoles.includes(role) ? 'checked' : ''}
283
+ ${role === 'admin' ? 'disabled' : ''}>
284
+ <span class="checkbox-custom"></span>
285
+ <span class="role-badge role-${role}">
286
+ ${this.getRoleIcon(role)} ${this.getRoleName(role)}
287
+ </span>
288
+ </label>
289
+ </div>
290
+ `).join('')}
291
+ </div>
292
+ </div>
293
+ </div>
294
+ `).join('')}
295
+ </div>
296
+ </div>
297
+ `).join('')}
298
+ </div>
299
+
300
+ <div class="permission-actions-modern">
301
+ <button class="btn-primary-large" id="savePermissions">
302
+ <span>💾</span> 保存权限设置
303
+ </button>
304
+ <button class="btn-secondary-large" id="resetPermissions">
305
+ <span>🔄</span> 重置为默认
306
+ </button>
307
+ </div>
308
+ </div>
309
+ `;
310
+
311
+ // 添加权限管理样式
312
+ this.addPermissionStyles();
313
+
314
+ // 标签切换
315
+ container.querySelectorAll('.permission-tab-btn').forEach(btn => {
316
+ btn.addEventListener('click', () => {
317
+ const resource = btn.dataset.resource;
318
+
319
+ container.querySelectorAll('.permission-tab-btn').forEach(b => b.classList.remove('active'));
320
+ container.querySelectorAll('.permission-tab-panel').forEach(c => c.classList.remove('active'));
321
+
322
+ btn.classList.add('active');
323
+ container.querySelector(`.permission-tab-panel[data-resource="${resource}"]`).classList.add('active');
324
+ });
325
+ });
326
+
327
+ // 复选框切换效果
328
+ container.querySelectorAll('.permission-checkbox').forEach(checkbox => {
329
+ checkbox.addEventListener('change', (e) => {
330
+ const item = e.target.closest('.role-permission-item');
331
+ if (e.target.checked) {
332
+ item.classList.add('active');
333
+ } else {
334
+ item.classList.remove('active');
335
+ }
336
+ });
337
+ });
338
+
339
+ // 保存权限
340
+ container.querySelector('#savePermissions').addEventListener('click', () => {
341
+ const checkboxes = container.querySelectorAll('input[type="checkbox"]:not([disabled])');
342
+
343
+ checkboxes.forEach(checkbox => {
344
+ const resource = checkbox.dataset.resource;
345
+ const action = checkbox.dataset.action;
346
+ const role = checkbox.dataset.role;
347
+
348
+ if (!this.permissions[resource][action]) {
349
+ this.permissions[resource][action] = [];
350
+ }
351
+
352
+ if (checkbox.checked) {
353
+ if (!this.permissions[resource][action].includes(role)) {
354
+ this.permissions[resource][action].push(role);
355
+ }
356
+ } else {
357
+ this.permissions[resource][action] = this.permissions[resource][action].filter(r => r !== role);
358
+ }
359
+ });
360
+
361
+ alert('权限设置已保存!');
362
+ });
363
+
364
+ // 重置权限
365
+ container.querySelector('#resetPermissions').addEventListener('click', () => {
366
+ if (confirm('确定要重置为默认权限设置吗?')) {
367
+ this.resetPermissions();
368
+ this.renderPermissionManager(container, currentUser);
369
+ alert('权限已重置为默认设置!');
370
+ }
371
+ });
372
+ }
373
+
374
+ /**
375
+ * 重置权限
376
+ */
377
+ resetPermissions() {
378
+ this.customPermissions = {};
379
+ this.saveCustomPermissions();
380
+ }
381
+
382
+ /**
383
+ * 获取资源名称
384
+ */
385
+ getResourceName(resource) {
386
+ const names = {
387
+ document: '文档',
388
+ group: '群组',
389
+ task: '任务',
390
+ file: '文件',
391
+ chat: '聊天',
392
+ system: '系统'
393
+ };
394
+ return names[resource] || resource;
395
+ }
396
+
397
+ /**
398
+ * 获取角色名称
399
+ */
400
+ getRoleName(role) {
401
+ const names = {
402
+ admin: '管理员',
403
+ user: '用户',
404
+ guest: '访客'
405
+ };
406
+ return names[role] || role;
407
+ }
408
+
409
+ /**
410
+ * 获取操作名称
411
+ */
412
+ getActionName(action) {
413
+ const names = {
414
+ create: '创建',
415
+ read: '查看',
416
+ update: '编辑',
417
+ delete: '删除',
418
+ share: '分享',
419
+ export: '导出',
420
+ invite: '邀请',
421
+ remove: '移除',
422
+ assign: '分配',
423
+ upload: '上传',
424
+ download: '下载',
425
+ send: '发送',
426
+ recall: '撤回',
427
+ mute: '禁言',
428
+ viewLogs: '查看日志',
429
+ manageUsers: '管理用户',
430
+ settings: '系统设置'
431
+ };
432
+ return names[action] || action;
433
+ }
434
+
435
+ /**
436
+ * 获取资源图标
437
+ */
438
+ getResourceIcon(resource) {
439
+ const icons = {
440
+ document: '📄',
441
+ group: '👥',
442
+ task: '📋',
443
+ file: '📎',
444
+ chat: '💬',
445
+ system: '⚙️'
446
+ };
447
+ return icons[resource] || '📦';
448
+ }
449
+
450
+ /**
451
+ * 获取资源描述
452
+ */
453
+ getResourceDescription(resource) {
454
+ const descriptions = {
455
+ document: '管理文档的创建、查看、编辑和删除权限',
456
+ group: '控制群组的创建、管理和成员邀请权限',
457
+ task: '设置任务的创建、分配和管理权限',
458
+ file: '配置文件的上传、下载和删除权限',
459
+ chat: '管理聊天消息的发送、撤回和禁言权限',
460
+ system: '控制系统级别的管理和配置权限'
461
+ };
462
+ return descriptions[resource] || '';
463
+ }
464
+
465
+ /**
466
+ * 获取操作图标
467
+ */
468
+ getActionIcon(action) {
469
+ const icons = {
470
+ create: '➕',
471
+ read: '👁️',
472
+ update: '✏️',
473
+ delete: '🗑️',
474
+ share: '🔗',
475
+ export: '📤',
476
+ invite: '📨',
477
+ remove: '❌',
478
+ assign: '👤',
479
+ upload: '⬆️',
480
+ download: '⬇️',
481
+ send: '📨',
482
+ recall: '↩️',
483
+ mute: '🔇',
484
+ viewLogs: '📊',
485
+ manageUsers: '👥',
486
+ settings: '⚙️'
487
+ };
488
+ return icons[action] || '🔹';
489
+ }
490
+
491
+ /**
492
+ * 获取操作描述
493
+ */
494
+ getActionDescription(action) {
495
+ const descriptions = {
496
+ create: '允许创建新内容',
497
+ read: '允许查看和访问',
498
+ update: '允许修改和更新',
499
+ delete: '允许删除内容',
500
+ share: '允许分享给他人',
501
+ export: '允许导出数据',
502
+ invite: '允许邀请新成员',
503
+ remove: '允许移除成员',
504
+ assign: '允许分配任务',
505
+ upload: '允许上传文件',
506
+ download: '允许下载文件',
507
+ send: '允许发送消息',
508
+ recall: '允许撤回消息',
509
+ mute: '允许禁言用户',
510
+ viewLogs: '允许查看系统日志',
511
+ manageUsers: '允许管理用户',
512
+ settings: '允许修改系统设置'
513
+ };
514
+ return descriptions[action] || '';
515
+ }
516
+
517
+ /**
518
+ * 获取角色图标
519
+ */
520
+ getRoleIcon(role) {
521
+ const icons = {
522
+ admin: '👑',
523
+ user: '👤',
524
+ guest: '👻'
525
+ };
526
+ return icons[role] || '👤';
527
+ }
528
+
529
+ /**
530
+ * 添加权限管理样式
531
+ */
532
+ addPermissionStyles() {
533
+ if (document.getElementById('permission-manager-styles')) return;
534
+
535
+ const style = document.createElement('style');
536
+ style.id = 'permission-manager-styles';
537
+ style.textContent = `
538
+ /* 权限管理现代化样式 */
539
+ .permission-manager-modern {
540
+ animation: fadeInUp 0.5s ease;
541
+ }
542
+
543
+ /* 权限标签页 */
544
+ .permission-tabs-modern {
545
+ display: flex;
546
+ gap: 12px;
547
+ margin-bottom: 30px;
548
+ flex-wrap: wrap;
549
+ justify-content: center;
550
+ }
551
+
552
+ .permission-tab-btn {
553
+ padding: 14px 24px;
554
+ background: var(--bg-card);
555
+ border: 2px solid var(--border);
556
+ border-radius: 12px;
557
+ color: var(--text-primary);
558
+ font-size: 15px;
559
+ font-weight: 600;
560
+ cursor: pointer;
561
+ transition: all 0.3s ease;
562
+ display: flex;
563
+ align-items: center;
564
+ gap: 10px;
565
+ }
566
+
567
+ .permission-tab-btn:hover {
568
+ border-color: var(--primary);
569
+ transform: translateY(-3px);
570
+ box-shadow: 0 8px 24px rgba(99,102,241,0.2);
571
+ }
572
+
573
+ .permission-tab-btn.active {
574
+ background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
575
+ color: white;
576
+ border-color: var(--primary);
577
+ box-shadow: 0 8px 24px rgba(99,102,241,0.3);
578
+ }
579
+
580
+ .tab-icon {
581
+ font-size: 20px;
582
+ }
583
+
584
+ .tab-label {
585
+ font-size: 15px;
586
+ }
587
+
588
+ /* 权限内容面板 */
589
+ .permission-content-modern {
590
+ position: relative;
591
+ min-height: 400px;
592
+ }
593
+
594
+ .permission-tab-panel {
595
+ display: none;
596
+ animation: fadeIn 0.3s ease;
597
+ }
598
+
599
+ .permission-tab-panel.active {
600
+ display: block;
601
+ }
602
+
603
+ /* 权限区域头部 */
604
+ .permission-section-header {
605
+ text-align: center;
606
+ padding: 30px 20px;
607
+ background: linear-gradient(135deg, var(--bg-card) 0%, rgba(99,102,241,0.05) 100%);
608
+ border-radius: 16px;
609
+ margin-bottom: 30px;
610
+ border: 2px solid var(--border);
611
+ }
612
+
613
+ .permission-section-header h3 {
614
+ margin: 0 0 10px;
615
+ font-size: 24px;
616
+ font-weight: 800;
617
+ color: var(--text-primary);
618
+ }
619
+
620
+ .section-description {
621
+ margin: 0;
622
+ font-size: 15px;
623
+ color: var(--text-secondary);
624
+ line-height: 1.6;
625
+ }
626
+
627
+ /* 权限卡片网格 */
628
+ .permission-cards-grid {
629
+ display: grid;
630
+ grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
631
+ gap: 20px;
632
+ margin-bottom: 30px;
633
+ }
634
+
635
+ /* 权限卡片 */
636
+ .permission-card {
637
+ background: var(--bg-card);
638
+ border: 2px solid var(--border);
639
+ border-radius: 16px;
640
+ padding: 20px;
641
+ transition: all 0.3s ease;
642
+ }
643
+
644
+ .permission-card:hover {
645
+ border-color: var(--primary);
646
+ box-shadow: 0 8px 24px rgba(99,102,241,0.15);
647
+ transform: translateY(-5px);
648
+ }
649
+
650
+ .permission-card-header {
651
+ display: flex;
652
+ gap: 16px;
653
+ margin-bottom: 20px;
654
+ padding-bottom: 16px;
655
+ border-bottom: 2px solid var(--border);
656
+ }
657
+
658
+ .action-icon {
659
+ width: 50px;
660
+ height: 50px;
661
+ border-radius: 12px;
662
+ background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
663
+ display: flex;
664
+ align-items: center;
665
+ justify-content: center;
666
+ font-size: 24px;
667
+ flex-shrink: 0;
668
+ }
669
+
670
+ .action-info {
671
+ flex: 1;
672
+ }
673
+
674
+ .action-info h4 {
675
+ margin: 0 0 6px;
676
+ font-size: 18px;
677
+ font-weight: 700;
678
+ color: var(--text-primary);
679
+ }
680
+
681
+ .action-info p {
682
+ margin: 0;
683
+ font-size: 13px;
684
+ color: var(--text-secondary);
685
+ line-height: 1.5;
686
+ }
687
+
688
+ /* 角色权限列表 */
689
+ .role-permissions {
690
+ display: flex;
691
+ flex-direction: column;
692
+ gap: 12px;
693
+ }
694
+
695
+ .role-permission-item {
696
+ background: var(--bg-dark);
697
+ border: 2px solid var(--border);
698
+ border-radius: 10px;
699
+ padding: 12px;
700
+ transition: all 0.3s ease;
701
+ }
702
+
703
+ .role-permission-item:hover {
704
+ border-color: var(--primary);
705
+ transform: translateX(5px);
706
+ }
707
+
708
+ .role-permission-item.active {
709
+ border-color: var(--success);
710
+ background: linear-gradient(90deg, rgba(16,185,129,0.1) 0%, transparent 100%);
711
+ }
712
+
713
+ /* 自定义复选框 */
714
+ .permission-checkbox-label {
715
+ display: flex;
716
+ align-items: center;
717
+ gap: 12px;
718
+ cursor: pointer;
719
+ width: 100%;
720
+ }
721
+
722
+ .permission-checkbox {
723
+ display: none;
724
+ }
725
+
726
+ .checkbox-custom {
727
+ width: 24px;
728
+ height: 24px;
729
+ border: 2px solid var(--border);
730
+ border-radius: 6px;
731
+ background: var(--bg-card);
732
+ position: relative;
733
+ transition: all 0.3s ease;
734
+ flex-shrink: 0;
735
+ }
736
+
737
+ .permission-checkbox:checked + .checkbox-custom {
738
+ background: linear-gradient(135deg, var(--success) 0%, #059669 100%);
739
+ border-color: var(--success);
740
+ }
741
+
742
+ .permission-checkbox:checked + .checkbox-custom::after {
743
+ content: '✓';
744
+ position: absolute;
745
+ top: 50%;
746
+ left: 50%;
747
+ transform: translate(-50%, -50%);
748
+ color: white;
749
+ font-size: 16px;
750
+ font-weight: 700;
751
+ }
752
+
753
+ .permission-checkbox:disabled + .checkbox-custom {
754
+ opacity: 0.5;
755
+ cursor: not-allowed;
756
+ }
757
+
758
+ /* 角色徽章 */
759
+ .role-badge {
760
+ padding: 8px 16px;
761
+ border-radius: 8px;
762
+ font-size: 14px;
763
+ font-weight: 600;
764
+ display: flex;
765
+ align-items: center;
766
+ gap: 8px;
767
+ flex: 1;
768
+ }
769
+
770
+ .role-admin {
771
+ background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
772
+ color: white;
773
+ }
774
+
775
+ .role-user {
776
+ background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
777
+ color: white;
778
+ }
779
+
780
+ .role-guest {
781
+ background: linear-gradient(135deg, #6b7280 0%, #4b5563 100%);
782
+ color: white;
783
+ }
784
+
785
+ /* 操作按钮区域 */
786
+ .permission-actions-modern {
787
+ display: flex;
788
+ gap: 16px;
789
+ justify-content: center;
790
+ margin-top: 40px;
791
+ flex-wrap: wrap;
792
+ }
793
+
794
+ .btn-primary-large,
795
+ .btn-secondary-large {
796
+ padding: 16px 32px;
797
+ border: none;
798
+ border-radius: 12px;
799
+ font-size: 16px;
800
+ font-weight: 700;
801
+ cursor: pointer;
802
+ transition: all 0.3s ease;
803
+ display: flex;
804
+ align-items: center;
805
+ gap: 10px;
806
+ }
807
+
808
+ .btn-primary-large {
809
+ background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
810
+ color: white;
811
+ box-shadow: 0 4px 12px rgba(99,102,241,0.3);
812
+ }
813
+
814
+ .btn-primary-large:hover {
815
+ transform: translateY(-3px);
816
+ box-shadow: 0 8px 24px rgba(99,102,241,0.5);
817
+ }
818
+
819
+ .btn-secondary-large {
820
+ background: var(--bg-card);
821
+ color: var(--text-primary);
822
+ border: 2px solid var(--border);
823
+ }
824
+
825
+ .btn-secondary-large:hover {
826
+ border-color: var(--primary);
827
+ transform: translateY(-3px);
828
+ box-shadow: 0 8px 24px rgba(99,102,241,0.2);
829
+ }
830
+
831
+ .btn-primary-large span,
832
+ .btn-secondary-large span {
833
+ font-size: 20px;
834
+ }
835
+
836
+ /* 响应式 */
837
+ @media (max-width: 768px) {
838
+ .permission-tabs-modern {
839
+ flex-direction: column;
840
+ }
841
+
842
+ .permission-tab-btn {
843
+ width: 100%;
844
+ justify-content: center;
845
+ }
846
+
847
+ .permission-cards-grid {
848
+ grid-template-columns: 1fr;
849
+ }
850
+
851
+ .permission-actions-modern {
852
+ flex-direction: column;
853
+ }
854
+
855
+ .btn-primary-large,
856
+ .btn-secondary-large {
857
+ width: 100%;
858
+ justify-content: center;
859
+ }
860
+ }
861
+
862
+ /* 动画 */
863
+ @keyframes fadeIn {
864
+ from {
865
+ opacity: 0;
866
+ }
867
+ to {
868
+ opacity: 1;
869
+ }
870
+ }
871
+
872
+ @keyframes fadeInUp {
873
+ from {
874
+ opacity: 0;
875
+ transform: translateY(20px);
876
+ }
877
+ to {
878
+ opacity: 1;
879
+ transform: translateY(0);
880
+ }
881
+ }
882
+ `;
883
+ document.head.appendChild(style);
884
+ }
885
+ }
886
+
887
+ // 导出单例
888
+ export const permissionManager = new PermissionManager();
889
+
890
+