update
This commit is contained in:
parent
1a9bf9f74b
commit
3079430bbc
@ -1,5 +1,5 @@
|
||||
"""
|
||||
模拟交易 API
|
||||
交易 API
|
||||
"""
|
||||
from fastapi import APIRouter, HTTPException, Query
|
||||
from typing import Optional
|
||||
@ -13,7 +13,7 @@ from app.services.db_service import db_service
|
||||
from app.utils.logger import logger
|
||||
|
||||
|
||||
router = APIRouter(prefix="/api/paper-trading", tags=["交易"])
|
||||
router = APIRouter(prefix="/api/trading", tags=["交易"])
|
||||
|
||||
|
||||
class CloseOrderRequest(BaseModel):
|
||||
|
||||
@ -684,10 +684,10 @@ async def health_check():
|
||||
"""健康检查"""
|
||||
return {"status": "healthy"}
|
||||
|
||||
@app.get("/paper-trading")
|
||||
async def paper_trading_page():
|
||||
"""模拟交易页面"""
|
||||
page_path = os.path.join(frontend_path, "paper-trading.html")
|
||||
@app.get("/trading")
|
||||
async def trading_page():
|
||||
"""交易页面"""
|
||||
page_path = os.path.join(frontend_path, "trading.html")
|
||||
if os.path.exists(page_path):
|
||||
return FileResponse(page_path)
|
||||
return {"message": "页面不存在"}
|
||||
|
||||
@ -57,6 +57,8 @@
|
||||
font-size: 24px;
|
||||
font-weight: 300;
|
||||
color: var(--text-primary);
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.trading-title span {
|
||||
@ -571,6 +573,17 @@
|
||||
background: rgba(255, 68, 68, 0.1);
|
||||
}
|
||||
|
||||
/* 管理员模式指示器 */
|
||||
.admin-indicator {
|
||||
font-size: 16px;
|
||||
opacity: 0.6;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.admin-indicator:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* 操作按钮 */
|
||||
.action-btn {
|
||||
padding: 4px 8px;
|
||||
@ -1150,23 +1163,27 @@
|
||||
<div class="sticky-header">
|
||||
<!-- 头部 -->
|
||||
<div class="trading-header">
|
||||
<h1 class="trading-title">AI 自动化交易 <span>| AI Agent Trading System</span></h1>
|
||||
<h1 class="trading-title" @click="handleTitleClick">AI 自动化交易 <span>| AI Agent Trading System</span></h1>
|
||||
<div style="display: flex; align-items: center; gap: 12px;">
|
||||
<div class="monitor-status">
|
||||
<div class="monitor-dot" :class="{ running: monitorRunning }"></div>
|
||||
<span>{{ monitorRunning ? '监控中' : '未启动' }}</span>
|
||||
</div>
|
||||
<div class="admin-dropdown">
|
||||
<!-- 隐藏的管理菜单,仅在管理员模式下显示 -->
|
||||
<div class="admin-dropdown" v-if="adminMode">
|
||||
<button class="admin-btn" @click="toggleAdminMenu">管理 ▾</button>
|
||||
<div class="admin-menu" v-if="showAdminMenu">
|
||||
<button @click="toggleAdminMode">
|
||||
<span v-if="adminMode">🔓 关闭管理员模式</span>
|
||||
<span v-else>🔒 开启管理员模式</span>
|
||||
<span>🔓 关闭管理员模式</span>
|
||||
</button>
|
||||
<button @click="adminSendReport">发送报告</button>
|
||||
<button @click="adminResetData" class="danger">重置数据</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 管理员模式指示器(仅在开启后显示) -->
|
||||
<div class="admin-indicator" v-if="adminMode">
|
||||
<span>⚙️</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1672,8 +1689,10 @@
|
||||
isFirstLoad: true,
|
||||
sendingReport: false,
|
||||
showAdminMenu: false,
|
||||
adminPassword: '223388',
|
||||
adminMode: localStorage.getItem('paperTradingAdminMode') === 'true',
|
||||
adminPassword: '223388', // 管理员密码
|
||||
adminMode: false, // 不再持久化,关闭页面后自动退出
|
||||
titleClickCount: 0, // 标题点击计数
|
||||
titleClickTimer: null, // 点击计时器
|
||||
showShareModal: false,
|
||||
shareOrderData: {
|
||||
symbol: '',
|
||||
@ -1707,6 +1726,46 @@
|
||||
document.removeEventListener('click', this.closeAdminMenu);
|
||||
},
|
||||
methods: {
|
||||
// 标题点击处理 - 隐藏的管理员入口(连续点击3次)
|
||||
handleTitleClick() {
|
||||
this.titleClickCount++;
|
||||
|
||||
// 清除之前的计时器
|
||||
if (this.titleClickTimer) {
|
||||
clearTimeout(this.titleClickTimer);
|
||||
}
|
||||
|
||||
// 设置新的计时器,2秒后重置计数
|
||||
this.titleClickTimer = setTimeout(() => {
|
||||
this.titleClickCount = 0;
|
||||
}, 2000);
|
||||
|
||||
// 连续点击3次触发管理员模式切换
|
||||
if (this.titleClickCount === 3) {
|
||||
this.titleClickCount = 0;
|
||||
this.promptAdminMode();
|
||||
}
|
||||
},
|
||||
|
||||
// 提示输入管理员密码
|
||||
promptAdminMode() {
|
||||
if (this.adminMode) {
|
||||
// 已开启,直接关闭
|
||||
this.adminMode = false;
|
||||
this.showAdminMenu = false;
|
||||
alert('管理员模式已关闭');
|
||||
} else {
|
||||
// 未开启,提示输入密码
|
||||
const password = prompt('请输入管理员密码:');
|
||||
if (password === this.adminPassword) {
|
||||
this.adminMode = true;
|
||||
alert('管理员模式已开启\n\n功能:\n• 删除订单\n• 重置数据\n• 发送报告');
|
||||
} else if (password !== null) {
|
||||
alert('密码错误');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 切换管理菜单
|
||||
toggleAdminMenu(event) {
|
||||
event.stopPropagation();
|
||||
@ -1720,11 +1779,12 @@
|
||||
}
|
||||
},
|
||||
|
||||
// 切换管理员模式
|
||||
// 切换管理员模式(仅用于关闭)
|
||||
toggleAdminMode() {
|
||||
this.adminMode = !this.adminMode;
|
||||
localStorage.setItem('paperTradingAdminMode', this.adminMode);
|
||||
this.showAdminMenu = false;
|
||||
if (this.adminMode) {
|
||||
this.adminMode = false;
|
||||
this.showAdminMenu = false;
|
||||
}
|
||||
},
|
||||
|
||||
// 验证管理密码
|
||||
@ -1870,7 +1930,7 @@
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/paper-trading/reset', {
|
||||
const response = await fetch('/api/trading/reset', {
|
||||
method: 'POST'
|
||||
});
|
||||
const data = await response.json();
|
||||
@ -1888,7 +1948,7 @@
|
||||
async sendReport() {
|
||||
this.sendingReport = true;
|
||||
try {
|
||||
const response = await fetch('/api/paper-trading/report?hours=4&send_telegram=true', {
|
||||
const response = await fetch('/api/trading/report?hours=4&send_telegram=true', {
|
||||
method: 'POST'
|
||||
});
|
||||
const data = await response.json();
|
||||
@ -1909,7 +1969,7 @@
|
||||
},
|
||||
|
||||
async fetchActiveOrders() {
|
||||
const response = await fetch('/api/paper-trading/orders/active');
|
||||
const response = await fetch('/api/trading/orders/active');
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
this.activeOrders = data.orders;
|
||||
@ -1917,7 +1977,7 @@
|
||||
},
|
||||
|
||||
async fetchHistoryOrders() {
|
||||
const response = await fetch('/api/paper-trading/orders?status=closed&limit=50');
|
||||
const response = await fetch('/api/trading/orders?status=closed&limit=50');
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
this.historyOrders = data.orders;
|
||||
@ -1925,7 +1985,7 @@
|
||||
},
|
||||
|
||||
async fetchStatistics() {
|
||||
const response = await fetch('/api/paper-trading/statistics');
|
||||
const response = await fetch('/api/trading/statistics');
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
this.stats = data.statistics;
|
||||
@ -1933,7 +1993,7 @@
|
||||
},
|
||||
|
||||
async fetchAccountStatus() {
|
||||
const response = await fetch('/api/paper-trading/account');
|
||||
const response = await fetch('/api/trading/account');
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
this.account = data.account;
|
||||
@ -1941,7 +2001,7 @@
|
||||
},
|
||||
|
||||
async fetchMonitorStatus() {
|
||||
const response = await fetch('/api/paper-trading/monitor/status');
|
||||
const response = await fetch('/api/trading/monitor/status');
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
this.monitorRunning = data.running;
|
||||
@ -1961,7 +2021,7 @@
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/paper-trading/orders/${order.order_id}/close`, {
|
||||
const response = await fetch(`/api/trading/orders/${order.order_id}/close`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ exit_price: price })
|
||||
@ -1998,7 +2058,7 @@
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/paper-trading/orders/${order.order_id}`, {
|
||||
const response = await fetch(`/api/trading/orders/${order.order_id}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
const data = await response.json();
|
||||
@ -2040,7 +2100,7 @@
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/paper-trading/orders/${order.order_id}`, {
|
||||
const response = await fetch(`/api/trading/orders/${order.order_id}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
const data = await response.json();
|
||||
@ -2150,7 +2210,7 @@
|
||||
async fetchDailyReturns() {
|
||||
this.loadingReturns = true;
|
||||
try {
|
||||
const response = await fetch('/api/paper-trading/daily-returns?days=30');
|
||||
const response = await fetch('/api/trading/daily-returns?days=30');
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
this.dailyReturns = data.data;
|
||||
Loading…
Reference in New Issue
Block a user