-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup_project.py
More file actions
283 lines (241 loc) · 15.6 KB
/
setup_project.py
File metadata and controls
283 lines (241 loc) · 15.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
项目环境检查和自动设置脚本 - 更新版
用于检查项目依赖是否安装,并自动设置开发环境
"""
import os
import sys
import subprocess
import json
from pathlib import Path
def print_status(message, status="INFO"):
"""打印带状态的消息"""
colors = {
"INFO": "\033[36m", # 青色
"SUCCESS": "\033[32m", # 绿色
"WARNING": "\033[33m", # 黄色
"ERROR": "\033[31m", # 红色
"RESET": "\033[0m" # 重置
}
print(f"{colors.get(status, '')}{status}: {message}{colors['RESET']}")
def check_python_version():
"""检查Python版本"""
version = sys.version_info
if version.major == 3 and version.minor >= 8:
print_status(f"Python版本检查通过: {version.major}.{version.minor}.{version.micro}", "SUCCESS")
return True
else:
print_status(f"Python版本过低: {version.major}.{version.minor}.{version.micro},需要3.8+", "ERROR")
return False
def check_node_version():
"""检查Node.js版本"""
try:
result = subprocess.run(['node', '--version'], capture_output=True, text=True)
if result.returncode == 0:
version = result.stdout.strip()
print_status(f"Node.js版本检查通过: {version}", "SUCCESS")
return True
except FileNotFoundError:
print_status("Node.js未安装,请安装Node.js 16+", "ERROR")
return False
def install_backend_dependencies():
"""安装后端依赖"""
print_status("开始安装后端Python依赖...", "INFO")
backend_path = Path("backend")
requirements_file = backend_path / "requirements.txt"
if not requirements_file.exists():
print_status("requirements.txt文件不存在", "ERROR")
return False
try:
# 安装依赖
subprocess.run([
sys.executable, "-m", "pip", "install", "-r", str(requirements_file)
], check=True)
print_status("后端依赖安装成功", "SUCCESS")
return True
except subprocess.CalledProcessError as e:
print_status(f"后端依赖安装失败: {e}", "ERROR")
return False
def install_frontend_dependencies():
"""安装前端依赖"""
print_status("开始安装前端Node.js依赖...", "INFO")
frontend_path = Path("frontend")
package_json = frontend_path / "package.json"
if not package_json.exists():
print_status("package.json文件不存在", "ERROR")
return False
try:
# 安装依赖
subprocess.run(["npm", "install"], check=True, cwd=frontend_path)
print_status("前端依赖安装成功", "SUCCESS")
return True
except subprocess.CalledProcessError as e:
print_status(f"前端依赖安装失败: {e}", "ERROR")
return False
def init_database():
"""初始化数据库"""
print_status("初始化数据库...", "INFO")
backend_path = Path("backend")
try:
# 检查是否能导入模块
subprocess.run([
sys.executable, "-c",
"import sys; sys.path.append('.'); from app.database import engine; from app.models import Base; Base.metadata.create_all(bind=engine); print('数据库表创建成功')"
], check=True, cwd=backend_path)
print_status("数据库初始化成功", "SUCCESS")
return True
except subprocess.CalledProcessError as e:
print_status(f"数据库初始化失败: {e}", "WARNING")
print_status("可能是因为依赖未安装,请先运行依赖安装", "INFO")
return False
def check_ports():
"""检查端口是否被占用"""
import socket
def is_port_open(port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(1)
result = sock.connect_ex(('localhost', port))
sock.close()
return result == 0
frontend_port = 3000
backend_port = 8000
if is_port_open(frontend_port):
print_status(f"前端端口{frontend_port}已被占用", "WARNING")
else:
print_status(f"前端端口{frontend_port}可用", "SUCCESS")
if is_port_open(backend_port):
print_status(f"后端端口{backend_port}已被占用", "WARNING")
else:
print_status(f"后端端口{backend_port}可用", "SUCCESS")
def check_project_structure():
"""检查项目结构是否完整"""
print_status("检查项目结构...", "INFO")
required_files = [
"backend/main.py",
"backend/requirements.txt",
"backend/app/models.py",
"backend/app/database.py",
"frontend/package.json",
"frontend/src/main.js",
"frontend/src/App.vue"
]
missing_files = []
for file_path in required_files:
if not Path(file_path).exists():
missing_files.append(file_path)
if missing_files:
print_status("以下文件缺失:", "WARNING")
for file in missing_files:
print(f" - {file}")
return False
else:
print_status("项目结构检查通过", "SUCCESS")
return True
def setup_project():
"""原有的setup_project函数,保持兼容性"""
print_status("运行原有项目设置...", "INFO")
project_root = os.getcwd()
backend_path = os.path.join(project_root, 'backend')
static_path = os.path.join(backend_path, 'static')
html_file_path = os.path.join(static_path, 'test_api.html')
init_db_script_path = os.path.join(backend_path, 'init_db.py')
print("------ 正在设置项目文件和目录 ------")
# 1. 创建 static 目录
print(f"正在创建目录: {static_path}")
os.makedirs(static_path, exist_ok=True)
print("目录创建或已存在!")
# 2. 写入 test_api.html 内容
html_content = '''<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>嵌入式Linux智能教学平台 - API测试</title><style>body{font-family:'Microsoft YaHei', Arial, sans-serif;max-width:800px;margin:0 auto;padding:20px;background-color:#f5f5f5}.container{background:white;padding:30px;border-radius:10px;box-shadow:0 2px 10px rgba(0,0,0,0.1)}h1{color:#2c3e50;text-align:center;margin-bottom:30px}.section{margin-bottom:30px;padding:20px;border:1px solid #ddd;border-radius:5px;background-color:#f9f9f9}.section h2{color:#34495e;margin-top:0}.form-group{margin-bottom:15px}label{display:block;margin-bottom:5px;font-weight:bold;color:#555}input,select{width:100%;padding:10px;border:1px solid #ddd;border-radius:4px;font-size:14px}button{background-color:#3498db;color:white;padding:12px 24px;border:none;border-radius:4px;cursor:pointer;font-size:16px;margin-right:10px}button:hover{background-color:#2980b9}.result{margin-top:15px;padding:15px;border-radius:4px;white-space:pre-wrap;font-family:monospace}.success{background-color:#d4edda;border:1px solid #c3e6cb;color:#155724}.error{background-color:#f8d7da;border:1px solid #f5c6cb;color:#721c24}.info{background-color:#d1ecf1;border:1px solid #bee5eb;color:#0c5460}</style></head><body><div class="container"><h1>🚀 嵌入式Linux智能教学平台 - API测试</h1><div class="section"><h2>📝 用户注册</h2><div class="form-group"><label for="reg-username">用户名:</label><input type="text" id="reg-username" placeholder="请输入用户名"></div><div class="form-group"><label for="reg-email">邮箱:</label><input type="email" id="reg-email" placeholder="请输入邮箱"></div><div class="form-group"><label for="reg-password">密码:</label><input type="password" id="reg-password" placeholder="请输入密码"></div><div class="form-group"><label for="reg-role">角色:</label><select id="reg-role"><option value="student">学生</option><option value="teacher">教师</option><option value="admin">管理员</option></select></div><button onclick="register()">注册用户</button><div id="register-result" class="result" style="display: none;"></div></div><div class="section"><h2>🔐 用户登录</h2><div class="form-group"><label for="login-username">用户名:</label><input type="text" id="login-username" placeholder="请输入用户名"></div><div class="form-group"><label for="login-password">密码:</label><input type="password" id="login-password" placeholder="请输入密码"></div><button onclick="login()">登录</button><div id="login-result" class="result" style="display: none;"></div></div><div class="section"><h2>👤 获取用户信息</h2><button onclick="getUserInfo()">获取当前用户信息</button><div id="userinfo-result" class="result" style="display: none;"></div></div><div class="section"><h2>💚 健康检查</h2><button onclick="healthCheck()">检查服务状态</button><div id="health-result" class="result" style="display: none;"></div></div></div><script>let currentToken='';function showResult(elementId,message,type='info'){const element=document.getElementById(elementId);element.textContent=message;element.className=`result ${type}`;element.style.display='block'}async function register(){const username=document.getElementById('reg-username').value;const email=document.getElementById('reg-email').value;const password=document.getElementById('reg-password').value;const role=document.getElementById('reg-role').value;if(!username||!email||!password){showResult('register-result','请填写所有必填字段!','error');return}try{const response=await fetch('http://localhost:8000/register',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({username:username,email:email,password:password,role:role})});const data=await response.json();if(response.ok){showResult('register-result',`✅ 注册成功!\n用户ID: ${data.id}\n用户名: ${data.username}\n邮箱: ${data.email}\n角色: ${data.role}`,'success')}else{showResult('register-result',`❌ 注册失败:${data.detail}`,'error')}}catch(error){showResult('register-result',`❌ 网络错误:${error.message}`,'error')}}async function login(){const username=document.getElementById('login-username').value;const password=document.getElementById('login-password').value;if(!username||!password){showResult('login-result','请填写用户名和密码!','error');return}try{const formData=new FormData();formData.append('username',username);formData.append('password',password);const response=await fetch('http://localhost:8000/token',{method:'POST',body:formData});const data=await response.json();if(response.ok){currentToken=data.access_token;showResult('login-result',`✅ 登录成功!\nToken: ${data.access_token}\nToken类型: ${data.token_type}`,'success')}else{showResult('login-result',`❌ 登录失败:${data.detail}`,'error')}}catch(error){showResult('login-result',`❌ 网络错误:${error.message}`,'error')}}async function getUserInfo(){if(!currentToken){showResult('userinfo-result','❌ 请先登录获取Token!','error');return}try{const response=await fetch('http://localhost:8000/me',{method:'GET',headers:{'Authorization':`Bearer ${currentToken}`}});const data=await response.json();if(response.ok){showResult('userinfo-result',`✅ 用户信息:\n用户ID: ${data.id}\n用户名: ${data.username}\n邮箱: ${data.email}\n角色: ${data.role}\n状态: ${data.is_active?'激活':'未激活'}\n创建时间: ${data.created_at}`,'success')}else{showResult('userinfo-result',`❌ 获取用户信息失败:${data.detail}`,'error')}}catch(error){showResult('userinfo-result',`❌ 网络错误:${error.message}`,'error')}}async function healthCheck(){try{const response=await fetch('http://localhost:8000/health');const data=await response.json();if(response.ok){showResult('health-result',`✅ 服务状态:${data.status}`,'success')}else{showResult('health-result',`❌ 服务异常:${data.detail}`,'error')}}catch(error){showResult('health-result',`❌ 无法连接到服务:${error.message}`,'error')}}</script></body></html>'''
print(f"正在写入文件: {html_file_path}")
with open(html_file_path, 'w', encoding='utf-8') as f:
f.write(html_content)
print("中文测试页面写入完成!")
# 3. 初始化数据库
print("正在初始化数据库...")
# 调用 init_db.py 脚本
try:
subprocess.run(['python', init_db_script_path], check=True, cwd=backend_path)
print("数据库初始化完成!")
except subprocess.CalledProcessError as e:
print(f"数据库初始化失败: {e}")
print(e.stdout.decode() if e.stdout else "")
print(e.stderr.decode() if e.stderr else "")
exit(1)
print("------ 文件和目录设置完成! ------")
def main():
"""主函数"""
print("=" * 60)
print("🚀 嵌入式Linux智能教学平台 - 环境检查工具")
print("=" * 60)
# 检查Python版本
if not check_python_version():
return
# 检查Node.js版本
node_ok = check_node_version()
# 检查项目结构
structure_ok = check_project_structure()
if not structure_ok:
print_status("项目结构不完整,运行原有设置脚本...", "INFO")
setup_project()
# 检查端口
check_ports()
# 尝试安装依赖
if node_ok:
frontend_success = install_frontend_dependencies()
else:
frontend_success = False
print_status("跳过前端依赖安装(Node.js未安装)", "WARNING")
backend_success = install_backend_dependencies()
# 初始化数据库
if backend_success:
init_database()
print("\n" + "=" * 60)
print("📋 项目状态总结:")
print("=" * 60)
print(f"✅ Python环境: {'正常' if check_python_version() else '异常'}")
print(f"✅ Node.js环境: {'正常' if node_ok else '未安装'}")
print(f"✅ 项目结构: {'完整' if structure_ok else '不完整'}")
print(f"✅ 后端依赖: {'已安装' if backend_success else '安装失败'}")
print(f"✅ 前端依赖: {'已安装' if frontend_success else '安装失败/跳过'}")
if backend_success and frontend_success:
print("\n" + "=" * 60)
print("🚀 项目启动命令:")
print("=" * 60)
print("1. 启动后端服务器:")
print(" cd backend")
print(" python main.py")
print(" # 或者: uvicorn main:app --reload")
print("")
print("2. 启动前端服务器 (新建命令行窗口):")
print(" cd frontend")
print(" npm run dev")
print("")
print("3. 访问应用:")
print(" 前端: http://localhost:3000")
print(" 后端API文档: http://localhost:8000/docs")
print(" API测试页面: http://localhost:8000/static/test_api.html")
print("=" * 60)
print("\n📝 给AI同学的提示:")
print("1. 现在可以开始开发AI功能模块")
print("2. 参考backend/app/models.py了解数据结构")
print("3. 在backend/app/目录下创建ai_service.py")
print("4. 查看新手指南.md获取详细任务安排")
elif backend_success:
print("\n✅ 后端环境配置完成,可以开始后端开发")
print("❌ 前端环境配置失败,请安装Node.js后重新运行")
else:
print("\n❌ 环境配置失败,请检查错误信息并解决问题")
print("💡 常见问题:")
print(" - 检查网络连接")
print(" - 确保有足够的磁盘空间")
print(" - 尝试使用管理员权限运行")
# 如果直接运行此文件,调用新的main函数
if __name__ == "__main__":
import sys
if len(sys.argv) > 1 and sys.argv[1] == "--legacy":
# 使用 --legacy 参数运行原有功能
setup_project()
else:
# 默认运行新的环境检查功能
main()