You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
buffer_platform/buffer_platform_v2/app/static/index.html

447 lines
18 KiB

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>期货智析 - 配置管理</title>
<!-- CSS -->
<link rel="stylesheet" href="/static/css/variables.css">
<link rel="stylesheet" href="/static/css/base.css">
<link rel="stylesheet" href="/static/css/components.css">
<link rel="stylesheet" href="/static/css/layout.css">
<style>
.config-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: var(--spacing-lg);
margin-bottom: var(--spacing-xl);
}
.config-card {
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
padding: var(--spacing-lg);
box-shadow: var(--shadow-sm);
transition: all var(--transition-fast);
cursor: pointer;
}
.config-card:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-lg);
border-color: var(--border-glow);
}
.config-card__icon {
font-size: 40px;
margin-bottom: var(--spacing-md);
}
.config-card__title {
font-size: var(--font-size-lg);
font-weight: 700;
color: var(--text-primary);
margin-bottom: var(--spacing-xs);
}
.config-card__desc {
font-size: var(--font-size-sm);
color: var(--text-secondary);
line-height: 1.6;
margin-bottom: var(--spacing-md);
}
.config-card__action {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: var(--font-size-sm);
color: var(--color-primary);
font-weight: 600;
}
/* 品种表格区域 */
.symbols-section {
margin-top: var(--spacing-xl);
}
.symbols-table-wrap {
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
overflow: hidden;
box-shadow: var(--shadow-sm);
}
.symbols-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--spacing-md) var(--spacing-lg);
border-bottom: 1px solid var(--border-color);
flex-wrap: wrap;
gap: var(--spacing-sm);
}
.symbols-toolbar__left {
display: flex;
align-items: center;
gap: var(--spacing-sm);
}
.symbols-toolbar__right {
display: flex;
align-items: center;
gap: var(--spacing-sm);
}
.table {
width: 100%;
border-collapse: collapse;
}
.table thead th {
padding: 12px var(--spacing-md);
font-size: var(--font-size-xs);
font-weight: 600;
color: var(--text-secondary);
text-align: left;
background: var(--bg-primary);
border-bottom: 1px solid var(--border-color);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.table tbody tr {
transition: background var(--transition-fast);
}
.table tbody tr:hover {
background: var(--bg-primary);
}
.table tbody td {
padding: 12px var(--spacing-md);
font-size: var(--font-size-sm);
color: var(--text-primary);
border-bottom: 1px solid var(--border-color);
}
.table tbody tr:last-child td {
border-bottom: none;
}
.action-btns {
display: flex;
gap: 6px;
}
/* 上传区域 */
.upload-area {
border: 2px dashed var(--border-color);
border-radius: var(--radius-md);
padding: var(--spacing-xl);
text-align: center;
margin: var(--spacing-lg);
transition: all var(--transition-fast);
cursor: pointer;
}
.upload-area:hover {
border-color: var(--color-primary);
background: var(--color-primary-soft);
}
.upload-area__icon {
font-size: 40px;
margin-bottom: var(--spacing-sm);
opacity: 0.5;
}
.upload-area__text {
font-size: var(--font-size-sm);
color: var(--text-secondary);
}
</style>
</head>
<body>
<div class="app-container">
<!-- 顶部导航 -->
<nav class="top-nav">
<div class="nav-left">
<div class="logo">
<div class="logo-icon">&#9672;</div>
<div class="logo-text">
<span class="logo-title">期货智析</span>
<span class="logo-subtitle">CONFIG</span>
</div>
</div>
</div>
<div class="nav-center">
<a class="nav-item active" href="/static/index.html">配置管理</a>
<a class="nav-item" href="/static/futures_analysis.html">品种分析</a>
<a class="nav-item" href="/static/ai_config.html">AI配置</a>
<a class="nav-item" href="/static/review_plan.html">复盘计划</a>
</div>
<div class="nav-right">
<button class="nav-btn" id="themeToggle" title="切换主题">&#127769;</button>
<span class="datetime" id="userInfo"></span>
<button class="nav-btn" id="btn-logout" title="登出">&#x23FB;</button>
</div>
</nav>
<!-- 主内容区 -->
<main class="main-content">
<!-- 功能入口卡片 -->
<div class="config-grid">
<a class="config-card" href="/static/futures_analysis.html" style="text-decoration:none;color:inherit;">
<div class="config-card__icon">&#128202;</div>
<div class="config-card__title">品种分析</div>
<div class="config-card__desc">智能期货品种分析工具提供K线图表、技术指标、AI智能分析等功能。</div>
<span class="config-card__action">进入分析 &rarr;</span>
</a>
<a class="config-card" href="/static/ai_config.html" style="text-decoration:none;color:inherit;">
<div class="config-card__icon">&#129302;</div>
<div class="config-card__title">AI 模型配置</div>
<div class="config-card__desc">配置AI分析模型、API密钥、分析参数和交易建议设置。</div>
<span class="config-card__action">配置模型 &rarr;</span>
</a>
<a class="config-card" href="/static/review_plan.html" style="text-decoration:none;color:inherit;">
<div class="config-card__icon">&#128221;</div>
<div class="config-card__title">复盘计划</div>
<div class="config-card__desc">查看和管理交易复盘计划,生成每日复盘报告。</div>
<span class="config-card__action">查看计划 &rarr;</span>
</a>
<a class="config-card" href="/static/role_select.html" style="text-decoration:none;color:inherit;">
<div class="config-card__icon">&#128101;</div>
<div class="config-card__title">用户管理</div>
<div class="config-card__desc">管理系统用户、角色权限和登录设置。</div>
<span class="config-card__action">用户管理 &rarr;</span>
</a>
</div>
<!-- 品种配置区域 -->
<div class="symbols-section">
<div class="symbols-table-wrap">
<div class="symbols-toolbar">
<div class="symbols-toolbar__left">
<h3 style="font-size:var(--font-size-lg);font-weight:700;">品种列表</h3>
<span class="badge" id="symbolCount">0 个品种</span>
</div>
<div class="symbols-toolbar__right">
<button class="btn btn--secondary btn--sm" id="btnUpload">
&#128228; 上传配置
</button>
<button class="btn btn--secondary btn--sm" id="btnBatchCollect">
&#9654; 批量采集
</button>
<button class="btn btn--secondary btn--sm" id="btnBatchTask">
&#128197; 批量建任务
</button>
<button class="btn btn--primary btn--sm" id="btnAddSymbol">
+ 添加品种
</button>
</div>
</div>
<!-- 上传区域(默认隐藏) -->
<div class="upload-area" id="uploadArea" style="display:none;">
<div class="upload-area__icon">&#128194;</div>
<div class="upload-area__text">点击或拖拽配置文件到此处<br><small>支持 JSON 格式</small></div>
<input type="file" id="fileInput" accept=".json" style="display:none;">
</div>
<!-- 品种表格 -->
<table class="table">
<thead>
<tr>
<th>品种名称</th>
<th>代码</th>
<th>交易所</th>
<th>类别</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody id="symbolsTableBody">
<!-- 动态生成 -->
</tbody>
</table>
</div>
</div>
</main>
</div>
<!-- 添加/编辑品种模态框 -->
<div class="modal-overlay" id="symbolModal">
<div class="modal-content">
<div class="modal-header">
<h3 id="symbolModalTitle">添加品种</h3>
<button class="modal-close" data-close="symbolModal">&#10005;</button>
</div>
<div class="modal-body">
<form id="symbolForm">
<div style="display:flex;flex-direction:column;gap:var(--spacing-md);">
<div>
<label style="display:block;font-size:var(--font-size-sm);font-weight:500;margin-bottom:var(--spacing-xs);color:var(--text-secondary);">品种名称</label>
<input type="text" class="input" id="symbolName" placeholder="如:螺纹钢" required>
</div>
<div>
<label style="display:block;font-size:var(--font-size-sm);font-weight:500;margin-bottom:var(--spacing-xs);color:var(--text-secondary);">品种代码</label>
<input type="text" class="input" id="symbolCode" placeholder="如RB" required>
</div>
<div>
<label style="display:block;font-size:var(--font-size-sm);font-weight:500;margin-bottom:var(--spacing-xs);color:var(--text-secondary);">交易所</label>
<select class="select" id="symbolExchange">
<option value="SHFE">上海期货交易所</option>
<option value="DCE">大连商品交易所</option>
<option value="CZCE">郑州商品交易所</option>
<option value="CFFEX">中国金融期货交易所</option>
<option value="INE">上海国际能源交易中心</option>
<option value="GFEX">广州期货交易所</option>
</select>
</div>
<div>
<label style="display:block;font-size:var(--font-size-sm);font-weight:500;margin-bottom:var(--spacing-xs);color:var(--text-secondary);">类别</label>
<select class="select" id="symbolCategory">
<option value="energy">能源</option>
<option value="metal">金属</option>
<option value="agriculture">农产品</option>
<option value="finance">金融</option>
<option value="chemical">化工</option>
</select>
</div>
</div>
<div style="display:flex;gap:var(--spacing-sm);justify-content:flex-end;margin-top:var(--spacing-lg);">
<button type="button" class="btn btn--secondary" data-close="symbolModal">取消</button>
<button type="submit" class="btn btn--primary">保存</button>
</div>
</form>
</div>
</div>
</div>
<!-- JS -->
<script type="module">
import { api } from '/static/js/api.js';
import { themeManager } from '/static/js/theme.js';
import { showNotification } from '/static/js/components.js';
import { logout } from '/static/js/auth.js';
// 主题切换
document.getElementById('themeToggle').addEventListener('click', () => {
themeManager.toggle();
});
// 登出
document.getElementById('btn-logout').addEventListener('click', () => {
logout();
});
// 用户信息
const userInfo = JSON.parse(localStorage.getItem('user_info') || '{}');
document.getElementById('userInfo').textContent = userInfo.username || '';
// 加载品种列表
async function loadSymbols() {
try {
const data = await api.get('/config/symbols');
const symbols = data.symbols || data || [];
renderSymbols(symbols);
} catch (err) {
showNotification('加载品种列表失败: ' + err.message, 'error');
}
}
function renderSymbols(symbols) {
const tbody = document.getElementById('symbolsTableBody');
document.getElementById('symbolCount').textContent = symbols.length + ' 个品种';
if (!symbols.length) {
tbody.innerHTML = '<tr><td colspan="6" style="text-align:center;color:var(--text-secondary);padding:40px;">暂无品种数据</td></tr>';
return;
}
tbody.innerHTML = symbols.map((s, i) => `
<tr>
<td style="font-weight:600;">${s.name || '--'}</td>
<td><code style="background:var(--bg-primary);padding:2px 8px;border-radius:4px;font-size:12px;">${s.symbol || s.code || '--'}</code></td>
<td>${s.exchange || '--'}</td>
<td><span class="badge">${s.category || '--'}</span></td>
<td><span class="badge ${s.enabled !== false ? 'badge--success' : ''}">${s.enabled !== false ? '启用' : '禁用'}</span></td>
<td>
<div class="action-btns">
<button class="btn btn--secondary btn--sm" onclick="editSymbol(${i})">编辑</button>
<button class="btn btn--danger btn--sm" onclick="deleteSymbol(${i})">删除</button>
</div>
</td>
</tr>
`).join('');
}
// 添加品种
document.getElementById('btnAddSymbol').addEventListener('click', () => {
document.getElementById('symbolModalTitle').textContent = '添加品种';
document.getElementById('symbolForm').reset();
document.getElementById('symbolModal').classList.add('active');
});
// 上传配置
document.getElementById('btnUpload').addEventListener('click', () => {
const area = document.getElementById('uploadArea');
area.style.display = area.style.display === 'none' ? 'block' : 'none';
});
document.getElementById('uploadArea').addEventListener('click', () => {
document.getElementById('fileInput').click();
});
// 关闭模态框
document.querySelectorAll('[data-close]').forEach(btn => {
btn.addEventListener('click', () => {
const modalId = btn.getAttribute('data-close');
document.getElementById(modalId).classList.remove('active');
});
});
// 表单提交
document.getElementById('symbolForm').addEventListener('submit', async (e) => {
e.preventDefault();
const name = document.getElementById('symbolName').value;
const code = document.getElementById('symbolCode').value;
const exchange = document.getElementById('symbolExchange').value;
const category = document.getElementById('symbolCategory').value;
try {
await api.post('/config/symbols', { name, symbol: code, exchange, category });
document.getElementById('symbolModal').classList.remove('active');
showNotification('品种添加成功', 'success');
loadSymbols();
} catch (err) {
showNotification('添加失败: ' + err.message, 'error');
}
});
// 全局函数
window.editSymbol = (index) => {
showNotification('编辑功能 - 待实现', 'info');
};
window.deleteSymbol = async (index) => {
if (confirm('确定要删除该品种吗?')) {
showNotification('删除功能 - 待实现', 'info');
}
};
// 初始化
loadSymbols();
</script>
</body>
</html>