feat(strategy): TODO#68-#75八项全做+导航自测——#68灯职责拆分:实走/影子在跑=直达/paper/live/{aid}监控页,实盘在跑=/live/monitor/{aid},未跑=发起;回放灯done=直达/paper/result/{aid}(run_meta.replay.account_id);#69回测任务按实例过滤:backtest_stats加instance_id列(ALTER迁移)+_write_back落列+GET /task?instance=N+任务中心过滤条+策略库「回测历史」按钮;回测灯done=直达最新结果页(run_meta.backtest.task_id按前缀分流),跑过无结果=任务中心过滤;#70模拟盘创建后直接跳列表(不跳结果/监控页);列宽重排(策略/实例150模式96频率60操作250,折行实测消除);#71列内容对齐实盘:策略/实例列显示实例名(instances映射,#id退化)+持仓数列(list_papers顺带count volume>0)+删创建时间列(净值日期已含);#72实盘名自动生成={实例名}_v{YYYYMMDD}{minor}(同实例同日递增,listLives计数);模拟盘名={实例名}·{模式};#73术语统一档案→实例(全局8文件UI文案+后端409提示,精确短语防误伤,spec比喻保留文档);#74MonacoDiff v4:优先monaco原生diff(差异高亮),挂载450ms自检original栏占比<30%自动降级双只读编辑器(滚动联动)——全屏模态下大概率吃到原生diff;#75收益标签与数值同源(retInfoOf:运行ret优先含kind,fallback run_returns,标签跟随数值来源,根治影子1044%实为回测收益挂影子标签);927绿+build绿+dev浏览器自测:策略库6入口(回测历史/模拟历史/实盘历史/回测灯/实走灯直达监控/组合无回放)与模拟盘列表新列全过 [vps]
This commit is contained in:
@@ -1,16 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { getTasks, getTaskParams, deleteTask, type TaskListItem } from '@/api/backtest'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const tasks = ref<TaskListItem[]>([])
|
||||
const loading = ref(false)
|
||||
const deleting = ref(false)
|
||||
const selection = ref<TaskListItem[]>([])
|
||||
// reserve-selection 后勾选按 row-key 持久;删除完要显式清表内勾选
|
||||
const tableRef = ref()
|
||||
// #69 按实例过滤(策略库「回测历史」跳 ?instance=N 只看该实例的任务)
|
||||
const instFilter = route.query.instance && !Array.isArray(route.query.instance)
|
||||
? ref<number | null>(Number(route.query.instance))
|
||||
: ref<number | null>(null)
|
||||
|
||||
// 筛选
|
||||
const typeFilter = ref<'all' | 'cta' | 'portfolio' | 'optimize' | 'factor'>('all')
|
||||
@@ -94,7 +99,7 @@ onUnmounted(() => {
|
||||
async function load(): Promise<void> {
|
||||
loading.value = true
|
||||
try {
|
||||
tasks.value = await getTasks()
|
||||
tasks.value = await getTasks(undefined, instFilter.value ?? undefined)
|
||||
} catch {
|
||||
ElMessage.error('任务列表加载失败')
|
||||
} finally {
|
||||
@@ -110,7 +115,7 @@ function hasActive(): boolean {
|
||||
}
|
||||
async function silentRefresh(): Promise<void> {
|
||||
try {
|
||||
tasks.value = await getTasks()
|
||||
tasks.value = await getTasks(undefined, instFilter.value ?? undefined)
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
@@ -232,6 +237,7 @@ function durationText(row: TaskListItem): string {
|
||||
<p class="page-subtitle">回测 / 参数优化 / 因子分析 的全部任务 · 完成 {{ counts.done }} · 失败 {{ counts.failed }}</p>
|
||||
</div>
|
||||
<div class="head-actions">
|
||||
<el-button v-if="instFilter != null" size="small" @click="router.push('/backtest/history')">实例 #{{ instFilter }} 过滤中 · 查看</el-button>
|
||||
<el-button type="danger" plain :disabled="!selection.length" :loading="deleting" @click="doDelete(selection)">
|
||||
删除选中({{ selection.length }})
|
||||
</el-button>
|
||||
|
||||
@@ -246,13 +246,13 @@ async function onSubmit(): Promise<void> {
|
||||
<el-card class="blk" shadow="never" v-loading="loading">
|
||||
<template #header><span class="section-title">策略与参数</span></template>
|
||||
<el-form :model="form" label-width="120px">
|
||||
<el-form-item label="策略 / 档案">
|
||||
<el-form-item label="策略 / 实例">
|
||||
<el-select v-model="form.strategy" placeholder="选择策略" style="width: 300px">
|
||||
<el-option v-for="s in strategies" :key="s.name" :label="s.name" :value="s.name" />
|
||||
</el-select>
|
||||
<el-select
|
||||
:model-value="selectedInstanceId" clearable filterable
|
||||
placeholder="实例档案(可选·带出参数)"
|
||||
placeholder="策略实例(可选·带出参数)"
|
||||
style="width: 260px; margin-left: 8px"
|
||||
@update:model-value="onPickInstance"
|
||||
>
|
||||
@@ -261,7 +261,7 @@ async function onSubmit(): Promise<void> {
|
||||
:label="`${i.name}(${i.interval})`"
|
||||
/>
|
||||
</el-select>
|
||||
<span v-if="selectedInstanceId != null" class="muted form-hint">完成后回写档案 #{{ selectedInstanceId }}</span>
|
||||
<span v-if="selectedInstanceId != null" class="muted form-hint">完成后回写实例 #{{ selectedInstanceId }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="paramsList.length" label="参数">
|
||||
<div class="param-grid">
|
||||
|
||||
@@ -495,13 +495,13 @@ function fmtNum(v: number | null | undefined, digits = 2): string {
|
||||
</el-select>
|
||||
<span class="muted form-hint">MVP 默认 HS300 子集(20-30 只),快速验证链路</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="策略 / 档案">
|
||||
<el-form-item label="策略 / 实例">
|
||||
<el-select v-model="form.strategy" style="width: 300px">
|
||||
<el-option v-for="opt in strategyOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||
</el-select>
|
||||
<el-select
|
||||
:model-value="selectedInstanceId" clearable filterable
|
||||
placeholder="实例档案(可选·带出参数)"
|
||||
placeholder="策略实例(可选·带出参数)"
|
||||
style="width: 260px; margin-left: 8px"
|
||||
@update:model-value="onPickInstance"
|
||||
>
|
||||
@@ -510,7 +510,7 @@ function fmtNum(v: number | null | undefined, digits = 2): string {
|
||||
:label="`${i.name}(${i.interval})`"
|
||||
/>
|
||||
</el-select>
|
||||
<span v-if="selectedInstanceId != null" class="muted form-hint">完成后回写档案 #{{ selectedInstanceId }}</span>
|
||||
<span v-if="selectedInstanceId != null" class="muted form-hint">完成后回写实例 #{{ selectedInstanceId }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="选股池上限">
|
||||
<el-input-number v-model="form.max_pool" :min="0" :step="10" :controls="false" style="width: 220px" />
|
||||
|
||||
Reference in New Issue
Block a user