collabdocchat 1.2.6 → 1.2.8

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.
@@ -0,0 +1,124 @@
1
+ # 贡献指南
2
+
3
+ 感谢你考虑为 CollabDocChat 做出贡献!
4
+
5
+ ## 如何贡献
6
+
7
+ ### 报告 Bug
8
+
9
+ 如果你发现了 bug,请创建一个 issue 并包含以下信息:
10
+
11
+ - Bug 的详细描述
12
+ - 复现步骤
13
+ - 预期行为
14
+ - 实际行为
15
+ - 截图(如果适用)
16
+ - 环境信息(操作系统、Node.js 版本等)
17
+
18
+ ### 提出新功能
19
+
20
+ 如果你有新功能的想法:
21
+
22
+ 1. 先检查 issues 中是否已有类似建议
23
+ 2. 创建一个新的 issue,标记为 "enhancement"
24
+ 3. 详细描述功能需求和使用场景
25
+ 4. 等待社区讨论和反馈
26
+
27
+ ### 提交代码
28
+
29
+ 1. **Fork 项目**
30
+ ```bash
31
+ git clone https://github.com/yourusername/collabdocchat.git
32
+ cd collabdocchat
33
+ ```
34
+
35
+ 2. **创建分支**
36
+ ```bash
37
+ git checkout -b feature/your-feature-name
38
+ ```
39
+
40
+ 3. **编写代码**
41
+ - 遵循项目的代码风格
42
+ - 添加必要的注释
43
+ - 确保代码可以正常运行
44
+
45
+ 4. **测试**
46
+ ```bash
47
+ npm run dev
48
+ # 测试你的更改
49
+ ```
50
+
51
+ 5. **提交更改**
52
+ ```bash
53
+ git add .
54
+ git commit -m "feat: 添加某某功能"
55
+ ```
56
+
57
+ 提交信息格式:
58
+ - `feat:` 新功能
59
+ - `fix:` 修复 bug
60
+ - `docs:` 文档更新
61
+ - `style:` 代码格式调整
62
+ - `refactor:` 代码重构
63
+ - `test:` 测试相关
64
+ - `chore:` 构建/工具相关
65
+
66
+ 6. **推送到 GitHub**
67
+ ```bash
68
+ git push origin feature/your-feature-name
69
+ ```
70
+
71
+ 7. **创建 Pull Request**
72
+ - 在 GitHub 上创建 PR
73
+ - 详细描述你的更改
74
+ - 关联相关的 issue
75
+
76
+ ## 代码规范
77
+
78
+ ### JavaScript 风格
79
+
80
+ - 使用 ES6+ 语法
81
+ - 使用 2 空格缩进
82
+ - 使用单引号
83
+ - 函数和变量使用驼峰命名
84
+ - 常量使用大写下划线命名
85
+
86
+ ### 文件组织
87
+
88
+ - 每个文件只导出一个主要功能
89
+ - 相关功能放在同一目录
90
+ - 使用清晰的文件命名
91
+
92
+ ### 注释
93
+
94
+ - 为复杂逻辑添加注释
95
+ - 使用 JSDoc 格式注释函数
96
+ - 保持注释简洁明了
97
+
98
+ ## 开发流程
99
+
100
+ 1. 在本地开发和测试
101
+ 2. 确保代码符合规范
102
+ 3. 提交 PR 前先 pull 最新代码
103
+ 4. 等待代码审查
104
+ 5. 根据反馈修改代码
105
+ 6. 合并到主分支
106
+
107
+ ## 社区准则
108
+
109
+ - 尊重所有贡献者
110
+ - 保持友好和专业
111
+ - 接受建设性批评
112
+ - 帮助新手贡献者
113
+
114
+ ## 问题?
115
+
116
+ 如有任何问题,请:
117
+ - 查看 [README.md](README.md)
118
+ - 搜索现有 issues
119
+ - 创建新的 issue
120
+ - 发送邮件至 your.email@example.com
121
+
122
+ 再次感谢你的贡献!🎉
123
+
124
+
@@ -0,0 +1,345 @@
1
+ # CollabDocChat 安装指南
2
+
3
+ ## 📦 安装方式
4
+
5
+ ### 方式一:本地安装(推荐)
6
+
7
+ 这是最简单且最可靠的安装方式:
8
+
9
+ ```bash
10
+ # 1. 创建项目目录
11
+ mkdir my-collab-project
12
+ cd my-collab-project
13
+
14
+ # 2. 初始化 npm 项目
15
+ npm init -y
16
+
17
+ # 3. 安装 CollabDocChat
18
+ npm install collabdocchat
19
+
20
+ # 4. 进入安装目录
21
+ cd node_modules/collabdocchat
22
+
23
+ # 5. 启动应用
24
+ npm start
25
+ ```
26
+
27
+ ### 方式二:克隆仓库
28
+
29
+ 适合开发者和需要自定义的用户:
30
+
31
+ ```bash
32
+ # 1. 克隆项目
33
+ git clone https://github.com/shijinghao/collabdocchat.git
34
+ cd collabdocchat
35
+
36
+ # 2. 安装依赖
37
+ npm install
38
+
39
+ # 3. 启动应用
40
+ npm start
41
+ ```
42
+
43
+ ### 方式三:使用安装脚本
44
+
45
+ #### Windows 用户
46
+
47
+ 1. 下载 `install-and-start.bat`
48
+ 2. 双击运行或在命令行中执行:
49
+ ```cmd
50
+ install-and-start.bat
51
+ ```
52
+
53
+ #### Linux/Mac 用户
54
+
55
+ 1. 下载 `install-and-start.sh`
56
+ 2. 添加执行权限并运行:
57
+ ```bash
58
+ chmod +x install-and-start.sh
59
+ ./install-and-start.sh
60
+ ```
61
+
62
+ ## 🔧 环境要求
63
+
64
+ ### 必需软件
65
+
66
+ 1. **Node.js** (>= 16.0.0)
67
+ - 下载地址: https://nodejs.org/
68
+ - 验证安装: `node --version`
69
+
70
+ 2. **npm** (>= 7.0.0)
71
+ - 通常随 Node.js 一起安装
72
+ - 验证安装: `npm --version`
73
+
74
+ 3. **MongoDB** (>= 4.4)
75
+ - 下载地址: https://www.mongodb.com/try/download/community
76
+ - 验证安装: `mongod --version`
77
+
78
+ ### MongoDB 安装指南
79
+
80
+ #### Windows
81
+
82
+ 1. 下载 MongoDB Community Server
83
+ 2. 运行安装程序,选择"Complete"安装
84
+ 3. 安装 MongoDB Compass (可选的图形界面)
85
+ 4. 启动 MongoDB 服务:
86
+ ```cmd
87
+ net start MongoDB
88
+ ```
89
+
90
+ #### Mac (使用 Homebrew)
91
+
92
+ ```bash
93
+ # 安装 MongoDB
94
+ brew tap mongodb/brew
95
+ brew install mongodb-community
96
+
97
+ # 启动 MongoDB
98
+ brew services start mongodb-community
99
+ ```
100
+
101
+ #### Linux (Ubuntu/Debian)
102
+
103
+ ```bash
104
+ # 导入公钥
105
+ wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | sudo apt-key add -
106
+
107
+ # 添加源
108
+ echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/6.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list
109
+
110
+ # 安装
111
+ sudo apt-get update
112
+ sudo apt-get install -y mongodb-org
113
+
114
+ # 启动服务
115
+ sudo systemctl start mongod
116
+ sudo systemctl enable mongod
117
+ ```
118
+
119
+ ## ⚙️ 配置
120
+
121
+ ### 首次运行
122
+
123
+ 首次运行时,应用会自动创建配置文件。您也可以手动创建 `.env` 文件:
124
+
125
+ ```env
126
+ # 服务器配置
127
+ PORT=3000
128
+ NODE_ENV=development
129
+
130
+ # MongoDB 配置
131
+ MONGODB_URI=mongodb://localhost:27017/collabdocchat
132
+
133
+ # JWT 配置
134
+ JWT_SECRET=your-secret-key-change-this-in-production
135
+ JWT_EXPIRES_IN=7d
136
+
137
+ # 管理员账号(首次启动时创建)
138
+ ADMIN_USERNAME=admin
139
+ ADMIN_PASSWORD=admin123
140
+ ADMIN_EMAIL=admin@example.com
141
+ ```
142
+
143
+ ### 配置说明
144
+
145
+ - **PORT**: 服务器端口,默认 3000
146
+ - **MONGODB_URI**: MongoDB 连接字符串
147
+ - **JWT_SECRET**: JWT 密钥,生产环境请务必修改
148
+ - **JWT_EXPIRES_IN**: Token 过期时间
149
+ - **ADMIN_USERNAME/PASSWORD**: 默认管理员账号
150
+
151
+ ## 🚀 启动应用
152
+
153
+ ### 开发模式
154
+
155
+ ```bash
156
+ npm run dev
157
+ ```
158
+
159
+ 特点:
160
+ - 自动重启服务器
161
+ - 热重载前端
162
+ - 自动打开浏览器
163
+
164
+ ### 生产模式
165
+
166
+ ```bash
167
+ npm start
168
+ ```
169
+
170
+ ### 快速启动
171
+
172
+ ```bash
173
+ npm run quick-start
174
+ ```
175
+
176
+ 自动配置并启动应用。
177
+
178
+ ## 🔍 验证安装
179
+
180
+ ### 1. 检查服务器
181
+
182
+ 访问: http://localhost:3000
183
+
184
+ 应该看到登录页面。
185
+
186
+ ### 2. 检查客户端
187
+
188
+ 访问: http://localhost:5173
189
+
190
+ 应该看到应用界面。
191
+
192
+ ### 3. 登录测试
193
+
194
+ 使用默认管理员账号登录:
195
+ - 用户名: `admin`
196
+ - 密码: `admin123`
197
+
198
+ ## ❌ 常见问题
199
+
200
+ ### 问题 1: MongoDB 连接失败
201
+
202
+ **错误信息**: `MongoNetworkError: connect ECONNREFUSED`
203
+
204
+ **解决方案**:
205
+ 1. 确认 MongoDB 服务已启动
206
+ 2. 检查 `.env` 中的 `MONGODB_URI` 配置
207
+ 3. 验证 MongoDB 端口 (默认 27017)
208
+
209
+ ```bash
210
+ # Windows
211
+ net start MongoDB
212
+
213
+ # Mac
214
+ brew services start mongodb-community
215
+
216
+ # Linux
217
+ sudo systemctl start mongod
218
+ ```
219
+
220
+ ### 问题 2: 端口被占用
221
+
222
+ **错误信息**: `Error: listen EADDRINUSE: address already in use :::3000`
223
+
224
+ **解决方案**:
225
+ 1. 更改 `.env` 中的 `PORT` 配置
226
+ 2. 或者停止占用端口的进程
227
+
228
+ ```bash
229
+ # Windows - 查找并结束进程
230
+ netstat -ano | findstr :3000
231
+ taskkill /PID <进程ID> /F
232
+
233
+ # Mac/Linux
234
+ lsof -ti:3000 | xargs kill -9
235
+ ```
236
+
237
+ ### 问题 3: npm 依赖安装失败
238
+
239
+ **解决方案**:
240
+ ```bash
241
+ # 清除缓存
242
+ npm cache clean --force
243
+
244
+ # 删除 node_modules
245
+ rm -rf node_modules package-lock.json
246
+
247
+ # 重新安装
248
+ npm install
249
+ ```
250
+
251
+ ### 问题 4: Node.js 版本过低
252
+
253
+ **错误信息**: `Error: The engine "node" is incompatible`
254
+
255
+ **解决方案**:
256
+ 升级 Node.js 到 16.0.0 或更高版本。
257
+
258
+ ## 🛑 停止应用
259
+
260
+ ### 方法一:使用脚本
261
+
262
+ ```bash
263
+ npm run stop
264
+ ```
265
+
266
+ ### 方法二:手动停止
267
+
268
+ 在运行应用的终端按 `Ctrl + C`
269
+
270
+ ### 方法三:结束进程
271
+
272
+ ```bash
273
+ # Windows
274
+ taskkill /F /IM node.exe
275
+
276
+ # Mac/Linux
277
+ pkill -f node
278
+ ```
279
+
280
+ ## 📊 性能优化
281
+
282
+ ### 生产环境建议
283
+
284
+ 1. **使用 PM2 管理进程**:
285
+ ```bash
286
+ npm install -g pm2
287
+ pm2 start server/index.js --name collabdocchat
288
+ pm2 startup
289
+ pm2 save
290
+ ```
291
+
292
+ 2. **配置反向代理** (Nginx):
293
+ ```nginx
294
+ server {
295
+ listen 80;
296
+ server_name your-domain.com;
297
+
298
+ location / {
299
+ proxy_pass http://localhost:3000;
300
+ proxy_http_version 1.1;
301
+ proxy_set_header Upgrade $http_upgrade;
302
+ proxy_set_header Connection 'upgrade';
303
+ proxy_set_header Host $host;
304
+ proxy_cache_bypass $http_upgrade;
305
+ }
306
+ }
307
+ ```
308
+
309
+ 3. **启用 MongoDB 认证**:
310
+ ```javascript
311
+ // .env
312
+ MONGODB_URI=mongodb://username:password@localhost:27017/collabdocchat?authSource=admin
313
+ ```
314
+
315
+ ## 🔐 安全建议
316
+
317
+ 1. **修改默认管理员密码**
318
+ 2. **使用强 JWT 密钥**
319
+ 3. **启用 HTTPS**
320
+ 4. **配置防火墙规则**
321
+ 5. **定期更新依赖包**
322
+
323
+ ```bash
324
+ npm audit
325
+ npm audit fix
326
+ ```
327
+
328
+ ## 📞 获取帮助
329
+
330
+ 如果遇到问题:
331
+
332
+ 1. 查看 [GitHub Issues](https://github.com/shijinghao/collabdocchat/issues)
333
+ 2. 阅读 [完整文档](https://github.com/shijinghao/collabdocchat#readme)
334
+ 3. 提交新的 Issue
335
+
336
+ ## 🎉 安装成功!
337
+
338
+ 现在您可以:
339
+ - 创建文档并邀请团队成员协作
340
+ - 使用实时聊天功能
341
+ - 管理任务和项目
342
+ - 探索更多功能
343
+
344
+ 祝您使用愉快!🚀
345
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "collabdocchat",
3
- "version": "1.2.6",
3
+ "version": "1.2.8",
4
4
  "description": "开源的实时协作文档聊天平台 - 集成任务管理、多人文档编辑、智能点名功能",
5
5
  "main": "./server/index.js",
6
6
  "type": "module",
@@ -20,7 +20,9 @@
20
20
  ".gitignore",
21
21
  "install-and-start.bat",
22
22
  "install-and-start.sh",
23
- "QUICK_START.md"
23
+ "QUICK_START.md",
24
+ "INSTALLATION.md",
25
+ "CONTRIBUTING.md"
24
26
  ],
25
27
  "keywords": [
26
28
  "collaboration",
@@ -1,186 +1,57 @@
1
- import { spawn } from 'child_process';
2
- import { platform } from 'os';
3
1
  import { fileURLToPath } from 'url';
4
2
  import { dirname, join } from 'path';
5
- import { writeFileSync, existsSync, readFileSync } from 'fs';
3
+ import { writeFileSync, existsSync } from 'fs';
6
4
 
7
5
  const __filename = fileURLToPath(import.meta.url);
8
6
  const __dirname = dirname(__filename);
9
7
  const rootDir = join(__dirname, '..');
10
8
 
11
- const PORT = process.env.PORT || 3000;
12
- const CLIENT_PORT = 5173;
13
- const CLIENT_URL = `http://localhost:${CLIENT_PORT}`;
14
- const pidFile = join(rootDir, '.collabdocchat.pid');
15
- const isWindows = platform() === 'win32';
16
-
17
- // 保存 PID 到文件
18
- function savePid(pid) {
19
- try {
20
- let pids = [];
21
- if (existsSync(pidFile)) {
22
- const content = readFileSync(pidFile, 'utf-8');
23
- pids = content.trim().split('\n').filter(Boolean);
24
- }
25
- if (!pids.includes(pid.toString())) {
26
- pids.push(pid.toString());
27
- writeFileSync(pidFile, pids.join('\n') + '\n');
28
- }
29
- } catch (error) {
30
- // 忽略错误
31
- }
32
- }
33
-
34
- // 打开浏览器的函数
35
- function openBrowser(url) {
36
- const platformName = platform();
37
- let command;
38
- let args;
39
-
40
- switch (platformName) {
41
- case 'win32':
42
- command = 'cmd';
43
- args = ['/c', 'start', url];
44
- break;
45
- case 'darwin':
46
- command = 'open';
47
- args = [url];
48
- break;
49
- default:
50
- command = 'xdg-open';
51
- args = [url];
52
- }
53
-
54
- const browser = spawn(command, args, { stdio: 'ignore', detached: true });
55
- browser.unref();
56
- }
57
-
58
- // 检查服务器是否就绪
59
- function waitForServer(url, maxAttempts = 30, delay = 1000) {
60
- return new Promise((resolve, reject) => {
61
- let attempts = 0;
62
- const urlObj = new URL(url);
63
-
64
- const check = () => {
65
- attempts++;
66
-
67
- const req = http.get({
68
- hostname: urlObj.hostname,
69
- port: urlObj.port,
70
- path: urlObj.pathname,
71
- timeout: 1000
72
- }, (res) => {
73
- if (res.statusCode === 200) {
74
- resolve();
75
- return;
76
- }
77
- if (attempts < maxAttempts) {
78
- setTimeout(check, delay);
79
- } else {
80
- reject(new Error('服务器启动超时'));
81
- }
82
- });
83
-
84
- req.on('error', () => {
85
- if (attempts < maxAttempts) {
86
- setTimeout(check, delay);
87
- } else {
88
- reject(new Error('服务器启动超时'));
89
- }
90
- });
91
-
92
- req.on('timeout', () => {
93
- req.destroy();
94
- if (attempts < maxAttempts) {
95
- setTimeout(check, delay);
96
- } else {
97
- reject(new Error('服务器启动超时'));
98
- }
99
- });
100
- };
101
-
102
- check();
103
- });
104
- }
105
-
106
- // 启动服务器
107
- function startServer() {
108
- console.log('\n🚀 正在启动 CollabDocChat 服务器...');
109
- const server = spawn('node', ['server/index.js'], {
110
- cwd: rootDir,
111
- stdio: 'inherit',
112
- detached: true,
113
- windowsHide: true
114
- });
115
-
116
- // 保存服务器进程 PID
117
- if (server.pid) {
118
- savePid(server.pid);
119
- }
120
-
121
- server.unref();
122
- return server;
123
- }
124
-
125
- // 启动客户端
126
- function startClient() {
127
- console.log('🎨 正在启动客户端...');
128
- const client = spawn(isWindows ? 'npm.cmd' : 'npm', ['run', 'client'], {
129
- cwd: rootDir,
130
- stdio: 'inherit',
131
- detached: true,
132
- windowsHide: true
133
- });
134
-
135
- // 保存客户端进程 PID(注意:npm 会启动子进程,这里保存的是 npm 进程的 PID)
136
- if (client.pid) {
137
- savePid(client.pid);
138
- }
139
-
140
- client.unref();
141
- return client;
142
- }
143
-
144
- // 主函数 - 完全异步,不阻塞
145
- function main() {
146
- console.log('\n📦 CollabDocChat 安装完成!');
147
- console.log('🚀 正在后台启动应用...\n');
148
-
149
- // 立即启动服务器(不等待)
150
- try {
151
- const server = startServer();
152
- } catch (error) {
153
- // 静默处理
154
- }
9
+ // 创建默认 .env 文件
10
+ function createEnvFile() {
11
+ const envPath = join(rootDir, '.env');
155
12
 
156
- // 立即启动客户端(不等待)
157
- try {
158
- const client = startClient();
159
- } catch (error) {
160
- // 静默处理
161
- }
162
-
163
- // 延迟打开浏览器,给服务器启动时间
164
- setTimeout(() => {
13
+ if (!existsSync(envPath)) {
14
+ const envContent = `# 服务器配置
15
+ PORT=3000
16
+ NODE_ENV=development
17
+
18
+ # MongoDB 配置
19
+ MONGODB_URI=mongodb://localhost:27017/collabdocchat
20
+
21
+ # JWT 配置
22
+ JWT_SECRET=your-secret-key-change-this-in-production-${Date.now()}
23
+ JWT_EXPIRES_IN=7d
24
+
25
+ # 管理员账号(首次启动时创建)
26
+ ADMIN_USERNAME=admin
27
+ ADMIN_PASSWORD=admin123
28
+ ADMIN_EMAIL=admin@example.com
29
+ `;
30
+
165
31
  try {
166
- console.log(`\n🌐 正在打开浏览器: ${CLIENT_URL}`);
167
- openBrowser(CLIENT_URL);
168
- console.log('\n✅ 应用正在启动中,浏览器已打开。');
169
- console.log(' 如果页面未加载,请稍等片刻后刷新页面。');
170
- console.log('\n💡 提示:服务器和客户端正在后台运行');
171
- console.log(' 要停止服务,运行: cd node_modules/collabdocchat && npm run stop');
32
+ writeFileSync(envPath, envContent);
33
+ console.log('✅ 已创建默认配置文件 .env');
172
34
  } catch (error) {
173
- // 静默处理
35
+ console.log('⚠️ 无法创建 .env 文件,请手动创建');
174
36
  }
175
- }, 8000);
37
+ }
176
38
  }
177
39
 
178
- // 立即执行
179
- main();
180
-
181
- // 延迟退出,给输出时间显示
182
- // 但不会阻塞太久
183
- setTimeout(() => {
184
- process.exit(0);
185
- }, 2000);
186
-
40
+ console.log('\n🎉 CollabDocChat 安装成功!\n');
41
+ console.log('📦 开源的实时协作文档聊天平台\n');
42
+
43
+ // 创建配置文件
44
+ createEnvFile();
45
+
46
+ console.log('\n📖 快速开始:\n');
47
+ console.log(' 1. 确保 MongoDB 已安装并运行');
48
+ console.log(' 2. 安装开发依赖: npm install');
49
+ console.log(' 3. 启动应用: npm start');
50
+ console.log('\n💡 更多信息:');
51
+ console.log(' • 查看 README.md 了解详细说明');
52
+ console.log(' • 查看 INSTALLATION.md 了解安装指南');
53
+ console.log(' • 默认管理员账号: admin / admin123');
54
+ console.log('\n🔗 文档链接:');
55
+ console.log(' • GitHub: https://github.com/shijinghao/collabdocchat');
56
+ console.log(' • npm: https://www.npmjs.com/package/collabdocchat');
57
+ console.log('\n');
@@ -1,8 +1,9 @@
1
- import { spawn } from 'child_process';
1
+ import { spawn, exec } from 'child_process';
2
2
  import { platform } from 'os';
3
3
  import { fileURLToPath } from 'url';
4
4
  import { dirname, join } from 'path';
5
5
  import http from 'http';
6
+ import { existsSync } from 'fs';
6
7
 
7
8
  const __filename = fileURLToPath(import.meta.url);
8
9
  const __dirname = dirname(__filename);
@@ -11,29 +12,92 @@ const rootDir = join(__dirname, '..');
11
12
  const PORT = process.env.PORT || 3000;
12
13
  const CLIENT_PORT = 5173;
13
14
  const CLIENT_URL = `http://localhost:${CLIENT_PORT}`;
15
+ const isWindows = platform() === 'win32';
16
+
17
+ // 检查 devDependencies 是否已安装
18
+ function checkDevDependencies() {
19
+ const vitePath = join(rootDir, 'node_modules', 'vite');
20
+ return existsSync(vitePath);
21
+ }
22
+
23
+ // 安装 devDependencies
24
+ function installDevDependencies() {
25
+ return new Promise((resolve, reject) => {
26
+ console.log('📦 正在安装开发依赖...\n');
27
+
28
+ const npmCmd = isWindows ? 'npm.cmd' : 'npm';
29
+ const install = spawn(npmCmd, ['install'], {
30
+ cwd: rootDir,
31
+ stdio: 'inherit',
32
+ shell: true
33
+ });
34
+
35
+ install.on('close', (code) => {
36
+ if (code === 0) {
37
+ console.log('\n✅ 依赖安装完成\n');
38
+ resolve();
39
+ } else {
40
+ reject(new Error(`依赖安装失败,退出码: ${code}`));
41
+ }
42
+ });
43
+
44
+ install.on('error', (error) => {
45
+ reject(error);
46
+ });
47
+ });
48
+ }
49
+
50
+ // 检查端口是否被占用
51
+ function checkPort(port) {
52
+ return new Promise((resolve) => {
53
+ const server = http.createServer();
54
+
55
+ server.once('error', (err) => {
56
+ if (err.code === 'EADDRINUSE') {
57
+ resolve(false); // 端口被占用
58
+ } else {
59
+ resolve(true);
60
+ }
61
+ });
62
+
63
+ server.once('listening', () => {
64
+ server.close();
65
+ resolve(true); // 端口可用
66
+ });
67
+
68
+ server.listen(port);
69
+ });
70
+ }
14
71
 
15
72
  // 打开浏览器的函数
16
73
  function openBrowser(url) {
17
- const platformName = platform();
18
- let command;
19
- let args;
20
-
21
- switch (platformName) {
22
- case 'win32':
23
- command = 'cmd';
24
- args = ['/c', 'start', url];
25
- break;
26
- case 'darwin':
27
- command = 'open';
28
- args = [url];
29
- break;
30
- default:
31
- command = 'xdg-open';
32
- args = [url];
33
- }
74
+ try {
75
+ const platformName = platform();
76
+ let command, args;
77
+
78
+ switch (platformName) {
79
+ case 'win32':
80
+ command = 'cmd';
81
+ args = ['/c', 'start', '""', url];
82
+ break;
83
+ case 'darwin':
84
+ command = 'open';
85
+ args = [url];
86
+ break;
87
+ default:
88
+ command = 'xdg-open';
89
+ args = [url];
90
+ }
34
91
 
35
- const browser = spawn(command, args, { stdio: 'ignore', detached: true });
36
- browser.unref();
92
+ const browser = spawn(command, args, {
93
+ stdio: 'ignore',
94
+ detached: true,
95
+ shell: true
96
+ });
97
+ browser.unref();
98
+ } catch (error) {
99
+ console.log(`⚠️ 无法自动打开浏览器,请手动访问: ${url}`);
100
+ }
37
101
  }
38
102
 
39
103
  // 检查服务器是否就绪
@@ -48,23 +112,13 @@ function waitForServer(url, maxAttempts = 30, delay = 1000) {
48
112
  const req = http.get({
49
113
  hostname: urlObj.hostname,
50
114
  port: urlObj.port,
51
- path: urlObj.pathname,
115
+ path: '/',
52
116
  timeout: 1000
53
117
  }, (res) => {
54
- if (res.statusCode === 200) {
55
- resolve();
56
- return;
57
- }
58
- // 继续等待
59
- if (attempts < maxAttempts) {
60
- setTimeout(check, delay);
61
- } else {
62
- reject(new Error('服务器启动超时'));
63
- }
118
+ resolve();
64
119
  });
65
120
 
66
121
  req.on('error', () => {
67
- // 服务器未就绪,继续等待
68
122
  if (attempts < maxAttempts) {
69
123
  setTimeout(check, delay);
70
124
  } else {
@@ -98,10 +152,11 @@ function startServer() {
98
152
  return server;
99
153
  }
100
154
 
101
- // 启动客户端(如果使用 Vite)
155
+ // 启动客户端
102
156
  function startClient() {
103
- console.log('🎨 正在启动客户端...');
104
- const client = spawn('npm', ['run', 'client'], {
157
+ console.log('🎨 正在启动客户端...\n');
158
+ const npmCmd = isWindows ? 'npm.cmd' : 'npm';
159
+ const client = spawn(npmCmd, ['run', 'client'], {
105
160
  cwd: rootDir,
106
161
  stdio: 'inherit',
107
162
  shell: true
@@ -114,12 +169,36 @@ function startClient() {
114
169
  async function main() {
115
170
  console.log('📦 CollabDocChat 正在启动...\n');
116
171
 
172
+ // 检查端口
173
+ const portAvailable = await checkPort(PORT);
174
+ if (!portAvailable) {
175
+ console.error(`❌ 错误:端口 ${PORT} 已被占用`);
176
+ console.error('\n💡 解决方案:');
177
+ console.error(' 1. 停止占用端口的进程: npm run stop');
178
+ console.error(' 2. 或修改 .env 文件中的 PORT 配置');
179
+ console.error(' 3. Windows: netstat -ano | findstr :3000');
180
+ console.error(' 然后: taskkill /PID <进程ID> /F\n');
181
+ process.exit(1);
182
+ }
183
+
184
+ // 检查并安装 devDependencies
185
+ if (!checkDevDependencies()) {
186
+ console.log('⚠️ 检测到缺少开发依赖\n');
187
+ try {
188
+ await installDevDependencies();
189
+ } catch (error) {
190
+ console.error('❌ 依赖安装失败:', error.message);
191
+ console.error('\n💡 请手动运行: npm install\n');
192
+ process.exit(1);
193
+ }
194
+ }
195
+
117
196
  // 启动服务器
118
197
  const server = startServer();
119
198
 
120
199
  // 等待服务器就绪
121
200
  try {
122
- await waitForServer(`http://localhost:${PORT}/health`, 30, 1000);
201
+ await waitForServer(`http://localhost:${PORT}`, 30, 1000);
123
202
  console.log(`✅ 服务器已就绪: http://localhost:${PORT}\n`);
124
203
  } catch (error) {
125
204
  console.error('❌ 服务器启动失败:', error.message);
@@ -135,12 +214,17 @@ async function main() {
135
214
  await waitForServer(CLIENT_URL, 20, 500);
136
215
  console.log(`\n🌐 正在打开浏览器: ${CLIENT_URL}`);
137
216
  openBrowser(CLIENT_URL);
217
+ console.log('\n✅ 应用启动成功!');
218
+ console.log('\n💡 提示:');
219
+ console.log(' • 服务器: http://localhost:3000');
220
+ console.log(' • 客户端: http://localhost:5173');
221
+ console.log(' • 默认账号: admin / admin123');
222
+ console.log('\n⚠️ 按 Ctrl+C 停止服务\n');
138
223
  } catch (error) {
139
224
  console.log(`\n⚠️ 客户端可能还在启动中,请手动访问: ${CLIENT_URL}`);
140
- // 即使检查失败也尝试打开浏览器
141
225
  openBrowser(CLIENT_URL);
142
226
  }
143
- }, 2000);
227
+ }, 3000);
144
228
 
145
229
  // 处理退出信号
146
230
  process.on('SIGINT', () => {
@@ -161,4 +245,3 @@ main().catch(error => {
161
245
  console.error('❌ 启动失败:', error);
162
246
  process.exit(1);
163
247
  });
164
-