a
This commit is contained in:
parent
c01f681dec
commit
4da3e0bd48
|
|
@ -1151,3 +1151,37 @@ async def backend_restart(_admin: Dict[str, Any] = Depends(require_system_admin)
|
||||||
"note": "重启期间接口可能短暂不可用,页面可等待 3-5 秒后刷新状态。",
|
"note": "重启期间接口可能短暂不可用,页面可等待 3-5 秒后刷新状态。",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/backend/stop")
|
||||||
|
async def backend_stop(_admin: Dict[str, Any] = Depends(require_system_admin)) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
停止后端服务(uvicorn)。
|
||||||
|
警告:停止后 API 将不可用,必须手动登录服务器启动!
|
||||||
|
"""
|
||||||
|
backend_dir = Path(__file__).parent.parent.parent # backend/
|
||||||
|
stop_script = backend_dir / "stop.sh"
|
||||||
|
if not stop_script.exists():
|
||||||
|
raise HTTPException(status_code=500, detail=f"找不到停止脚本: {stop_script}")
|
||||||
|
|
||||||
|
cur_pid = os.getpid()
|
||||||
|
|
||||||
|
# 后台执行:sleep 1 后再停止,保证当前请求可以返回
|
||||||
|
cmd = ["bash", "-lc", f"sleep 1; '{stop_script}'"]
|
||||||
|
try:
|
||||||
|
subprocess.Popen(
|
||||||
|
cmd,
|
||||||
|
cwd=str(backend_dir),
|
||||||
|
stdout=subprocess.DEVNULL,
|
||||||
|
stderr=subprocess.DEVNULL,
|
||||||
|
start_new_session=True,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(status_code=500, detail=f"启动停止脚本失败: {e}")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"message": "已发起后端停止(1s 后执行)",
|
||||||
|
"pid_before": cur_pid,
|
||||||
|
"script": str(stop_script),
|
||||||
|
"warning": "后端服务停止后,Web 界面将无法访问,请手动在服务器启动!",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -610,43 +610,16 @@ const GlobalConfig = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleStartTrading = async () => {
|
const handleStopBackend = async () => {
|
||||||
|
if (!window.confirm('警告:确定要停止后端服务吗?\n\n停止后 Web 界面将立即无法访问!\n必须手动登录服务器执行 ./start.sh 才能恢复。')) return
|
||||||
setSystemBusy(true)
|
setSystemBusy(true)
|
||||||
setMessage('')
|
setMessage('')
|
||||||
try {
|
try {
|
||||||
const res = await api.startTradingSystem()
|
const res = await api.stopBackend()
|
||||||
setMessage(res.message || '交易系统已启动')
|
setMessage(res.message || '后端服务已停止')
|
||||||
await loadSystemStatus()
|
alert('后端服务已停止,页面将不再响应。请手动去服务器启动。')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setMessage('启动失败: ' + (error.message || '未知错误'))
|
setMessage('停止后端失败: ' + (error.message || '未知错误'))
|
||||||
} finally {
|
|
||||||
setSystemBusy(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleStopTrading = async () => {
|
|
||||||
setSystemBusy(true)
|
|
||||||
setMessage('')
|
|
||||||
try {
|
|
||||||
const res = await api.stopTradingSystem()
|
|
||||||
setMessage(res.message || '交易系统已停止')
|
|
||||||
await loadSystemStatus()
|
|
||||||
} catch (error) {
|
|
||||||
setMessage('停止失败: ' + (error.message || '未知错误'))
|
|
||||||
} finally {
|
|
||||||
setSystemBusy(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleRestartTrading = async () => {
|
|
||||||
setSystemBusy(true)
|
|
||||||
setMessage('')
|
|
||||||
try {
|
|
||||||
const res = await api.restartTradingSystem()
|
|
||||||
setMessage(res.message || '交易系统已重启')
|
|
||||||
await loadSystemStatus()
|
|
||||||
} catch (error) {
|
|
||||||
setMessage('重启失败: ' + (error.message || '未知错误'))
|
|
||||||
} finally {
|
} finally {
|
||||||
setSystemBusy(false)
|
setSystemBusy(false)
|
||||||
}
|
}
|
||||||
|
|
@ -1203,6 +1176,15 @@ const GlobalConfig = () => {
|
||||||
>
|
>
|
||||||
重启后端服务
|
重启后端服务
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="system-btn danger"
|
||||||
|
onClick={handleStopBackend}
|
||||||
|
disabled={systemBusy}
|
||||||
|
title="停止后端服务(需要手动去服务器启动)"
|
||||||
|
>
|
||||||
|
停止后端服务
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="system-btn"
|
className="system-btn"
|
||||||
|
|
@ -1218,24 +1200,6 @@ const GlobalConfig = () => {
|
||||||
<div className="system-control-group" style={{ marginTop: '15px' }}>
|
<div className="system-control-group" style={{ marginTop: '15px' }}>
|
||||||
<h4 className="control-group-title" style={{ margin: '10px 0 8px', fontSize: '14px', color: '#666' }}>交易服务管理</h4>
|
<h4 className="control-group-title" style={{ margin: '10px 0 8px', fontSize: '14px', color: '#666' }}>交易服务管理</h4>
|
||||||
<div className="system-actions">
|
<div className="system-actions">
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="system-btn"
|
|
||||||
onClick={handleStartTrading}
|
|
||||||
disabled={systemBusy || systemStatus?.running === true}
|
|
||||||
title="通过 supervisorctl 启动交易系统"
|
|
||||||
>
|
|
||||||
启动
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="system-btn"
|
|
||||||
onClick={handleStopTrading}
|
|
||||||
disabled={systemBusy || systemStatus?.running === false}
|
|
||||||
title="通过 supervisorctl 停止交易系统"
|
|
||||||
>
|
|
||||||
停止
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="system-btn primary"
|
className="system-btn primary"
|
||||||
|
|
|
||||||
|
|
@ -671,6 +671,18 @@ export const api = {
|
||||||
return response.json();
|
return response.json();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
stopBackend: async () => {
|
||||||
|
const response = await fetch(buildUrl('/api/system/backend/stop'), {
|
||||||
|
method: 'POST',
|
||||||
|
headers: withAccountHeaders({ 'Content-Type': 'application/json' }),
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
const error = await response.json().catch(() => ({ detail: '停止后端失败' }));
|
||||||
|
throw new Error(error.detail || '停止后端失败');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
},
|
||||||
|
|
||||||
// 日志监控(Redis List)
|
// 日志监控(Redis List)
|
||||||
getSystemLogs: async (params = {}) => {
|
getSystemLogs: async (params = {}) => {
|
||||||
const query = new URLSearchParams(params).toString();
|
const query = new URLSearchParams(params).toString();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user