/** * Train tab component — unified training with [鼠标 | 滚轮] sub-tabs. */ import { fetchSSE } from './api.js' const template = `
JointCVAE 联合模型 {{ mouseTrain.epoch }} / {{ mouseTrain.total }}
loss = {{ mouseTrain.loss.toFixed(4) }}
训练完成!点击分布:μ = {{ mouseTrain.mu.toFixed(1) }} ms,σ = {{ mouseTrain.sigma.toFixed(1) }} ms
{{ mouseTrain.error }}
ScrollCVAE 滚轮模型 {{ scrollTrain.epoch }} / {{ scrollTrain.total }}
loss = {{ scrollTrain.loss.toFixed(4) }}
滚轮模型训练完成!
{{ scrollTrain.error }}
` export const TrainView = { template, emits: ['status-changed'], setup(props, { emit }) { const { ref, reactive, computed } = Vue const subTab = ref('mouse') // ── 鼠标训练 ── const mouseTrain = reactive({ epochs: 100, running: false, done: false, epoch: 0, total: 0, loss: null, mu: 0, sigma: 0, error: '', }) const mouseTrainPct = computed(() => { if (!mouseTrain.total) return 0 return Math.round(mouseTrain.epoch / mouseTrain.total * 100) }) function startMouseTrain() { mouseTrain.running = true; mouseTrain.done = false; mouseTrain.error = '' mouseTrain.epoch = 0; mouseTrain.total = mouseTrain.epochs; mouseTrain.loss = null fetchSSE('/api/train', { epochs: mouseTrain.epochs }, (msg) => { if (msg.error) { mouseTrain.error = msg.error; mouseTrain.running = false; return } if (msg.done) { mouseTrain.mu = msg.mu || 0; mouseTrain.sigma = msg.sigma || 0 mouseTrain.running = false; mouseTrain.done = true; emit('status-changed'); return } mouseTrain.epoch = msg.epoch; mouseTrain.total = msg.total; mouseTrain.loss = msg.loss }) } // ── 滚轮训练 ── const scrollTrain = reactive({ epochs: 100, running: false, done: false, epoch: 0, total: 0, loss: null, error: '', }) const scrollTrainPct = computed(() => { if (!scrollTrain.total) return 0 return Math.round(scrollTrain.epoch / scrollTrain.total * 100) }) function startScrollTrain() { scrollTrain.running = true; scrollTrain.done = false; scrollTrain.error = '' scrollTrain.epoch = 0; scrollTrain.total = scrollTrain.epochs; scrollTrain.loss = null fetchSSE('/api/scroll/train', { epochs: scrollTrain.epochs }, (msg) => { if (msg.error) { scrollTrain.error = msg.error; scrollTrain.running = false; return } if (msg.done) { scrollTrain.running = false; scrollTrain.done = true; emit('status-changed'); return } scrollTrain.epoch = msg.epoch; scrollTrain.total = msg.total; scrollTrain.loss = msg.loss }) } return { subTab, mouseTrain, scrollTrain, mouseTrainPct, scrollTrainPct, startMouseTrain, startScrollTrain, } } }