collabdocchat 2.4.7 → 2.4.9
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 +1 -1
- package/scripts/start-app.js +55 -33
- package/server/index.js +13 -0
- package/server/public/index.html +246 -0
package/package.json
CHANGED
package/scripts/start-app.js
CHANGED
|
@@ -33,7 +33,7 @@ function installDevDependencies() {
|
|
|
33
33
|
const install = spawn(npmCmd, ['install'], {
|
|
34
34
|
cwd: rootDir,
|
|
35
35
|
stdio: 'inherit',
|
|
36
|
-
shell:
|
|
36
|
+
shell: isWindows // Windows 需要 shell
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
install.on('close', (code) => {
|
|
@@ -187,16 +187,16 @@ async function main() {
|
|
|
187
187
|
process.exit(1);
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
190
|
+
// 检查是否有开发依赖(全局安装时可能没有)
|
|
191
|
+
const hasDevDeps = checkDevDependencies();
|
|
192
|
+
|
|
193
|
+
if (!hasDevDeps) {
|
|
194
|
+
console.log('⚠️ 检测到全局安装模式(无开发依赖)');
|
|
195
|
+
console.log('💡 将只启动服务器,不启动客户端\n');
|
|
196
|
+
console.log('📝 如需完整开发环境,请:');
|
|
197
|
+
console.log(' 1. 克隆项目到本地目录');
|
|
198
|
+
console.log(' 2. 运行 npm install');
|
|
199
|
+
console.log(' 3. 运行 npm run dev\n');
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
// 启动服务器
|
|
@@ -211,38 +211,60 @@ async function main() {
|
|
|
211
211
|
process.exit(1);
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
214
|
+
let client = null;
|
|
215
|
+
|
|
216
|
+
// 只有在有开发依赖时才启动客户端
|
|
217
|
+
if (hasDevDeps) {
|
|
218
|
+
// 启动客户端
|
|
219
|
+
client = startClient();
|
|
220
|
+
|
|
221
|
+
// 等待客户端就绪后打开浏览器
|
|
222
|
+
setTimeout(async () => {
|
|
223
|
+
try {
|
|
224
|
+
await waitForServer(CLIENT_URL, 20, 500);
|
|
225
|
+
console.log(`\n🌐 正在打开浏览器: ${CLIENT_URL}`);
|
|
226
|
+
openBrowser(CLIENT_URL);
|
|
227
|
+
console.log('\n✅ 应用启动成功!');
|
|
228
|
+
console.log('\n💡 提示:');
|
|
229
|
+
console.log(` • 服务器: http://localhost:${PORT}`);
|
|
230
|
+
console.log(' • 客户端: http://localhost:5173');
|
|
231
|
+
console.log(' • 默认账号: admin / admin123');
|
|
232
|
+
console.log('\n⚠️ 按 Ctrl+C 停止服务\n');
|
|
233
|
+
} catch (error) {
|
|
234
|
+
console.log(`\n⚠️ 客户端可能还在启动中,请手动访问: ${CLIENT_URL}`);
|
|
235
|
+
openBrowser(CLIENT_URL);
|
|
236
|
+
}
|
|
237
|
+
}, 3000);
|
|
238
|
+
} else {
|
|
239
|
+
// 全局安装模式,只有服务器,自动打开浏览器
|
|
240
|
+
console.log('\n✅ 服务器启动成功!');
|
|
241
|
+
console.log('\n💡 提示:');
|
|
242
|
+
console.log(` • API 服务器: http://localhost:${PORT}`);
|
|
243
|
+
console.log(' • 默认账号: admin / admin123');
|
|
244
|
+
console.log('\n📝 注意:');
|
|
245
|
+
console.log(' 全局安装模式仅提供 API 服务器');
|
|
246
|
+
console.log(' 如需完整的前端界面,请在本地项目中运行');
|
|
247
|
+
console.log('\n🌐 正在打开浏览器...\n');
|
|
248
|
+
|
|
249
|
+
// 延迟1秒后打开浏览器
|
|
250
|
+
setTimeout(() => {
|
|
251
|
+
openBrowser(`http://localhost:${PORT}`);
|
|
252
|
+
}, 1000);
|
|
253
|
+
|
|
254
|
+
console.log('⚠️ 按 Ctrl+C 停止服务\n');
|
|
255
|
+
}
|
|
234
256
|
|
|
235
257
|
// 处理退出信号
|
|
236
258
|
process.on('SIGINT', () => {
|
|
237
259
|
console.log('\n\n🛑 正在关闭服务器...');
|
|
238
260
|
server.kill();
|
|
239
|
-
client.kill();
|
|
261
|
+
if (client) client.kill();
|
|
240
262
|
process.exit(0);
|
|
241
263
|
});
|
|
242
264
|
|
|
243
265
|
process.on('SIGTERM', () => {
|
|
244
266
|
server.kill();
|
|
245
|
-
client.kill();
|
|
267
|
+
if (client) client.kill();
|
|
246
268
|
process.exit(0);
|
|
247
269
|
});
|
|
248
270
|
}
|
package/server/index.js
CHANGED
|
@@ -4,6 +4,8 @@ import { WebSocketServer } from 'ws';
|
|
|
4
4
|
import cors from 'cors';
|
|
5
5
|
import dotenv from 'dotenv';
|
|
6
6
|
import mongoose from 'mongoose';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import { dirname, join } from 'path';
|
|
7
9
|
import authRoutes from './routes/auth.js';
|
|
8
10
|
import taskRoutes from './routes/tasks.js';
|
|
9
11
|
import documentRoutes from './routes/documents.js';
|
|
@@ -23,6 +25,9 @@ import { initDefaultAdmin } from './utils/initAdmin.js';
|
|
|
23
25
|
import { errorHandler, notFoundHandler } from './middleware/errorHandler.js';
|
|
24
26
|
import backupService from './utils/backup.js';
|
|
25
27
|
|
|
28
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
29
|
+
const __dirname = dirname(__filename);
|
|
30
|
+
|
|
26
31
|
dotenv.config();
|
|
27
32
|
|
|
28
33
|
const app = express();
|
|
@@ -50,6 +55,9 @@ mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/collabdoc
|
|
|
50
55
|
// 静态文件服务(用于文件下载)
|
|
51
56
|
app.use('/uploads', express.static('uploads'));
|
|
52
57
|
|
|
58
|
+
// 静态页面服务(全局安装模式的欢迎页面)
|
|
59
|
+
app.use(express.static(join(__dirname, 'public')));
|
|
60
|
+
|
|
53
61
|
// API 路由
|
|
54
62
|
app.use('/api/auth', authRoutes);
|
|
55
63
|
app.use('/api/tasks', taskRoutes);
|
|
@@ -74,6 +82,11 @@ app.get('/health', (req, res) => {
|
|
|
74
82
|
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
|
75
83
|
});
|
|
76
84
|
|
|
85
|
+
// 根路径 - 返回欢迎页面
|
|
86
|
+
app.get('/', (req, res) => {
|
|
87
|
+
res.sendFile(join(__dirname, 'public', 'index.html'));
|
|
88
|
+
});
|
|
89
|
+
|
|
77
90
|
// 404 处理
|
|
78
91
|
app.use(notFoundHandler);
|
|
79
92
|
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>CollabDocChat - API 服务器</title>
|
|
7
|
+
<style>
|
|
8
|
+
* {
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
body {
|
|
15
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
16
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
17
|
+
min-height: 100vh;
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
justify-content: center;
|
|
21
|
+
padding: 20px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.container {
|
|
25
|
+
background: white;
|
|
26
|
+
border-radius: 20px;
|
|
27
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
28
|
+
max-width: 800px;
|
|
29
|
+
width: 100%;
|
|
30
|
+
padding: 40px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.header {
|
|
34
|
+
text-align: center;
|
|
35
|
+
margin-bottom: 40px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.logo {
|
|
39
|
+
font-size: 48px;
|
|
40
|
+
margin-bottom: 10px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
h1 {
|
|
44
|
+
color: #333;
|
|
45
|
+
font-size: 32px;
|
|
46
|
+
margin-bottom: 10px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.subtitle {
|
|
50
|
+
color: #666;
|
|
51
|
+
font-size: 16px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.status {
|
|
55
|
+
background: #f0fdf4;
|
|
56
|
+
border: 2px solid #86efac;
|
|
57
|
+
border-radius: 12px;
|
|
58
|
+
padding: 20px;
|
|
59
|
+
margin-bottom: 30px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.status-title {
|
|
63
|
+
color: #16a34a;
|
|
64
|
+
font-weight: bold;
|
|
65
|
+
font-size: 18px;
|
|
66
|
+
margin-bottom: 10px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.status-item {
|
|
70
|
+
color: #166534;
|
|
71
|
+
margin: 8px 0;
|
|
72
|
+
padding-left: 20px;
|
|
73
|
+
position: relative;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.status-item::before {
|
|
77
|
+
content: "✓";
|
|
78
|
+
position: absolute;
|
|
79
|
+
left: 0;
|
|
80
|
+
color: #16a34a;
|
|
81
|
+
font-weight: bold;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.info-box {
|
|
85
|
+
background: #f8fafc;
|
|
86
|
+
border-radius: 12px;
|
|
87
|
+
padding: 20px;
|
|
88
|
+
margin-bottom: 20px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.info-title {
|
|
92
|
+
font-weight: bold;
|
|
93
|
+
color: #334155;
|
|
94
|
+
margin-bottom: 15px;
|
|
95
|
+
font-size: 18px;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.info-item {
|
|
99
|
+
display: flex;
|
|
100
|
+
justify-content: space-between;
|
|
101
|
+
padding: 10px 0;
|
|
102
|
+
border-bottom: 1px solid #e2e8f0;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.info-item:last-child {
|
|
106
|
+
border-bottom: none;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.info-label {
|
|
110
|
+
color: #64748b;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.info-value {
|
|
114
|
+
color: #0f172a;
|
|
115
|
+
font-weight: 500;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.api-link {
|
|
119
|
+
color: #667eea;
|
|
120
|
+
text-decoration: none;
|
|
121
|
+
font-weight: 500;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.api-link:hover {
|
|
125
|
+
text-decoration: underline;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.warning-box {
|
|
129
|
+
background: #fef3c7;
|
|
130
|
+
border: 2px solid #fbbf24;
|
|
131
|
+
border-radius: 12px;
|
|
132
|
+
padding: 20px;
|
|
133
|
+
margin-bottom: 20px;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.warning-title {
|
|
137
|
+
color: #92400e;
|
|
138
|
+
font-weight: bold;
|
|
139
|
+
margin-bottom: 10px;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.warning-text {
|
|
143
|
+
color: #78350f;
|
|
144
|
+
line-height: 1.6;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.action-box {
|
|
148
|
+
background: #eff6ff;
|
|
149
|
+
border-radius: 12px;
|
|
150
|
+
padding: 20px;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.action-title {
|
|
154
|
+
color: #1e40af;
|
|
155
|
+
font-weight: bold;
|
|
156
|
+
margin-bottom: 15px;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.action-steps {
|
|
160
|
+
color: #1e3a8a;
|
|
161
|
+
line-height: 1.8;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.action-steps li {
|
|
165
|
+
margin: 8px 0;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
code {
|
|
169
|
+
background: #1e293b;
|
|
170
|
+
color: #e2e8f0;
|
|
171
|
+
padding: 2px 8px;
|
|
172
|
+
border-radius: 4px;
|
|
173
|
+
font-family: 'Courier New', monospace;
|
|
174
|
+
font-size: 14px;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.footer {
|
|
178
|
+
text-align: center;
|
|
179
|
+
margin-top: 30px;
|
|
180
|
+
color: #64748b;
|
|
181
|
+
font-size: 14px;
|
|
182
|
+
}
|
|
183
|
+
</style>
|
|
184
|
+
</head>
|
|
185
|
+
<body>
|
|
186
|
+
<div class="container">
|
|
187
|
+
<div class="header">
|
|
188
|
+
<div class="logo">🎉</div>
|
|
189
|
+
<h1>CollabDocChat</h1>
|
|
190
|
+
<p class="subtitle">开源的实时协作文档聊天平台</p>
|
|
191
|
+
</div>
|
|
192
|
+
|
|
193
|
+
<div class="status">
|
|
194
|
+
<div class="status-title">✅ API 服务器运行中</div>
|
|
195
|
+
<div class="status-item">MongoDB 已连接</div>
|
|
196
|
+
<div class="status-item">WebSocket 服务已启动</div>
|
|
197
|
+
<div class="status-item">所有 API 端点可用</div>
|
|
198
|
+
</div>
|
|
199
|
+
|
|
200
|
+
<div class="info-box">
|
|
201
|
+
<div class="info-title">📍 服务器信息</div>
|
|
202
|
+
<div class="info-item">
|
|
203
|
+
<span class="info-label">API 地址</span>
|
|
204
|
+
<span class="info-value"><a href="/api" class="api-link" target="_blank">http://localhost:3000/api</a></span>
|
|
205
|
+
</div>
|
|
206
|
+
<div class="info-item">
|
|
207
|
+
<span class="info-label">健康检查</span>
|
|
208
|
+
<span class="info-value"><a href="/health" class="api-link" target="_blank">http://localhost:3000/health</a></span>
|
|
209
|
+
</div>
|
|
210
|
+
<div class="info-item">
|
|
211
|
+
<span class="info-label">WebSocket</span>
|
|
212
|
+
<span class="info-value">ws://localhost:3000</span>
|
|
213
|
+
</div>
|
|
214
|
+
<div class="info-item">
|
|
215
|
+
<span class="info-label">默认账号</span>
|
|
216
|
+
<span class="info-value">admin / admin123</span>
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
|
|
220
|
+
<div class="warning-box">
|
|
221
|
+
<div class="warning-title">⚠️ 全局安装模式</div>
|
|
222
|
+
<p class="warning-text">
|
|
223
|
+
当前运行在全局安装模式下,仅提供 API 服务器。
|
|
224
|
+
如需完整的前端界面和开发环境,请按照下方步骤操作。
|
|
225
|
+
</p>
|
|
226
|
+
</div>
|
|
227
|
+
|
|
228
|
+
<div class="action-box">
|
|
229
|
+
<div class="action-title">🚀 获取完整功能</div>
|
|
230
|
+
<ol class="action-steps">
|
|
231
|
+
<li>克隆或下载项目到本地目录</li>
|
|
232
|
+
<li>运行 <code>npm install</code> 安装所有依赖</li>
|
|
233
|
+
<li>运行 <code>npm run dev</code> 启动完整应用</li>
|
|
234
|
+
<li>访问 <code>http://localhost:5173</code> 使用前端界面</li>
|
|
235
|
+
</ol>
|
|
236
|
+
</div>
|
|
237
|
+
|
|
238
|
+
<div class="footer">
|
|
239
|
+
<p>CollabDocChat v2.4.8 | MIT License</p>
|
|
240
|
+
<p><a href="https://github.com/shijinghao/collabdocchat" class="api-link" target="_blank">GitHub</a> |
|
|
241
|
+
<a href="https://www.npmjs.com/package/collabdocchat" class="api-link" target="_blank">NPM</a></p>
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
</body>
|
|
245
|
+
</html>
|
|
246
|
+
|