2026-07-13 15:28:48 +08:00
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { computed } from 'vue'
|
|
|
|
|
import type { DatasetSplitOptions } from './types'
|
|
|
|
|
|
|
|
|
|
const props = withDefaults(defineProps<{
|
|
|
|
|
modelValue: DatasetSplitOptions
|
|
|
|
|
ariaLabelPrefix?: string
|
|
|
|
|
}>(), {
|
|
|
|
|
ariaLabelPrefix: '',
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits<{
|
|
|
|
|
'update:modelValue': [value: DatasetSplitOptions]
|
|
|
|
|
}>()
|
|
|
|
|
|
|
|
|
|
const splitTotal = computed(() => {
|
|
|
|
|
const { train, validation, test } = props.modelValue
|
|
|
|
|
return train + validation + test
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
function updateField(field: keyof DatasetSplitOptions, value: number | undefined) {
|
|
|
|
|
emit('update:modelValue', {
|
|
|
|
|
...props.modelValue,
|
|
|
|
|
[field]: Math.min(100, Math.max(0, Number(value) || 0)),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function ariaLabel(label: string) {
|
|
|
|
|
return `${props.ariaLabelPrefix}${label}比例`
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<div class="generation-option-row dataset-split-row">
|
|
|
|
|
<div class="generation-option-copy">
|
|
|
|
|
<strong>数据集划分</strong>
|
|
|
|
|
<small>按比例将生成后的问答对随机划分为训练集、验证集和测试集</small>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="dataset-split-config">
|
|
|
|
|
<div class="dataset-split-grid">
|
|
|
|
|
<label class="dataset-split-field">
|
|
|
|
|
<span>训练集</span>
|
|
|
|
|
<span class="dataset-split-input">
|
|
|
|
|
<el-input-number
|
|
|
|
|
:model-value="modelValue.train"
|
|
|
|
|
:min="0"
|
|
|
|
|
:max="100"
|
|
|
|
|
:step="1"
|
|
|
|
|
:precision="0"
|
|
|
|
|
controls-position="right"
|
|
|
|
|
:aria-label="ariaLabel('训练集')"
|
|
|
|
|
@update:model-value="updateField('train', $event)"
|
|
|
|
|
/>
|
|
|
|
|
<span>%</span>
|
|
|
|
|
</span>
|
|
|
|
|
</label>
|
|
|
|
|
<label class="dataset-split-field">
|
|
|
|
|
<span>验证集</span>
|
|
|
|
|
<span class="dataset-split-input">
|
|
|
|
|
<el-input-number
|
|
|
|
|
:model-value="modelValue.validation"
|
|
|
|
|
:min="0"
|
|
|
|
|
:max="100"
|
|
|
|
|
:step="1"
|
|
|
|
|
:precision="0"
|
|
|
|
|
controls-position="right"
|
|
|
|
|
:aria-label="ariaLabel('验证集')"
|
|
|
|
|
@update:model-value="updateField('validation', $event)"
|
|
|
|
|
/>
|
|
|
|
|
<span>%</span>
|
|
|
|
|
</span>
|
|
|
|
|
</label>
|
|
|
|
|
<label class="dataset-split-field">
|
|
|
|
|
<span>测试集</span>
|
|
|
|
|
<span class="dataset-split-input">
|
|
|
|
|
<el-input-number
|
|
|
|
|
:model-value="modelValue.test"
|
|
|
|
|
:min="0"
|
|
|
|
|
:max="100"
|
|
|
|
|
:step="1"
|
|
|
|
|
:precision="0"
|
|
|
|
|
controls-position="right"
|
|
|
|
|
:aria-label="ariaLabel('测试集')"
|
|
|
|
|
@update:model-value="updateField('test', $event)"
|
|
|
|
|
/>
|
|
|
|
|
<span>%</span>
|
|
|
|
|
</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="dataset-split-summary" :class="{ 'is-invalid': splitTotal !== 100 }">
|
|
|
|
|
<span>总计 {{ splitTotal }}%</span>
|
|
|
|
|
<span v-if="splitTotal !== 100" role="alert">
|
|
|
|
|
训练集、验证集和测试集比例总和必须为 100%
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
.generation-option-row {
|
|
|
|
|
display: flex;
|
|
|
|
|
min-height: 64px;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
gap: 24px;
|
|
|
|
|
padding: 12px 14px;
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
border: 1px solid #e2e5ec;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.generation-option-copy {
|
|
|
|
|
display: grid;
|
|
|
|
|
gap: 4px;
|
|
|
|
|
|
|
|
|
|
strong {
|
|
|
|
|
color: #344054;
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
small {
|
|
|
|
|
color: #8a93a3;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dataset-split-row {
|
2026-07-13 16:16:50 +08:00
|
|
|
align-items: flex-start;
|
2026-07-13 15:28:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dataset-split-config {
|
|
|
|
|
display: grid;
|
|
|
|
|
gap: 10px;
|
2026-07-13 16:16:50 +08:00
|
|
|
flex: 0 0 460px;
|
2026-07-13 15:28:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dataset-split-grid {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
2026-07-13 16:16:50 +08:00
|
|
|
gap: 12px;
|
2026-07-13 15:28:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dataset-split-field {
|
|
|
|
|
display: grid;
|
|
|
|
|
gap: 7px;
|
|
|
|
|
color: #5f6878;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dataset-split-input {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
|
|
|
|
:deep(.el-input-number) {
|
|
|
|
|
width: 100%;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dataset-split-summary {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
color: #2ca66a;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
|
|
&.is-invalid {
|
|
|
|
|
color: #dc2626;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 900px) {
|
2026-07-13 16:16:50 +08:00
|
|
|
.dataset-split-row {
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: stretch;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dataset-split-config {
|
|
|
|
|
flex: auto;
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-13 15:28:48 +08:00
|
|
|
.dataset-split-grid {
|
|
|
|
|
grid-template-columns: minmax(0, 1fr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dataset-split-summary {
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|