modernx-gui 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +237 -0
- package/bin/modernx-gui +33 -0
- package/bin/modernx-gui-dev +326 -0
- package/bin/modernx-gui-simple +195 -0
- package/dist/index.js +1 -0
- package/package.json +57 -0
- package/src/components/ModernXGUI.js +126 -0
- package/src/index.js +10 -0
- package/src/lib/browser-compatibility.js +82 -0
- package/src/lib/browser.js +17 -0
- package/src/lib/hot-reloader.js +105 -0
- package/src/lib/project-detector.js +67 -0
- package/src/lib/server.js +59 -0
- package/src/lib/state-synchronizer.js +67 -0
package/README.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# ModernX GUI
|
|
2
|
+
|
|
3
|
+
Development GUI with real-time visualization for ModernX applications, providing comprehensive debugging and state inspection capabilities.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Real-time Visualization**: Live display of Redux state and actions
|
|
8
|
+
- **Project Structure Analysis**: Automatic detection and visualization of ModernX models
|
|
9
|
+
- **WebSocket Communication**: Real-time data synchronization between app and GUI
|
|
10
|
+
- **Action History**: Complete history of Redux actions with timestamps and payloads
|
|
11
|
+
- **State Inspector**: Visual tree view of application state
|
|
12
|
+
- **Hot Module Replacement**: Automatic GUI updates during development
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install modernx-gui --save-dev
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Command Line Interface
|
|
23
|
+
|
|
24
|
+
Start the GUI from any ModernX project directory:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx modernx-gui
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This will:
|
|
31
|
+
1. Automatically detect your ModernX project structure
|
|
32
|
+
2. Start a local development server
|
|
33
|
+
3. Open your default browser to the GUI interface
|
|
34
|
+
4. Begin real-time state monitoring
|
|
35
|
+
|
|
36
|
+
### Programmatic Integration
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
import modernx from 'modernx';
|
|
40
|
+
import gui from 'modernx-gui';
|
|
41
|
+
|
|
42
|
+
const app = modernx({
|
|
43
|
+
plugins: [
|
|
44
|
+
gui({
|
|
45
|
+
port: 3000,
|
|
46
|
+
autoOpen: true,
|
|
47
|
+
websocket: true,
|
|
48
|
+
}),
|
|
49
|
+
],
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### CLI Integration
|
|
54
|
+
|
|
55
|
+
When creating a new ModernX project, you can include the GUI automatically:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npx modernx create my-app --tools gui
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## GUI Interface
|
|
62
|
+
|
|
63
|
+
### Project Structure Panel
|
|
64
|
+
|
|
65
|
+
- **Models List**: Displays all detected ModernX models
|
|
66
|
+
- **File Tree**: Shows project structure and relationships
|
|
67
|
+
- **Configuration**: Shows current ModernX configuration
|
|
68
|
+
|
|
69
|
+
### State Viewer
|
|
70
|
+
|
|
71
|
+
- **Current State**: Real-time display of application state
|
|
72
|
+
- **State Tree**: Expandable tree view of nested state
|
|
73
|
+
- **State Diff**: Visual diff between state changes
|
|
74
|
+
|
|
75
|
+
### Action History
|
|
76
|
+
|
|
77
|
+
- **Action Timeline**: Chronological list of all actions
|
|
78
|
+
- **Action Details**: Payload, timestamp, and metadata
|
|
79
|
+
- **State Transitions**: Visual representation of state changes
|
|
80
|
+
|
|
81
|
+
### Real-time Monitoring
|
|
82
|
+
|
|
83
|
+
- **Live Updates**: Automatic state and action updates
|
|
84
|
+
- **Performance Metrics**: Action execution time and performance
|
|
85
|
+
- **Error Tracking**: Visual error reporting and stack traces
|
|
86
|
+
|
|
87
|
+
## Configuration Options
|
|
88
|
+
|
|
89
|
+
| Option | Type | Default | Description |
|
|
90
|
+
|--------|------|---------|-------------|
|
|
91
|
+
| `port` | number | `3000` | GUI server port |
|
|
92
|
+
| `autoOpen` | boolean | `true` | Auto-open browser |
|
|
93
|
+
| `websocket` | boolean | `true` | Enable WebSocket communication |
|
|
94
|
+
| `host` | string | `'localhost'` | GUI server host |
|
|
95
|
+
|
|
96
|
+
### Example Configuration
|
|
97
|
+
|
|
98
|
+
```javascript
|
|
99
|
+
gui({
|
|
100
|
+
port: 3001,
|
|
101
|
+
autoOpen: false,
|
|
102
|
+
websocket: true,
|
|
103
|
+
host: '0.0.0.0', // Allow remote connections
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Development Workflow
|
|
108
|
+
|
|
109
|
+
### 1. Start Development Server
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
cd my-modernx-app
|
|
113
|
+
npx modernx-gui
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 2. Start Your Application
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npm run dev
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 3. Open GUI Interface
|
|
123
|
+
|
|
124
|
+
The GUI will automatically:
|
|
125
|
+
- Detect your running ModernX application
|
|
126
|
+
- Connect via WebSocket for real-time updates
|
|
127
|
+
- Display current state and action history
|
|
128
|
+
|
|
129
|
+
### 4. Monitor and Debug
|
|
130
|
+
|
|
131
|
+
Use the GUI interface to:
|
|
132
|
+
- Inspect current application state
|
|
133
|
+
- Review action history and payloads
|
|
134
|
+
- Monitor performance metrics
|
|
135
|
+
- Track state changes in real-time
|
|
136
|
+
|
|
137
|
+
## WebSocket Protocol
|
|
138
|
+
|
|
139
|
+
The GUI communicates with your application via WebSocket:
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
// Send state update to GUI
|
|
143
|
+
ws.send(JSON.stringify({
|
|
144
|
+
type: 'state_update',
|
|
145
|
+
payload: newState,
|
|
146
|
+
timestamp: Date.now(),
|
|
147
|
+
}));
|
|
148
|
+
|
|
149
|
+
// Send action to GUI
|
|
150
|
+
ws.send(JSON.stringify({
|
|
151
|
+
type: 'action',
|
|
152
|
+
payload: {
|
|
153
|
+
type: 'USER_ACTION',
|
|
154
|
+
payload: actionData,
|
|
155
|
+
},
|
|
156
|
+
timestamp: Date.now(),
|
|
157
|
+
}));
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Migration from DVA GUI
|
|
161
|
+
|
|
162
|
+
If you're migrating from DVA, the ModernX GUI provides enhanced capabilities:
|
|
163
|
+
|
|
164
|
+
```javascript
|
|
165
|
+
// DVA GUI (Electron-based)
|
|
166
|
+
import dva from 'dva';
|
|
167
|
+
import gui from 'dva-gui';
|
|
168
|
+
|
|
169
|
+
// ModernX GUI (Web-based, enhanced)
|
|
170
|
+
import modernx from 'modernx';
|
|
171
|
+
import gui from 'modernx-gui';
|
|
172
|
+
|
|
173
|
+
// Enhanced features:
|
|
174
|
+
// - WebSocket real-time communication
|
|
175
|
+
// - Cross-browser compatibility
|
|
176
|
+
// - Hot module replacement
|
|
177
|
+
// - Enhanced state visualization
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Browser Compatibility
|
|
181
|
+
|
|
182
|
+
- **Chrome**: Full support
|
|
183
|
+
- **Firefox**: Full support
|
|
184
|
+
- **Safari**: Full support
|
|
185
|
+
- **Edge**: Full support
|
|
186
|
+
- **Legacy browsers**: Graceful degradation
|
|
187
|
+
|
|
188
|
+
## Development
|
|
189
|
+
|
|
190
|
+
### Building
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
npm run build
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Development Mode
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
npm run dev
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Testing
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
npm test
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Troubleshooting
|
|
209
|
+
|
|
210
|
+
### Common Issues
|
|
211
|
+
|
|
212
|
+
1. **GUI not connecting**
|
|
213
|
+
- Check if WebSocket is enabled
|
|
214
|
+
- Verify port availability
|
|
215
|
+
- Check firewall settings
|
|
216
|
+
|
|
217
|
+
2. **Project not detected**
|
|
218
|
+
- Ensure `package.json` has ModernX dependency
|
|
219
|
+
- Check for `src/models/` directory
|
|
220
|
+
- Verify project structure
|
|
221
|
+
|
|
222
|
+
3. **Browser not opening**
|
|
223
|
+
- Check default browser settings
|
|
224
|
+
- Try manual browser navigation to GUI URL
|
|
225
|
+
- Verify port is not in use
|
|
226
|
+
|
|
227
|
+
### Debug Mode
|
|
228
|
+
|
|
229
|
+
Enable debug logging:
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
DEBUG=modernx-gui:* npx modernx-gui
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
MIT
|
package/bin/modernx-gui
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { startServer } = require('../lib/server');
|
|
4
|
+
const { detectProject } = require('../lib/project-detector');
|
|
5
|
+
const { openBrowser } = require('../lib/browser');
|
|
6
|
+
|
|
7
|
+
async function main() {
|
|
8
|
+
try {
|
|
9
|
+
console.log('🚀 Starting ModernX GUI...');
|
|
10
|
+
|
|
11
|
+
// Detect current project structure
|
|
12
|
+
const projectInfo = await detectProject(process.cwd());
|
|
13
|
+
console.log('📁 Project detected:', projectInfo.name);
|
|
14
|
+
|
|
15
|
+
// Start development server
|
|
16
|
+
const server = await startServer({
|
|
17
|
+
port: 3000,
|
|
18
|
+
projectInfo,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
console.log(`🌐 GUI Server running at: ${server.url}`);
|
|
22
|
+
|
|
23
|
+
// Open browser automatically
|
|
24
|
+
await openBrowser(server.url);
|
|
25
|
+
console.log('✅ ModernX GUI is ready!');
|
|
26
|
+
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error('❌ Failed to start ModernX GUI:', error.message);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
main();
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ModernX GUI 开发版本启动脚本
|
|
5
|
+
* 直接使用源代码,无需构建
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const express = require('express');
|
|
9
|
+
const WebSocket = require('ws');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
|
|
13
|
+
// 直接导入源代码模块
|
|
14
|
+
const { detectProject } = require('./src/lib/project-detector.js');
|
|
15
|
+
|
|
16
|
+
async function openBrowser(url) {
|
|
17
|
+
try {
|
|
18
|
+
const { execSync } = require('child_process');
|
|
19
|
+
const platform = process.platform;
|
|
20
|
+
|
|
21
|
+
if (platform === 'darwin') {
|
|
22
|
+
execSync(`open "${url}"`);
|
|
23
|
+
} else if (platform === 'win32') {
|
|
24
|
+
execSync(`start "${url}"`);
|
|
25
|
+
} else {
|
|
26
|
+
execSync(`xdg-open "${url}"`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
console.log(`🌐 已在浏览器中打开: ${url}`);
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.warn('无法自动打开浏览器:', error.message);
|
|
32
|
+
console.log(`请手动访问: ${url}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function startServer(options = {}) {
|
|
37
|
+
const app = express();
|
|
38
|
+
const port = options.port || 3000;
|
|
39
|
+
|
|
40
|
+
// 创建一个简单的 HTML 界面(因为还没有构建前端)
|
|
41
|
+
app.get('/', (req, res) => {
|
|
42
|
+
const html = `
|
|
43
|
+
<!DOCTYPE html>
|
|
44
|
+
<html lang="zh-CN">
|
|
45
|
+
<head>
|
|
46
|
+
<meta charset="UTF-8">
|
|
47
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
48
|
+
<title>ModernX GUI - 开发版</title>
|
|
49
|
+
<style>
|
|
50
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
51
|
+
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #f5f5f5; }
|
|
52
|
+
.header { background: #2563eb; color: white; padding: 1rem; display: flex; justify-content: space-between; align-items: center; }
|
|
53
|
+
.header h1 { font-size: 1.5rem; }
|
|
54
|
+
.status { display: flex; align-items: center; gap: 0.5rem; }
|
|
55
|
+
.status-dot { width: 12px; height: 12px; border-radius: 50%; background: #10b981; }
|
|
56
|
+
.container { display: grid; grid-template-columns: 300px 1fr; height: calc(100vh - 60px); }
|
|
57
|
+
.sidebar { background: white; border-right: 1px solid #e5e7eb; padding: 1rem; overflow-y: auto; }
|
|
58
|
+
.main-content { padding: 1rem; overflow-y: auto; }
|
|
59
|
+
.card { background: white; border-radius: 8px; padding: 1rem; margin-bottom: 1rem; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
|
|
60
|
+
.card h3 { margin-bottom: 0.5rem; color: #374151; }
|
|
61
|
+
.state-display { background: #1f2937; color: #10b981; padding: 1rem; border-radius: 4px; font-family: 'Monaco', 'Consolas', monospace; font-size: 0.875rem; white-space: pre-wrap; max-height: 300px; overflow-y: auto; }
|
|
62
|
+
.action-item { background: #f9fafb; border: 1px solid #e5e7eb; border-radius: 4px; padding: 0.75rem; margin-bottom: 0.5rem; }
|
|
63
|
+
.action-type { font-weight: 600; color: #2563eb; }
|
|
64
|
+
.action-time { font-size: 0.75rem; color: #6b7280; margin-left: 0.5rem; }
|
|
65
|
+
.action-payload { background: #1f2937; color: #f3f4f6; padding: 0.5rem; border-radius: 4px; font-family: monospace; font-size: 0.75rem; margin-top: 0.5rem; white-space: pre-wrap; }
|
|
66
|
+
.models-list ul { list-style: none; }
|
|
67
|
+
.models-list li { background: #f3f4f6; padding: 0.5rem; border-radius: 4px; margin-bottom: 0.25rem; }
|
|
68
|
+
.connection-status { display: flex; align-items: center; gap: 0.5rem; }
|
|
69
|
+
.connected { color: #10b981; }
|
|
70
|
+
.disconnected { color: #ef4444; }
|
|
71
|
+
</style>
|
|
72
|
+
</head>
|
|
73
|
+
<body>
|
|
74
|
+
<header class="header">
|
|
75
|
+
<h1>🎨 ModernX GUI</h1>
|
|
76
|
+
<div class="connection-status">
|
|
77
|
+
<div class="status-dot"></div>
|
|
78
|
+
<span id="connection-status">连接中...</span>
|
|
79
|
+
</div>
|
|
80
|
+
</header>
|
|
81
|
+
|
|
82
|
+
<div class="container">
|
|
83
|
+
<aside class="sidebar">
|
|
84
|
+
<div class="card">
|
|
85
|
+
<h3>📁 项目信息</h3>
|
|
86
|
+
<div id="project-info">
|
|
87
|
+
<p>加载中...</p>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<div class="card">
|
|
92
|
+
<h3>📊 模型列表</h3>
|
|
93
|
+
<div class="models-list">
|
|
94
|
+
<ul id="models-list">
|
|
95
|
+
<li>加载中...</li>
|
|
96
|
+
</ul>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</aside>
|
|
100
|
+
|
|
101
|
+
<main class="main-content">
|
|
102
|
+
<div class="card">
|
|
103
|
+
<h3>🔄 当前状态</h3>
|
|
104
|
+
<div class="state-display" id="state-display">
|
|
105
|
+
{
|
|
106
|
+
"user": {
|
|
107
|
+
"currentUser": null,
|
|
108
|
+
"loading": false,
|
|
109
|
+
"error": null
|
|
110
|
+
},
|
|
111
|
+
"counter": {
|
|
112
|
+
"count": 0,
|
|
113
|
+
"history": []
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
<div class="card">
|
|
120
|
+
<h3>⚡ 动作历史</h3>
|
|
121
|
+
<div id="actions-history">
|
|
122
|
+
<div class="action-item">
|
|
123
|
+
<div>
|
|
124
|
+
<span class="action-type">等待动作...</span>
|
|
125
|
+
<span class="action-time">--:--:--</span>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
</main>
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<script>
|
|
134
|
+
let ws;
|
|
135
|
+
let actions = [];
|
|
136
|
+
|
|
137
|
+
// 连接 WebSocket
|
|
138
|
+
function connectWebSocket() {
|
|
139
|
+
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
140
|
+
ws = new WebSocket(\`\${protocol}//\${window.location.host}\`);
|
|
141
|
+
|
|
142
|
+
ws.onopen = () => {
|
|
143
|
+
console.log('Connected to ModernX GUI');
|
|
144
|
+
document.getElementById('connection-status').textContent = '已连接';
|
|
145
|
+
document.querySelector('.status-dot').style.background = '#10b981';
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
ws.onmessage = (event) => {
|
|
149
|
+
try {
|
|
150
|
+
const data = JSON.parse(event.data);
|
|
151
|
+
|
|
152
|
+
if (data.type === 'state_update') {
|
|
153
|
+
document.getElementById('state-display').textContent = JSON.stringify(data.payload, null, 2);
|
|
154
|
+
} else if (data.type === 'action') {
|
|
155
|
+
addActionToHistory(data.payload);
|
|
156
|
+
}
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error('Error parsing message:', error);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
ws.onclose = () => {
|
|
163
|
+
console.log('Disconnected from ModernX GUI');
|
|
164
|
+
document.getElementById('connection-status').textContent = '连接断开';
|
|
165
|
+
document.querySelector('.status-dot').style.background = '#ef4444';
|
|
166
|
+
// 尝试重连
|
|
167
|
+
setTimeout(connectWebSocket, 2000);
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 添加动作到历史记录
|
|
172
|
+
function addActionToHistory(action) {
|
|
173
|
+
actions.unshift(action);
|
|
174
|
+
if (actions.length > 50) actions.pop(); // 只保留最近50条
|
|
175
|
+
|
|
176
|
+
const historyContainer = document.getElementById('actions-history');
|
|
177
|
+
historyContainer.innerHTML = actions.map(action => \`
|
|
178
|
+
<div class="action-item">
|
|
179
|
+
<div>
|
|
180
|
+
<span class="action-type">\${action.type}</span>
|
|
181
|
+
<span class="action-time">\${new Date(action.timestamp).toLocaleTimeString()}</span>
|
|
182
|
+
</div>
|
|
183
|
+
<div class="action-payload">\${JSON.stringify(action.payload, null, 2)}</div>
|
|
184
|
+
</div>
|
|
185
|
+
\`).join('');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// 加载项目信息
|
|
189
|
+
async function loadProjectInfo() {
|
|
190
|
+
try {
|
|
191
|
+
const response = await fetch('/api/project');
|
|
192
|
+
const projectInfo = await response.json();
|
|
193
|
+
|
|
194
|
+
document.getElementById('project-info').innerHTML = \`
|
|
195
|
+
<p><strong>项目名称:</strong> \${projectInfo.name || '未知'}</p>
|
|
196
|
+
<p><strong>项目路径:</strong> \${projectInfo.path || '未知'}</p>
|
|
197
|
+
<p><strong>ModernX 项目:</strong> \${projectInfo.isModernX ? '✅ 是' : '❌ 否'}</p>
|
|
198
|
+
\`;
|
|
199
|
+
|
|
200
|
+
const modelsList = document.getElementById('models-list');
|
|
201
|
+
if (projectInfo.models && projectInfo.models.length > 0) {
|
|
202
|
+
modelsList.innerHTML = projectInfo.models.map(model =>
|
|
203
|
+
\`<li>\${model}</li>\`
|
|
204
|
+
).join('');
|
|
205
|
+
} else {
|
|
206
|
+
modelsList.innerHTML = '<li>暂无模型文件</li>';
|
|
207
|
+
}
|
|
208
|
+
} catch (error) {
|
|
209
|
+
console.error('Failed to load project info:', error);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 初始化
|
|
214
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
215
|
+
connectWebSocket();
|
|
216
|
+
loadProjectInfo();
|
|
217
|
+
});
|
|
218
|
+
</script>
|
|
219
|
+
</body>
|
|
220
|
+
</html>`;
|
|
221
|
+
res.send(html);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// API endpoint for project info
|
|
225
|
+
app.get('/api/project', (req, res) => {
|
|
226
|
+
res.json(options.projectInfo || {});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// WebSocket server for real-time communication
|
|
230
|
+
const server = app.listen(port, () => {
|
|
231
|
+
console.log(`🚀 ModernX GUI 服务器运行在端口 ${port}`);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
const wss = new WebSocket.Server({ server });
|
|
235
|
+
|
|
236
|
+
// Handle WebSocket connections
|
|
237
|
+
wss.on('connection', (ws) => {
|
|
238
|
+
console.log('📡 客户端连接到 GUI');
|
|
239
|
+
|
|
240
|
+
ws.on('message', (message) => {
|
|
241
|
+
try {
|
|
242
|
+
const data = JSON.parse(message);
|
|
243
|
+
console.log('📨 收到消息:', data);
|
|
244
|
+
|
|
245
|
+
// Broadcast to all clients
|
|
246
|
+
wss.clients.forEach((client) => {
|
|
247
|
+
if (client.readyState === WebSocket.OPEN) {
|
|
248
|
+
client.send(JSON.stringify(data));
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
} catch (error) {
|
|
252
|
+
console.error('❌ 处理消息错误:', error);
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
ws.on('close', () => {
|
|
257
|
+
console.log('📡 客户端断开连接');
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
return {
|
|
262
|
+
server,
|
|
263
|
+
wss,
|
|
264
|
+
url: `http://localhost:${port}`,
|
|
265
|
+
port,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async function main() {
|
|
270
|
+
try {
|
|
271
|
+
console.log('🚀 启动 ModernX GUI (开发版)...');
|
|
272
|
+
|
|
273
|
+
// 检测当前项目结构
|
|
274
|
+
const projectInfo = await detectProject(process.cwd());
|
|
275
|
+
console.log('📁 项目检测完成:', projectInfo.name);
|
|
276
|
+
|
|
277
|
+
// 启动开发服务器
|
|
278
|
+
const server = await startServer({
|
|
279
|
+
port: 3000,
|
|
280
|
+
projectInfo,
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
console.log(`🌐 GUI 服务器地址: ${server.url}`);
|
|
284
|
+
|
|
285
|
+
// 自动打开浏览器
|
|
286
|
+
await openBrowser(server.url);
|
|
287
|
+
console.log('✅ ModernX GUI 已就绪!');
|
|
288
|
+
console.log('');
|
|
289
|
+
console.log('💡 提示:');
|
|
290
|
+
console.log(' - 这是一个开发版本,使用临时界面');
|
|
291
|
+
console.log(' - 完整功能需要构建前端代码');
|
|
292
|
+
console.log(' - 可以手动发送状态更新进行测试');
|
|
293
|
+
console.log('');
|
|
294
|
+
console.log('🔧 测试命令:');
|
|
295
|
+
console.log(' curl -X POST http://localhost:3000/api/test -d \'{"type":"state_update","payload":{"test":"hello"}}\'');
|
|
296
|
+
|
|
297
|
+
// 添加测试端点
|
|
298
|
+
server.server.on('request', (req, res) => {
|
|
299
|
+
if (req.method === 'POST' && req.url === '/api/test') {
|
|
300
|
+
let body = '';
|
|
301
|
+
req.on('data', chunk => body += chunk);
|
|
302
|
+
req.on('end', () => {
|
|
303
|
+
try {
|
|
304
|
+
const data = JSON.parse(body);
|
|
305
|
+
server.wss.clients.forEach(client => {
|
|
306
|
+
if (client.readyState === WebSocket.OPEN) {
|
|
307
|
+
client.send(JSON.stringify(data));
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
311
|
+
res.end(JSON.stringify({ success: true, message: '数据已广播' }));
|
|
312
|
+
} catch (error) {
|
|
313
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
314
|
+
res.end(JSON.stringify({ error: 'Invalid JSON' }));
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
} catch (error) {
|
|
321
|
+
console.error('❌ 启动 ModernX GUI 失败:', error.message);
|
|
322
|
+
process.exit(1);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
main();
|