feat(paper/live): 生命周期管理补全: paper停止/恢复(实走20:30 step跳过stopped)/删除(连带净值成交持仓挂单)/编辑(名称标的资金); live删除(运行中拒绝)/编辑(stopped才可改); 前端列表+结果页按钮/编辑弹窗/删除确认 [vps]
CI/CD / test (push) Successful in 10s
CI/CD / nas-deploy (push) Failing after 11s
CI/CD / nas-verify (push) Has been skipped

This commit is contained in:
2026-08-13 18:27:32 +08:00
parent d8c156e6de
commit ccf958c5d6
8 changed files with 488 additions and 8 deletions
+66 -2
View File
@@ -2,8 +2,11 @@
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
listLives, startLive, stopLive,
listLives, startLive, stopLive, deleteLive, updateLive,
type LiveAccount,
} from '@/api/live'
@@ -73,6 +76,51 @@ function goNew(): void {
router.push('/live/new')
}
async function onDelete(a: LiveAccount): Promise<void> {
try {
await ElMessageBox.confirm(
`删除实盘实例 #${a.id}${a.name})?成交/持仓/余额数据将一并删除,不可恢复。`,
'删除确认',
{ type: 'warning' },
)
} catch {
return
}
actionLoading.value = a.id
try {
await deleteLive(a.id)
ElMessage.success(`#${a.id} 已删除`)
await refreshSilent()
} catch (e: unknown) {
ElMessage.error(e instanceof Error ? e.message : '删除失败')
} finally {
actionLoading.value = null
}
}
// 编辑(仅 stopped 可改;后端运行中会 400)
const editVisible = ref(false)
const editForm = reactive({ id: 0, name: '', account: '', vt_symbol: '', strategy_name: '', interval: '' })
function openEdit(a: LiveAccount): void {
editForm.id = a.id
editForm.name = a.name
editForm.account = a.account
editForm.vt_symbol = a.vt_symbol
editForm.strategy_name = a.strategy_name
editForm.interval = a.interval
editVisible.value = true
}
async function saveEdit(): Promise<void> {
try {
await updateLive(editForm.id, { ...editForm })
ElMessage.success(`#${editForm.id} 已更新`)
editVisible.value = false
await refreshSilent()
} catch (e: unknown) {
ElMessage.error(e instanceof Error ? e.message : '更新失败')
}
}
async function onStart(a: LiveAccount): Promise<void> {
actionLoading.value = a.id
try {
@@ -178,7 +226,7 @@ async function onStop(a: LiveAccount): Promise<void> {
</span>
</template>
</el-table-column>
<el-table-column label="操作" width="180">
<el-table-column label="操作" width="240">
<template #default="{ row }">
<el-button
v-if="row.status !== 'running'"
@@ -193,10 +241,26 @@ async function onStop(a: LiveAccount): Promise<void> {
@click="onStop(row)"
>停止</el-button>
<el-button link type="primary" size="small" @click="goMonitor(row)">监控</el-button>
<el-button v-if="row.status !== 'running'" link type="primary" size="small" @click="openEdit(row)">编辑</el-button>
<el-button v-if="row.status !== 'running'" link type="danger" size="small" :loading="actionLoading === row.id" @click="onDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog v-model="editVisible" title="编辑实盘实例" width="480px">
<el-form :model="editForm" label-width="90px">
<el-form-item label="名称"><el-input v-model="editForm.name" /></el-form-item>
<el-form-item label="交易账号"><el-input v-model="editForm.account" /></el-form-item>
<el-form-item label="标的"><el-input v-model="editForm.vt_symbol" /></el-form-item>
<el-form-item label="策略实例名"><el-input v-model="editForm.strategy_name" /></el-form-item>
<el-form-item label="频率"><el-input v-model="editForm.interval" /></el-form-item>
</el-form>
<template #footer>
<el-button @click="editVisible = false">取消</el-button>
<el-button type="primary" @click="saveEdit">保存</el-button>
</template>
</el-dialog>
</div>
</template>