collabdocchat 2.1.1 → 2.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.
package/package.json
CHANGED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
|
|
8
|
+
const filePath = path.join(__dirname, '../src/pages/user-dashboard.js');
|
|
9
|
+
|
|
10
|
+
console.log('正在读取文件...');
|
|
11
|
+
let content = fs.readFileSync(filePath, 'utf8');
|
|
12
|
+
|
|
13
|
+
console.log('移除 Quill 导入...');
|
|
14
|
+
content = content.replace(/import Quill from 'quill';\r?\n/g, '');
|
|
15
|
+
content = content.replace(/import 'quill\/dist\/quill\.snow\.css';\r?\n/g, '');
|
|
16
|
+
|
|
17
|
+
console.log('替换 Quill 编辑器为 textarea...');
|
|
18
|
+
// 替换 Quill 初始化代码
|
|
19
|
+
content = content.replace(
|
|
20
|
+
/\/\/ 初始化 Quill 编辑器[\s\S]*?const quill = new Quill\('#editor', \{[\s\S]*?\}\);/g,
|
|
21
|
+
'// 使用原生 textarea\n const editor = document.getElementById(\'editor\');'
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// 替换 quill.root.innerHTML 为 editor.value
|
|
25
|
+
content = content.replace(/quill\.root\.innerHTML/g, 'editor.value');
|
|
26
|
+
|
|
27
|
+
// 替换 quill.on('text-change' 为 editor.addEventListener('input'
|
|
28
|
+
content = content.replace(/quill\.on\('text-change',/g, 'editor.addEventListener(\'input\',');
|
|
29
|
+
|
|
30
|
+
// 替换 quill.getSelection() 和 quill.setSelection()
|
|
31
|
+
content = content.replace(
|
|
32
|
+
/const selection = quill\.getSelection\(\);\s*quill\.root\.innerHTML = data\.content;\s*if \(selection\) \{\s*quill\.setSelection\(selection\);\s*\}/g,
|
|
33
|
+
'const cursorPos = editor.selectionStart;\n editor.value = data.content;\n editor.setSelectionRange(cursorPos, cursorPos);'
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
// 替换编辑器 HTML 结构
|
|
37
|
+
content = content.replace(
|
|
38
|
+
/<div id="editor"><\/div>/g,
|
|
39
|
+
'<textarea id="editor" style="width: 100%; min-height: 400px; padding: 10px; font-family: monospace;"></textarea>'
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
console.log('写入文件...');
|
|
43
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
44
|
+
|
|
45
|
+
console.log('✅ 完成!已移除 Quill 依赖并替换为原生 textarea');
|
|
46
|
+
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { ApiService } from '../services/api.js';
|
|
1
|
+
import { ApiService } from '../services/api.js';
|
|
2
2
|
import { AuthService } from '../services/auth.js';
|
|
3
|
-
import Quill from 'quill';
|
|
4
|
-
import 'quill/dist/quill.snow.css';
|
|
5
3
|
import 'emoji-picker-element';
|
|
6
4
|
|
|
7
5
|
export function renderUserDashboard(user, wsService) {
|
|
@@ -18,42 +16,42 @@ export function renderUserDashboard(user, wsService) {
|
|
|
18
16
|
<aside class="sidebar">
|
|
19
17
|
<div class="sidebar-header">
|
|
20
18
|
<h2>CollabDocChat</h2>
|
|
21
|
-
<span class="badge-user"
|
|
19
|
+
<span class="badge-user">鐢ㄦ埛</span>
|
|
22
20
|
</div>
|
|
23
21
|
|
|
24
22
|
<div class="user-info">
|
|
25
23
|
<div class="avatar">${user.username[0].toUpperCase()}</div>
|
|
26
24
|
<div>
|
|
27
25
|
<div class="username">${user.username}</div>
|
|
28
|
-
<div class="user-role"
|
|
26
|
+
<div class="user-role">鏅€氱敤鎴?/div>
|
|
29
27
|
</div>
|
|
30
28
|
</div>
|
|
31
29
|
|
|
32
30
|
<nav class="nav-menu">
|
|
33
31
|
<button class="nav-item active" data-view="groups">
|
|
34
|
-
<span class="icon"
|
|
32
|
+
<span class="icon">馃懃</span> 鎴戠殑缇ょ粍
|
|
35
33
|
</button>
|
|
36
34
|
<button class="nav-item" data-view="allgroups">
|
|
37
|
-
<span class="icon"
|
|
35
|
+
<span class="icon">馃寪</span> 鎵€鏈夌兢缁?
|
|
38
36
|
</button>
|
|
39
37
|
<button class="nav-item" data-view="tasks">
|
|
40
|
-
<span class="icon"
|
|
38
|
+
<span class="icon">馃搵</span> 鎴戠殑浠诲姟
|
|
41
39
|
</button>
|
|
42
40
|
<button class="nav-item" data-view="documents">
|
|
43
|
-
<span class="icon"
|
|
41
|
+
<span class="icon">馃搫</span> 鍏变韩鏂囨。
|
|
44
42
|
</button>
|
|
45
43
|
<button class="nav-item" data-view="files">
|
|
46
|
-
<span class="icon"
|
|
44
|
+
<span class="icon">馃搸</span> 鏂囦欢鍏变韩
|
|
47
45
|
</button>
|
|
48
46
|
<button class="nav-item" data-view="chat">
|
|
49
|
-
<span class="icon"
|
|
47
|
+
<span class="icon">馃挰</span> 缇よ亰
|
|
50
48
|
</button>
|
|
51
49
|
<button class="nav-item" data-view="search">
|
|
52
|
-
<span class="icon"
|
|
50
|
+
<span class="icon">馃攳</span> 鎼滅储
|
|
53
51
|
</button>
|
|
54
52
|
</nav>
|
|
55
53
|
|
|
56
|
-
<button class="btn-logout" id="logoutBtn"
|
|
54
|
+
<button class="btn-logout" id="logoutBtn">閫€鍑虹櫥褰?/button>
|
|
57
55
|
</aside>
|
|
58
56
|
|
|
59
57
|
<main class="main-content">
|
|
@@ -62,7 +60,7 @@ export function renderUserDashboard(user, wsService) {
|
|
|
62
60
|
</div>
|
|
63
61
|
`;
|
|
64
62
|
|
|
65
|
-
//
|
|
63
|
+
// 瀵艰埅鍒囨崲
|
|
66
64
|
document.querySelectorAll('.nav-item').forEach(item => {
|
|
67
65
|
item.addEventListener('click', () => {
|
|
68
66
|
document.querySelectorAll('.nav-item').forEach(i => i.classList.remove('active'));
|
|
@@ -72,7 +70,7 @@ export function renderUserDashboard(user, wsService) {
|
|
|
72
70
|
});
|
|
73
71
|
});
|
|
74
72
|
|
|
75
|
-
//
|
|
73
|
+
// 閫€鍑虹櫥褰?
|
|
76
74
|
document.getElementById('logoutBtn').addEventListener('click', () => {
|
|
77
75
|
authService.logout();
|
|
78
76
|
});
|
|
@@ -111,14 +109,14 @@ export function renderUserDashboard(user, wsService) {
|
|
|
111
109
|
|
|
112
110
|
container.innerHTML = `
|
|
113
111
|
<div class="view-header">
|
|
114
|
-
<h2
|
|
112
|
+
<h2>鎴戠殑缇ょ粍</h2>
|
|
115
113
|
</div>
|
|
116
114
|
<div class="groups-grid" id="groupsList"></div>
|
|
117
115
|
`;
|
|
118
116
|
|
|
119
117
|
const groupsList = document.getElementById('groupsList');
|
|
120
118
|
if (groups.length === 0) {
|
|
121
|
-
groupsList.innerHTML = '<div class="empty-state"
|
|
119
|
+
groupsList.innerHTML = '<div class="empty-state">鎮ㄨ繕娌℃湁鍔犲叆浠讳綍缇ょ粍<br>璇峰墠寰€"鎵€鏈夌兢缁?鏌ョ湅骞跺姞鍏?/div>';
|
|
122
120
|
return;
|
|
123
121
|
}
|
|
124
122
|
|
|
@@ -127,15 +125,15 @@ export function renderUserDashboard(user, wsService) {
|
|
|
127
125
|
groupCard.className = 'group-card';
|
|
128
126
|
groupCard.innerHTML = `
|
|
129
127
|
<h3>${group.name}</h3>
|
|
130
|
-
<p>${group.description || '
|
|
128
|
+
<p>${group.description || '鏆傛棤鎻忚堪'}</p>
|
|
131
129
|
<div class="group-stats">
|
|
132
|
-
<span
|
|
133
|
-
<span
|
|
134
|
-
<span
|
|
130
|
+
<span>馃懃 ${group.members.length} 鎴愬憳</span>
|
|
131
|
+
<span>馃搫 ${group.documents.length} 鏂囨。</span>
|
|
132
|
+
<span>馃搵 ${group.tasks.length} 浠诲姟</span>
|
|
135
133
|
</div>
|
|
136
134
|
<div style="display: flex; gap: 10px; margin-top: 10px;">
|
|
137
|
-
<button class="btn-select" data-id="${group._id}"
|
|
138
|
-
<button class="btn-secondary" data-id="${group._id}" data-action="leave"
|
|
135
|
+
<button class="btn-select" data-id="${group._id}">杩涘叆缇ょ粍</button>
|
|
136
|
+
<button class="btn-secondary" data-id="${group._id}" data-action="leave">閫€鍑虹兢缁?/button>
|
|
139
137
|
</div>
|
|
140
138
|
`;
|
|
141
139
|
groupsList.appendChild(groupCard);
|
|
@@ -145,19 +143,19 @@ export function renderUserDashboard(user, wsService) {
|
|
|
145
143
|
btn.addEventListener('click', () => {
|
|
146
144
|
currentGroup = groups.find(g => g._id === btn.dataset.id);
|
|
147
145
|
wsService.joinGroup(currentGroup._id);
|
|
148
|
-
alert(
|
|
146
|
+
alert(`宸茶繘鍏ョ兢缁? ${currentGroup.name}`);
|
|
149
147
|
});
|
|
150
148
|
});
|
|
151
149
|
|
|
152
150
|
document.querySelectorAll('[data-action="leave"]').forEach(btn => {
|
|
153
151
|
btn.addEventListener('click', async () => {
|
|
154
|
-
if (confirm('
|
|
152
|
+
if (confirm('纭畾瑕侀€€鍑鸿缇ょ粍鍚楋紵')) {
|
|
155
153
|
try {
|
|
156
154
|
await apiService.leaveGroup(btn.dataset.id);
|
|
157
|
-
alert('
|
|
155
|
+
alert('宸查€€鍑虹兢缁?);
|
|
158
156
|
await renderGroupsView(container);
|
|
159
157
|
} catch (error) {
|
|
160
|
-
alert('
|
|
158
|
+
alert('閫€鍑哄け璐? ' + error.message);
|
|
161
159
|
}
|
|
162
160
|
}
|
|
163
161
|
});
|
|
@@ -171,7 +169,7 @@ export function renderUserDashboard(user, wsService) {
|
|
|
171
169
|
|
|
172
170
|
container.innerHTML = `
|
|
173
171
|
<div class="view-header">
|
|
174
|
-
<h2
|
|
172
|
+
<h2>鎵€鏈夌兢缁?/h2>
|
|
175
173
|
</div>
|
|
176
174
|
<div class="groups-grid" id="allGroupsList"></div>
|
|
177
175
|
`;
|
|
@@ -183,14 +181,14 @@ export function renderUserDashboard(user, wsService) {
|
|
|
183
181
|
groupCard.className = 'group-card';
|
|
184
182
|
groupCard.innerHTML = `
|
|
185
183
|
<h3>${group.name}</h3>
|
|
186
|
-
<p>${group.description || '
|
|
184
|
+
<p>${group.description || '鏆傛棤鎻忚堪'}</p>
|
|
187
185
|
<div class="group-stats">
|
|
188
|
-
<span
|
|
189
|
-
<span
|
|
186
|
+
<span>馃懃 ${group.members.length} 鎴愬憳</span>
|
|
187
|
+
<span>馃搫 ${group.documents.length} 鏂囨。</span>
|
|
190
188
|
</div>
|
|
191
189
|
${isJoined ?
|
|
192
|
-
'<div style="color: var(--success); margin-top: 10px;"
|
|
193
|
-
`<button class="btn-primary" data-id="${group._id}" data-action="join"
|
|
190
|
+
'<div style="color: var(--success); margin-top: 10px;">鉁?宸插姞鍏?/div>' :
|
|
191
|
+
`<button class="btn-primary" data-id="${group._id}" data-action="join">鍔犲叆缇ょ粍</button>`
|
|
194
192
|
}
|
|
195
193
|
`;
|
|
196
194
|
allGroupsList.appendChild(groupCard);
|
|
@@ -200,10 +198,10 @@ export function renderUserDashboard(user, wsService) {
|
|
|
200
198
|
btn.addEventListener('click', async () => {
|
|
201
199
|
try {
|
|
202
200
|
await apiService.joinGroup(btn.dataset.id);
|
|
203
|
-
alert('
|
|
201
|
+
alert('鍔犲叆鎴愬姛锛?);
|
|
204
202
|
await renderAllGroupsView(container);
|
|
205
203
|
} catch (error) {
|
|
206
|
-
alert('
|
|
204
|
+
alert('鍔犲叆澶辫触: ' + error.message);
|
|
207
205
|
}
|
|
208
206
|
});
|
|
209
207
|
});
|
|
@@ -215,7 +213,7 @@ export function renderUserDashboard(user, wsService) {
|
|
|
215
213
|
|
|
216
214
|
container.innerHTML = `
|
|
217
215
|
<div class="view-header">
|
|
218
|
-
<h2
|
|
216
|
+
<h2>鎴戠殑浠诲姟</h2>
|
|
219
217
|
</div>
|
|
220
218
|
<div class="tasks-list" id="tasksList"></div>
|
|
221
219
|
`;
|
|
@@ -223,7 +221,7 @@ export function renderUserDashboard(user, wsService) {
|
|
|
223
221
|
const tasksList = document.getElementById('tasksList');
|
|
224
222
|
|
|
225
223
|
if (result.tasks.length === 0) {
|
|
226
|
-
tasksList.innerHTML = '<div class="empty-state"
|
|
224
|
+
tasksList.innerHTML = '<div class="empty-state">鏆傛棤浠诲姟</div>';
|
|
227
225
|
return;
|
|
228
226
|
}
|
|
229
227
|
|
|
@@ -235,19 +233,19 @@ export function renderUserDashboard(user, wsService) {
|
|
|
235
233
|
<p>${task.description}</p>
|
|
236
234
|
<div class="task-meta">
|
|
237
235
|
<span class="status-badge">${getStatusText(task.status)}</span>
|
|
238
|
-
<span
|
|
239
|
-
${task.deadline ? `<span
|
|
236
|
+
<span>缇ょ粍: ${task.group.name}</span>
|
|
237
|
+
${task.deadline ? `<span>鎴: ${new Date(task.deadline).toLocaleDateString()}</span>` : ''}
|
|
240
238
|
</div>
|
|
241
|
-
${task.relatedDocument ? `<a href="#" class="doc-link" data-id="${task.relatedDocument._id}"
|
|
239
|
+
${task.relatedDocument ? `<a href="#" class="doc-link" data-id="${task.relatedDocument._id}">馃搫 鏌ョ湅鐩稿叧鏂囨。</a>` : ''}
|
|
242
240
|
<div class="task-actions">
|
|
243
|
-
${task.status === 'pending' ? `<button class="btn-primary btn-sm" data-id="${task._id}" data-action="start"
|
|
244
|
-
${task.status === 'in_progress' ? `<button class="btn-success btn-sm" data-id="${task._id}" data-action="complete"
|
|
241
|
+
${task.status === 'pending' ? `<button class="btn-primary btn-sm" data-id="${task._id}" data-action="start">寮€濮嬩换鍔?/button>` : ''}
|
|
242
|
+
${task.status === 'in_progress' ? `<button class="btn-success btn-sm" data-id="${task._id}" data-action="complete">瀹屾垚浠诲姟</button>` : ''}
|
|
245
243
|
</div>
|
|
246
244
|
`;
|
|
247
245
|
tasksList.appendChild(taskCard);
|
|
248
246
|
});
|
|
249
247
|
|
|
250
|
-
//
|
|
248
|
+
// 浠诲姟鎿嶄綔
|
|
251
249
|
document.querySelectorAll('[data-action]').forEach(btn => {
|
|
252
250
|
btn.addEventListener('click', async () => {
|
|
253
251
|
const taskId = btn.dataset.id;
|
|
@@ -258,24 +256,24 @@ export function renderUserDashboard(user, wsService) {
|
|
|
258
256
|
await apiService.updateTaskStatus(taskId, status);
|
|
259
257
|
await renderTasksView(container);
|
|
260
258
|
} catch (error) {
|
|
261
|
-
alert('
|
|
259
|
+
alert('鎿嶄綔澶辫触: ' + error.message);
|
|
262
260
|
}
|
|
263
261
|
});
|
|
264
262
|
});
|
|
265
263
|
} catch (error) {
|
|
266
|
-
console.error('
|
|
264
|
+
console.error('鑾峰彇浠诲姟澶辫触:', error);
|
|
267
265
|
container.innerHTML = `
|
|
268
266
|
<div class="view-header">
|
|
269
|
-
<h2
|
|
267
|
+
<h2>鎴戠殑浠诲姟</h2>
|
|
270
268
|
</div>
|
|
271
|
-
<div class="empty-state"
|
|
269
|
+
<div class="empty-state">鍔犺浇浠诲姟澶辫触: ${error.message}</div>
|
|
272
270
|
`;
|
|
273
271
|
}
|
|
274
272
|
}
|
|
275
273
|
|
|
276
274
|
async function renderDocumentsView(container) {
|
|
277
275
|
if (!currentGroup) {
|
|
278
|
-
container.innerHTML = '<div class="empty-state"
|
|
276
|
+
container.innerHTML = '<div class="empty-state">璇峰厛閫夋嫨涓€涓兢缁?/div>';
|
|
279
277
|
return;
|
|
280
278
|
}
|
|
281
279
|
|
|
@@ -283,7 +281,7 @@ export function renderUserDashboard(user, wsService) {
|
|
|
283
281
|
|
|
284
282
|
container.innerHTML = `
|
|
285
283
|
<div class="view-header">
|
|
286
|
-
<h2
|
|
284
|
+
<h2>鍏变韩鏂囨。 - ${currentGroup.name}</h2>
|
|
287
285
|
</div>
|
|
288
286
|
<div class="documents-list" id="docsList"></div>
|
|
289
287
|
`;
|
|
@@ -291,7 +289,7 @@ export function renderUserDashboard(user, wsService) {
|
|
|
291
289
|
const docsList = document.getElementById('docsList');
|
|
292
290
|
|
|
293
291
|
if (result.documents.length === 0) {
|
|
294
|
-
docsList.innerHTML = '<div class="empty-state"
|
|
292
|
+
docsList.innerHTML = '<div class="empty-state">鏆傛棤鏂囨。</div>';
|
|
295
293
|
return;
|
|
296
294
|
}
|
|
297
295
|
|
|
@@ -299,14 +297,14 @@ export function renderUserDashboard(user, wsService) {
|
|
|
299
297
|
const docCard = document.createElement('div');
|
|
300
298
|
docCard.className = 'document-card';
|
|
301
299
|
docCard.innerHTML = `
|
|
302
|
-
<h3
|
|
300
|
+
<h3>馃搫 ${doc.title}</h3>
|
|
303
301
|
<div class="doc-meta">
|
|
304
|
-
<span
|
|
305
|
-
<span>${doc.permission === 'readonly' ? '
|
|
306
|
-
<span
|
|
302
|
+
<span>鍒涘缓鑰? ${doc.creator.username}</span>
|
|
303
|
+
<span>${doc.permission === 'readonly' ? '馃敀 鍙' : '鉁忥笍 鍙紪杈?}</span>
|
|
304
|
+
<span>鏇存柊: ${new Date(doc.updatedAt).toLocaleString()}</span>
|
|
307
305
|
</div>
|
|
308
306
|
<button class="btn-edit" data-id="${doc._id}">
|
|
309
|
-
${doc.permission === 'readonly' ? '
|
|
307
|
+
${doc.permission === 'readonly' ? '鏌ョ湅' : '缂栬緫'}
|
|
310
308
|
</button>
|
|
311
309
|
`;
|
|
312
310
|
docsList.appendChild(docCard);
|
|
@@ -325,25 +323,25 @@ export function renderUserDashboard(user, wsService) {
|
|
|
325
323
|
|
|
326
324
|
container.innerHTML = `
|
|
327
325
|
<div class="view-header">
|
|
328
|
-
<button class="btn-back" id="backBtn"
|
|
326
|
+
<button class="btn-back" id="backBtn">鈫?杩斿洖</button>
|
|
329
327
|
<h2>${doc.title}</h2>
|
|
330
|
-
<span class="doc-status">${doc.permission === 'readonly' ? '
|
|
328
|
+
<span class="doc-status">${doc.permission === 'readonly' ? '馃敀 鍙妯″紡' : '鉁忥笍 缂栬緫妯″紡'}</span>
|
|
331
329
|
</div>
|
|
332
330
|
<div class="editor-container">
|
|
333
331
|
<div class="editor-toolbar">
|
|
334
332
|
<div class="online-users" id="onlineUsers">
|
|
335
|
-
<span class="user-badge"
|
|
333
|
+
<span class="user-badge">馃懁 ${user.username}</span>
|
|
336
334
|
</div>
|
|
337
|
-
${doc.permission === 'editable' ? '<button class="btn-primary" id="saveBtn"
|
|
335
|
+
${doc.permission === 'editable' ? '<button class="btn-primary" id="saveBtn">淇濆瓨</button>' : ''}
|
|
338
336
|
</div>
|
|
339
337
|
<div id="editor" ${doc.permission === 'readonly' ? 'class="readonly"' : ''}></div>
|
|
340
338
|
<div class="editor-footer">
|
|
341
|
-
<span
|
|
339
|
+
<span>鏈€鍚庣紪杈? ${new Date(doc.updatedAt).toLocaleString()}</span>
|
|
342
340
|
</div>
|
|
343
341
|
</div>
|
|
344
342
|
`;
|
|
345
343
|
|
|
346
|
-
//
|
|
344
|
+
// 鍒濆鍖?Quill 缂栬緫鍣?
|
|
347
345
|
const quill = new Quill('#editor', {
|
|
348
346
|
theme: 'snow',
|
|
349
347
|
modules: {
|
|
@@ -359,15 +357,15 @@ export function renderUserDashboard(user, wsService) {
|
|
|
359
357
|
readOnly: doc.permission === 'readonly'
|
|
360
358
|
});
|
|
361
359
|
|
|
362
|
-
//
|
|
363
|
-
|
|
360
|
+
// 璁剧疆鍒濆鍐呭
|
|
361
|
+
editor.value = doc.content || '';
|
|
364
362
|
|
|
365
|
-
//
|
|
363
|
+
// 瀹炴椂鍚屾
|
|
366
364
|
if (doc.permission === 'editable') {
|
|
367
365
|
let typingTimeout;
|
|
368
366
|
let saveTimeout;
|
|
369
367
|
|
|
370
|
-
|
|
368
|
+
editor.addEventListener('input', () => {
|
|
371
369
|
clearTimeout(typingTimeout);
|
|
372
370
|
clearTimeout(saveTimeout);
|
|
373
371
|
wsService.sendTyping(documentId, user.username, true);
|
|
@@ -376,45 +374,45 @@ export function renderUserDashboard(user, wsService) {
|
|
|
376
374
|
wsService.sendTyping(documentId, user.username, false);
|
|
377
375
|
}, 1000);
|
|
378
376
|
|
|
379
|
-
//
|
|
377
|
+
// 鑷姩淇濆瓨
|
|
380
378
|
saveTimeout = setTimeout(async () => {
|
|
381
|
-
const content =
|
|
379
|
+
const content = editor.value;
|
|
382
380
|
try {
|
|
383
381
|
await apiService.updateDocument(documentId, content);
|
|
384
382
|
} catch (error) {
|
|
385
|
-
console.error('
|
|
383
|
+
console.error('鑷姩淇濆瓨澶辫触:', error);
|
|
386
384
|
}
|
|
387
385
|
}, 2000);
|
|
388
386
|
});
|
|
389
387
|
|
|
390
388
|
document.getElementById('saveBtn').addEventListener('click', async () => {
|
|
391
389
|
try {
|
|
392
|
-
const content =
|
|
390
|
+
const content = editor.value;
|
|
393
391
|
await apiService.updateDocument(documentId, content);
|
|
394
|
-
alert('
|
|
392
|
+
alert('淇濆瓨鎴愬姛锛?);
|
|
395
393
|
} catch (error) {
|
|
396
|
-
alert('
|
|
394
|
+
alert('淇濆瓨澶辫触: ' + error.message);
|
|
397
395
|
}
|
|
398
396
|
});
|
|
399
397
|
}
|
|
400
398
|
|
|
401
|
-
//
|
|
399
|
+
// 鐩戝惉鏂囨。鏇存柊
|
|
402
400
|
wsService.on('document_update', (data) => {
|
|
403
401
|
if (data.documentId === documentId && data.userId !== user.id) {
|
|
404
402
|
const selection = quill.getSelection();
|
|
405
|
-
|
|
403
|
+
editor.value = data.content;
|
|
406
404
|
if (selection) {
|
|
407
405
|
quill.setSelection(selection);
|
|
408
406
|
}
|
|
409
407
|
}
|
|
410
408
|
});
|
|
411
409
|
|
|
412
|
-
//
|
|
410
|
+
// 鐩戝惉鎵撳瓧鐘舵€?
|
|
413
411
|
wsService.on('typing', (data) => {
|
|
414
412
|
if (data.documentId === documentId && data.userId !== user.id) {
|
|
415
413
|
const onlineUsers = document.getElementById('onlineUsers');
|
|
416
414
|
if (data.isTyping) {
|
|
417
|
-
onlineUsers.innerHTML += `<span class="user-badge typing" data-user="${data.userId}"
|
|
415
|
+
onlineUsers.innerHTML += `<span class="user-badge typing" data-user="${data.userId}">鉁忥笍 ${data.username}</span>`;
|
|
418
416
|
} else {
|
|
419
417
|
const badge = onlineUsers.querySelector(`[data-user="${data.userId}"]`);
|
|
420
418
|
if (badge) badge.remove();
|
|
@@ -429,7 +427,7 @@ export function renderUserDashboard(user, wsService) {
|
|
|
429
427
|
|
|
430
428
|
async function renderFilesView(container) {
|
|
431
429
|
if (!currentGroup) {
|
|
432
|
-
container.innerHTML = '<div class="empty-state"
|
|
430
|
+
container.innerHTML = '<div class="empty-state">璇峰厛閫夋嫨涓€涓兢缁?/div>';
|
|
433
431
|
return;
|
|
434
432
|
}
|
|
435
433
|
|
|
@@ -438,31 +436,31 @@ export function renderUserDashboard(user, wsService) {
|
|
|
438
436
|
|
|
439
437
|
container.innerHTML = `
|
|
440
438
|
<div class="view-header">
|
|
441
|
-
<h2
|
|
442
|
-
<button class="btn-primary" id="uploadFileBtn"
|
|
439
|
+
<h2>鏂囦欢鍏变韩 - ${currentGroup.name}</h2>
|
|
440
|
+
<button class="btn-primary" id="uploadFileBtn">馃摛 涓婁紶鏂囦欢</button>
|
|
443
441
|
</div>
|
|
444
442
|
<div class="files-list" id="filesList"></div>
|
|
445
443
|
|
|
446
|
-
<!--
|
|
444
|
+
<!-- 鏂囦欢涓婁紶妯℃€佹 -->
|
|
447
445
|
<div class="modal hidden" id="uploadFileModal">
|
|
448
446
|
<div class="modal-content">
|
|
449
447
|
<div class="modal-header">
|
|
450
|
-
<h3
|
|
448
|
+
<h3>涓婁紶鏂囦欢</h3>
|
|
451
449
|
<button class="modal-close" id="closeUploadModal">×</button>
|
|
452
450
|
</div>
|
|
453
451
|
<form id="uploadFileForm">
|
|
454
452
|
<div class="form-group">
|
|
455
|
-
<label
|
|
453
|
+
<label>閫夋嫨鏂囦欢</label>
|
|
456
454
|
<input type="file" id="fileInput" required>
|
|
457
|
-
<small
|
|
455
|
+
<small>鏀寔鍥剧墖銆丳DF銆乄ord銆丒xcel绛夛紝鏈€澶?0MB</small>
|
|
458
456
|
</div>
|
|
459
457
|
<div class="form-group">
|
|
460
|
-
<label
|
|
461
|
-
<textarea id="fileDescription" rows="3" placeholder="
|
|
458
|
+
<label>鎻忚堪锛堝彲閫夛級</label>
|
|
459
|
+
<textarea id="fileDescription" rows="3" placeholder="鏂囦欢鎻忚堪..."></textarea>
|
|
462
460
|
</div>
|
|
463
461
|
<div class="form-actions">
|
|
464
|
-
<button type="button" class="btn-secondary" id="cancelUpload"
|
|
465
|
-
<button type="submit" class="btn-primary"
|
|
462
|
+
<button type="button" class="btn-secondary" id="cancelUpload">鍙栨秷</button>
|
|
463
|
+
<button type="submit" class="btn-primary">涓婁紶</button>
|
|
466
464
|
</div>
|
|
467
465
|
</form>
|
|
468
466
|
</div>
|
|
@@ -472,7 +470,7 @@ export function renderUserDashboard(user, wsService) {
|
|
|
472
470
|
const filesList = document.getElementById('filesList');
|
|
473
471
|
|
|
474
472
|
if (!result.files || result.files.length === 0) {
|
|
475
|
-
filesList.innerHTML = '<div class="empty-state"
|
|
473
|
+
filesList.innerHTML = '<div class="empty-state">鏆傛棤鏂囦欢</div>';
|
|
476
474
|
} else {
|
|
477
475
|
result.files.forEach(file => {
|
|
478
476
|
const fileCard = document.createElement('div');
|
|
@@ -486,37 +484,37 @@ export function renderUserDashboard(user, wsService) {
|
|
|
486
484
|
<div class="file-info">
|
|
487
485
|
<h4>${file.originalName}</h4>
|
|
488
486
|
<div class="file-meta">
|
|
489
|
-
<span
|
|
490
|
-
<span
|
|
491
|
-
<span
|
|
487
|
+
<span>涓婁紶鑰? ${file.uploader.username}</span>
|
|
488
|
+
<span>澶у皬: ${fileSize}</span>
|
|
489
|
+
<span>鏃堕棿: ${new Date(file.createdAt).toLocaleString()}</span>
|
|
492
490
|
</div>
|
|
493
491
|
${file.description ? `<p class="file-description">${file.description}</p>` : ''}
|
|
494
492
|
</div>
|
|
495
493
|
<div class="file-actions">
|
|
496
|
-
<a href="${apiService.getFileDownloadUrl(file._id)}" class="btn-primary" download
|
|
497
|
-
${file.uploader._id === currentUserId ? `<button class="btn-danger" data-id="${file._id}" data-action="delete-file"
|
|
494
|
+
<a href="${apiService.getFileDownloadUrl(file._id)}" class="btn-primary" download>涓嬭浇</a>
|
|
495
|
+
${file.uploader._id === currentUserId ? `<button class="btn-danger" data-id="${file._id}" data-action="delete-file">鍒犻櫎</button>` : ''}
|
|
498
496
|
</div>
|
|
499
497
|
`;
|
|
500
498
|
filesList.appendChild(fileCard);
|
|
501
499
|
});
|
|
502
500
|
|
|
503
|
-
//
|
|
501
|
+
// 鍒犻櫎鏂囦欢浜嬩欢
|
|
504
502
|
document.querySelectorAll('[data-action="delete-file"]').forEach(btn => {
|
|
505
503
|
btn.addEventListener('click', async () => {
|
|
506
|
-
if (confirm('
|
|
504
|
+
if (confirm('纭畾瑕佸垹闄よ繖涓枃浠跺悧锛?)) {
|
|
507
505
|
try {
|
|
508
506
|
await apiService.deleteFile(btn.dataset.id);
|
|
509
|
-
alert('
|
|
507
|
+
alert('鏂囦欢鍒犻櫎鎴愬姛锛?);
|
|
510
508
|
await renderFilesView(container);
|
|
511
509
|
} catch (error) {
|
|
512
|
-
alert('
|
|
510
|
+
alert('鍒犻櫎澶辫触: ' + error.message);
|
|
513
511
|
}
|
|
514
512
|
}
|
|
515
513
|
});
|
|
516
514
|
});
|
|
517
515
|
}
|
|
518
516
|
|
|
519
|
-
//
|
|
517
|
+
// 鏂囦欢涓婁紶鍔熻兘
|
|
520
518
|
document.getElementById('uploadFileBtn').addEventListener('click', () => {
|
|
521
519
|
document.getElementById('uploadFileModal').classList.remove('hidden');
|
|
522
520
|
});
|
|
@@ -537,38 +535,38 @@ export function renderUserDashboard(user, wsService) {
|
|
|
537
535
|
const description = document.getElementById('fileDescription').value;
|
|
538
536
|
|
|
539
537
|
if (!fileInput.files[0]) {
|
|
540
|
-
alert('
|
|
538
|
+
alert('璇烽€夋嫨鏂囦欢');
|
|
541
539
|
return;
|
|
542
540
|
}
|
|
543
541
|
|
|
544
542
|
try {
|
|
545
543
|
await apiService.uploadFile(currentGroup._id, fileInput.files[0], description);
|
|
546
|
-
alert('
|
|
544
|
+
alert('鏂囦欢涓婁紶鎴愬姛锛?);
|
|
547
545
|
document.getElementById('uploadFileModal').classList.add('hidden');
|
|
548
546
|
document.getElementById('uploadFileForm').reset();
|
|
549
547
|
await renderFilesView(container);
|
|
550
548
|
} catch (error) {
|
|
551
|
-
alert('
|
|
549
|
+
alert('涓婁紶澶辫触: ' + error.message);
|
|
552
550
|
}
|
|
553
551
|
});
|
|
554
552
|
} catch (error) {
|
|
555
|
-
console.error('
|
|
553
|
+
console.error('鑾峰彇鏂囦欢鍒楄〃澶辫触:', error);
|
|
556
554
|
container.innerHTML = `
|
|
557
555
|
<div class="view-header">
|
|
558
|
-
<h2
|
|
556
|
+
<h2>鏂囦欢鍏变韩</h2>
|
|
559
557
|
</div>
|
|
560
|
-
<div class="empty-state"
|
|
558
|
+
<div class="empty-state">鍔犺浇鏂囦欢澶辫触: ${error.message}</div>
|
|
561
559
|
`;
|
|
562
560
|
}
|
|
563
561
|
}
|
|
564
562
|
|
|
565
563
|
function getFileIcon(mimetype) {
|
|
566
|
-
if (mimetype.startsWith('image/')) return '
|
|
567
|
-
if (mimetype === 'application/pdf') return '
|
|
568
|
-
if (mimetype.includes('word') || mimetype.includes('document')) return '
|
|
569
|
-
if (mimetype.includes('excel') || mimetype.includes('spreadsheet')) return '
|
|
570
|
-
if (mimetype.includes('zip') || mimetype.includes('compressed')) return '
|
|
571
|
-
return '
|
|
564
|
+
if (mimetype.startsWith('image/')) return '馃柤锔?;
|
|
565
|
+
if (mimetype === 'application/pdf') return '馃摃';
|
|
566
|
+
if (mimetype.includes('word') || mimetype.includes('document')) return '馃摌';
|
|
567
|
+
if (mimetype.includes('excel') || mimetype.includes('spreadsheet')) return '馃摋';
|
|
568
|
+
if (mimetype.includes('zip') || mimetype.includes('compressed')) return '馃摝';
|
|
569
|
+
return '馃搫';
|
|
572
570
|
}
|
|
573
571
|
|
|
574
572
|
function formatFileSize(bytes) {
|
|
@@ -581,7 +579,7 @@ export function renderUserDashboard(user, wsService) {
|
|
|
581
579
|
|
|
582
580
|
async function renderChatView(container) {
|
|
583
581
|
if (!currentGroup) {
|
|
584
|
-
container.innerHTML = '<div class="empty-state"
|
|
582
|
+
container.innerHTML = '<div class="empty-state">璇峰厛閫夋嫨涓€涓兢缁?/div>';
|
|
585
583
|
return;
|
|
586
584
|
}
|
|
587
585
|
|
|
@@ -593,14 +591,14 @@ export function renderUserDashboard(user, wsService) {
|
|
|
593
591
|
|
|
594
592
|
container.innerHTML = `
|
|
595
593
|
<div class="view-header">
|
|
596
|
-
<h2
|
|
594
|
+
<h2>缇よ亰 - ${currentGroup.name}</h2>
|
|
597
595
|
</div>
|
|
598
596
|
<div class="chat-container">
|
|
599
597
|
<div class="messages" id="messages"></div>
|
|
600
598
|
<div class="chat-input">
|
|
601
|
-
<button class="btn-emoji" id="emojiBtn" ${canSpeak ? '' : 'disabled'}
|
|
602
|
-
<input type="text" id="messageInput" placeholder="${canSpeak ? '
|
|
603
|
-
<button class="btn-primary" id="sendBtn" ${canSpeak ? '' : 'disabled'}
|
|
599
|
+
<button class="btn-emoji" id="emojiBtn" ${canSpeak ? '' : 'disabled'}>馃槉</button>
|
|
600
|
+
<input type="text" id="messageInput" placeholder="${canSpeak ? '杈撳叆娑堟伅...' : (isMutedAll ? '鍏ㄤ綋绂佽█涓紝鏃犳硶鍙戣█' : '浣犲凡琚瑷€')}" ${canSpeak ? '' : 'disabled'}>
|
|
601
|
+
<button class="btn-primary" id="sendBtn" ${canSpeak ? '' : 'disabled'}>鍙戦€?/button>
|
|
604
602
|
</div>
|
|
605
603
|
<emoji-picker id="emojiPicker" class="hidden"></emoji-picker>
|
|
606
604
|
</div>
|
|
@@ -610,7 +608,7 @@ export function renderUserDashboard(user, wsService) {
|
|
|
610
608
|
const messageInput = document.getElementById('messageInput');
|
|
611
609
|
const sendBtn = document.getElementById('sendBtn');
|
|
612
610
|
|
|
613
|
-
//
|
|
611
|
+
// 鍔犺浇鍘嗗彶娑堟伅
|
|
614
612
|
try {
|
|
615
613
|
const messagesResult = await apiService.getGroupMessages(currentGroup._id);
|
|
616
614
|
if (messagesResult.messages) {
|
|
@@ -629,10 +627,10 @@ export function renderUserDashboard(user, wsService) {
|
|
|
629
627
|
messagesDiv.scrollTop = messagesDiv.scrollHeight;
|
|
630
628
|
}
|
|
631
629
|
} catch (err) {
|
|
632
|
-
console.error('
|
|
630
|
+
console.error('鍔犺浇鍘嗗彶娑堟伅澶辫触:', err);
|
|
633
631
|
}
|
|
634
632
|
|
|
635
|
-
//
|
|
633
|
+
// 琛ㄦ儏鍖呭姛鑳?
|
|
636
634
|
const emojiBtn = document.getElementById('emojiBtn');
|
|
637
635
|
const emojiPicker = document.getElementById('emojiPicker');
|
|
638
636
|
|
|
@@ -646,15 +644,15 @@ export function renderUserDashboard(user, wsService) {
|
|
|
646
644
|
emojiPicker.classList.add('hidden');
|
|
647
645
|
});
|
|
648
646
|
|
|
649
|
-
//
|
|
647
|
+
// 鐐瑰嚮澶栭儴鍏抽棴琛ㄦ儏閫夋嫨鍣?
|
|
650
648
|
document.addEventListener('click', (e) => {
|
|
651
649
|
if (!emojiBtn.contains(e.target) && !emojiPicker.contains(e.target)) {
|
|
652
650
|
emojiPicker.classList.add('hidden');
|
|
653
651
|
}
|
|
654
652
|
});
|
|
655
653
|
|
|
656
|
-
//
|
|
657
|
-
function showNotification(title, body, icon = '
|
|
654
|
+
// 娑堟伅閫氱煡绯荤粺
|
|
655
|
+
function showNotification(title, body, icon = '馃挰') {
|
|
658
656
|
if ('Notification' in window && Notification.permission === 'granted') {
|
|
659
657
|
new Notification(title, {
|
|
660
658
|
body: body,
|
|
@@ -665,12 +663,12 @@ export function renderUserDashboard(user, wsService) {
|
|
|
665
663
|
}
|
|
666
664
|
}
|
|
667
665
|
|
|
668
|
-
//
|
|
666
|
+
// 璇锋眰閫氱煡鏉冮檺
|
|
669
667
|
if ('Notification' in window && Notification.permission === 'default') {
|
|
670
668
|
Notification.requestPermission();
|
|
671
669
|
}
|
|
672
670
|
|
|
673
|
-
//
|
|
671
|
+
// 鐩戝惉娑堟伅
|
|
674
672
|
wsService.on('chat_message', (data) => {
|
|
675
673
|
if (data.groupId === currentGroup._id) {
|
|
676
674
|
const messageEl = document.createElement('div');
|
|
@@ -685,35 +683,35 @@ export function renderUserDashboard(user, wsService) {
|
|
|
685
683
|
messagesDiv.appendChild(messageEl);
|
|
686
684
|
messagesDiv.scrollTop = messagesDiv.scrollHeight;
|
|
687
685
|
|
|
688
|
-
//
|
|
686
|
+
// 鏄剧ず閫氱煡锛堝鏋滀笉鏄嚜宸卞彂閫佺殑娑堟伅锛?
|
|
689
687
|
if (data.userId !== currentUserId) {
|
|
690
|
-
showNotification(`${data.username}
|
|
688
|
+
showNotification(`${data.username} 鍦?${currentGroup.name}`, data.content);
|
|
691
689
|
}
|
|
692
690
|
}
|
|
693
691
|
});
|
|
694
692
|
|
|
695
|
-
//
|
|
693
|
+
// 鏈嶅姟绔嫤鎴彁绀猴紙姣斿琚瑷€/鏈姞鍏ョ兢缁勶級
|
|
696
694
|
wsService.on('chat_blocked', (data) => {
|
|
697
695
|
if (data.groupId === currentGroup._id) {
|
|
698
696
|
const notificationEl = document.createElement('div');
|
|
699
697
|
notificationEl.className = 'notification';
|
|
700
|
-
notificationEl.textContent = data.message || '
|
|
698
|
+
notificationEl.textContent = data.message || '娑堟伅鍙戦€佸け璐?;
|
|
701
699
|
messagesDiv.appendChild(notificationEl);
|
|
702
700
|
messagesDiv.scrollTop = messagesDiv.scrollHeight;
|
|
703
701
|
}
|
|
704
702
|
});
|
|
705
703
|
|
|
706
|
-
//
|
|
704
|
+
// 鐩戝惉鐐瑰悕閫氱煡
|
|
707
705
|
wsService.on('call_response', (data) => {
|
|
708
706
|
if (data.groupId === currentGroup._id) {
|
|
709
707
|
const notificationEl = document.createElement('div');
|
|
710
708
|
notificationEl.className = 'notification';
|
|
711
|
-
notificationEl.textContent = `${data.username}
|
|
709
|
+
notificationEl.textContent = `${data.username} 宸插搷搴旂偣鍚峘;
|
|
712
710
|
messagesDiv.appendChild(notificationEl);
|
|
713
711
|
}
|
|
714
712
|
});
|
|
715
713
|
|
|
716
|
-
//
|
|
714
|
+
// 鍙戦€佹秷鎭?
|
|
717
715
|
const sendMessage = () => {
|
|
718
716
|
const content = messageInput.value.trim();
|
|
719
717
|
if (content) {
|
|
@@ -731,22 +729,22 @@ export function renderUserDashboard(user, wsService) {
|
|
|
731
729
|
async function renderSearchView(container) {
|
|
732
730
|
container.innerHTML = `
|
|
733
731
|
<div class="view-header">
|
|
734
|
-
<h2
|
|
732
|
+
<h2>馃攳 鎼滅储</h2>
|
|
735
733
|
</div>
|
|
736
734
|
<div class="search-container">
|
|
737
735
|
<div class="search-box">
|
|
738
|
-
<input type="text" id="searchInput" placeholder="
|
|
739
|
-
<button class="btn-primary" id="searchBtn"
|
|
736
|
+
<input type="text" id="searchInput" placeholder="鎼滅储娑堟伅銆佹枃妗c€佷换鍔?..">
|
|
737
|
+
<button class="btn-primary" id="searchBtn">鎼滅储</button>
|
|
740
738
|
</div>
|
|
741
739
|
<div class="search-filters">
|
|
742
740
|
<label>
|
|
743
|
-
<input type="checkbox" id="filterMessages" checked>
|
|
741
|
+
<input type="checkbox" id="filterMessages" checked> 娑堟伅
|
|
744
742
|
</label>
|
|
745
743
|
<label>
|
|
746
|
-
<input type="checkbox" id="filterDocuments" checked>
|
|
744
|
+
<input type="checkbox" id="filterDocuments" checked> 鏂囨。
|
|
747
745
|
</label>
|
|
748
746
|
<label>
|
|
749
|
-
<input type="checkbox" id="filterTasks" checked>
|
|
747
|
+
<input type="checkbox" id="filterTasks" checked> 浠诲姟
|
|
750
748
|
</label>
|
|
751
749
|
</div>
|
|
752
750
|
<div class="search-results" id="searchResults"></div>
|
|
@@ -760,7 +758,7 @@ export function renderUserDashboard(user, wsService) {
|
|
|
760
758
|
const performSearch = async () => {
|
|
761
759
|
const query = searchInput.value.trim();
|
|
762
760
|
if (!query) {
|
|
763
|
-
searchResults.innerHTML = '<div class="empty-state"
|
|
761
|
+
searchResults.innerHTML = '<div class="empty-state">璇疯緭鍏ユ悳绱㈠叧閿瘝</div>';
|
|
764
762
|
return;
|
|
765
763
|
}
|
|
766
764
|
|
|
@@ -770,12 +768,12 @@ export function renderUserDashboard(user, wsService) {
|
|
|
770
768
|
tasks: document.getElementById('filterTasks').checked
|
|
771
769
|
};
|
|
772
770
|
|
|
773
|
-
searchResults.innerHTML = '<div class="loading"
|
|
771
|
+
searchResults.innerHTML = '<div class="loading">鎼滅储涓?..</div>';
|
|
774
772
|
|
|
775
773
|
try {
|
|
776
774
|
const results = [];
|
|
777
775
|
|
|
778
|
-
//
|
|
776
|
+
// 鎼滅储娑堟伅
|
|
779
777
|
if (filters.messages && currentGroup) {
|
|
780
778
|
try {
|
|
781
779
|
const messagesResult = await apiService.getGroupMessages(currentGroup._id);
|
|
@@ -786,7 +784,7 @@ export function renderUserDashboard(user, wsService) {
|
|
|
786
784
|
matchedMessages.forEach(msg => {
|
|
787
785
|
results.push({
|
|
788
786
|
type: 'message',
|
|
789
|
-
title:
|
|
787
|
+
title: `娑堟伅 - ${msg.username}`,
|
|
790
788
|
content: msg.content,
|
|
791
789
|
time: msg.timestamp,
|
|
792
790
|
group: currentGroup.name
|
|
@@ -794,11 +792,11 @@ export function renderUserDashboard(user, wsService) {
|
|
|
794
792
|
});
|
|
795
793
|
}
|
|
796
794
|
} catch (err) {
|
|
797
|
-
console.error('
|
|
795
|
+
console.error('鎼滅储娑堟伅澶辫触:', err);
|
|
798
796
|
}
|
|
799
797
|
}
|
|
800
798
|
|
|
801
|
-
//
|
|
799
|
+
// 鎼滅储鏂囨。
|
|
802
800
|
if (filters.documents) {
|
|
803
801
|
try {
|
|
804
802
|
if (currentGroup) {
|
|
@@ -821,11 +819,11 @@ export function renderUserDashboard(user, wsService) {
|
|
|
821
819
|
}
|
|
822
820
|
}
|
|
823
821
|
} catch (err) {
|
|
824
|
-
console.error('
|
|
822
|
+
console.error('鎼滅储鏂囨。澶辫触:', err);
|
|
825
823
|
}
|
|
826
824
|
}
|
|
827
825
|
|
|
828
|
-
//
|
|
826
|
+
// 鎼滅储浠诲姟
|
|
829
827
|
if (filters.tasks) {
|
|
830
828
|
try {
|
|
831
829
|
const tasksResult = await apiService.getMyTasks();
|
|
@@ -846,36 +844,36 @@ export function renderUserDashboard(user, wsService) {
|
|
|
846
844
|
});
|
|
847
845
|
}
|
|
848
846
|
} catch (err) {
|
|
849
|
-
console.error('
|
|
847
|
+
console.error('鎼滅储浠诲姟澶辫触:', err);
|
|
850
848
|
}
|
|
851
849
|
}
|
|
852
850
|
|
|
853
|
-
//
|
|
851
|
+
// 鏄剧ず缁撴灉
|
|
854
852
|
if (results.length === 0) {
|
|
855
|
-
searchResults.innerHTML = '<div class="empty-state"
|
|
853
|
+
searchResults.innerHTML = '<div class="empty-state">鏈壘鍒扮浉鍏崇粨鏋?/div>';
|
|
856
854
|
} else {
|
|
857
855
|
searchResults.innerHTML = results.map(result => {
|
|
858
856
|
const typeIcon = {
|
|
859
|
-
message: '
|
|
860
|
-
document: '
|
|
861
|
-
task: '
|
|
857
|
+
message: '馃挰',
|
|
858
|
+
document: '馃搫',
|
|
859
|
+
task: '馃搵'
|
|
862
860
|
};
|
|
863
861
|
return `
|
|
864
862
|
<div class="search-result-item">
|
|
865
863
|
<div class="result-header">
|
|
866
|
-
<span class="result-type">${typeIcon[result.type]} ${result.type === 'message' ? '
|
|
864
|
+
<span class="result-type">${typeIcon[result.type]} ${result.type === 'message' ? '娑堟伅' : result.type === 'document' ? '鏂囨。' : '浠诲姟'}</span>
|
|
867
865
|
<span class="result-time">${new Date(result.time).toLocaleString()}</span>
|
|
868
866
|
</div>
|
|
869
867
|
<h4>${highlightText(result.title, query)}</h4>
|
|
870
868
|
<p>${highlightText(result.content, query)}</p>
|
|
871
|
-
${result.group ? `<span class="result-group"
|
|
872
|
-
${result.status ? `<span class="result-status"
|
|
869
|
+
${result.group ? `<span class="result-group">缇ょ粍: ${result.group}</span>` : ''}
|
|
870
|
+
${result.status ? `<span class="result-status">鐘舵€? ${getStatusText(result.status)}</span>` : ''}
|
|
873
871
|
</div>
|
|
874
872
|
`;
|
|
875
873
|
}).join('');
|
|
876
874
|
}
|
|
877
875
|
} catch (error) {
|
|
878
|
-
searchResults.innerHTML = `<div class="empty-state"
|
|
876
|
+
searchResults.innerHTML = `<div class="empty-state">鎼滅储澶辫触: ${error.message}</div>`;
|
|
879
877
|
}
|
|
880
878
|
};
|
|
881
879
|
|
|
@@ -893,10 +891,10 @@ export function renderUserDashboard(user, wsService) {
|
|
|
893
891
|
|
|
894
892
|
function getStatusText(status) {
|
|
895
893
|
const statusMap = {
|
|
896
|
-
'pending': '
|
|
897
|
-
'in_progress': '
|
|
898
|
-
'completed': '
|
|
899
|
-
'terminated': '
|
|
894
|
+
'pending': '寰呭鐞?,
|
|
895
|
+
'in_progress': '杩涜涓?,
|
|
896
|
+
'completed': '宸插畬鎴?,
|
|
897
|
+
'terminated': '宸茬粓姝?
|
|
900
898
|
};
|
|
901
899
|
return statusMap[status] || status;
|
|
902
900
|
}
|