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.
- package/CONTRIBUTING.md +124 -0
- package/INSTALLATION.md +345 -0
- package/package.json +4 -2
- package/scripts/postinstall.js +44 -173
- package/scripts/start-app.js +122 -39
package/CONTRIBUTING.md
ADDED
|
@@ -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
|
+
|
package/INSTALLATION.md
ADDED
|
@@ -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.
|
|
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",
|
package/scripts/postinstall.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
-
|
|
167
|
-
|
|
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
|
-
}
|
|
37
|
+
}
|
|
176
38
|
}
|
|
177
39
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
//
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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');
|
package/scripts/start-app.js
CHANGED
|
@@ -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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
36
|
-
|
|
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:
|
|
115
|
+
path: '/',
|
|
52
116
|
timeout: 1000
|
|
53
117
|
}, (res) => {
|
|
54
|
-
|
|
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
|
-
//
|
|
155
|
+
// 启动客户端
|
|
102
156
|
function startClient() {
|
|
103
|
-
console.log('🎨
|
|
104
|
-
const
|
|
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}
|
|
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
|
-
},
|
|
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
|
-
|