feat: 数据处理向导新增模型配置步骤

StepId 新增 model 步骤,DataProcessCreateView 增加模型选择与生成参数编排,各选项面板与样式适配新步骤流程,回归脚本补充断言。
This commit is contained in:
caoxiaozhu
2026-07-13 17:12:49 +08:00
parent 42f2efb449
commit 762d48d090
9 changed files with 257 additions and 121 deletions

View File

@@ -5,6 +5,7 @@ import { ElMessage, type UploadFile } from 'element-plus'
import { storeToRefs } from 'pinia'
import AppConfirmDialog from '@/components/AppConfirmDialog.vue'
import TaskSetupStep from './create/TaskSetupStep.vue'
import ModelSelectionStep from './create/ModelSelectionStep.vue'
import SourceUploadStep from './create/SourceUploadStep.vue'
import PreviewCompareStep from './create/PreviewCompareStep.vue'
import GenerationStep from './create/GenerationStep.vue'
@@ -22,6 +23,7 @@ import { useDataProcessGeneration } from './create/useDataProcessGeneration'
import { useModelsStore } from '@/stores/models'
import type {
ExternalDataSource,
GenerationControlOptions,
PreviewItem,
ProcessType,
StepId,
@@ -35,15 +37,17 @@ const modelsStore = useModelsStore()
const { list: modelList } = storeToRefs(modelsStore)
const generationModels = computed(() => modelList.value.filter((model) => model.type === 'LLM'))
const taskSetupRef = ref<InstanceType<typeof TaskSetupStep>>()
const modelSelectionRef = ref<InstanceType<typeof ModelSelectionStep>>()
const confirmDialogRef = ref<InstanceType<typeof AppConfirmDialog>>()
const PREVIEW_MODEL_VERSION = 'document-chunk-v2'
const WIZARD_STEPS = [
{ id: 'create', title: '创建任务', desc: '填写任务信息与处理配置' },
{ id: 'model', title: '大模型选择', desc: '选择生成模型并设置输出要求' },
{ id: 'upload', title: '上传文件', desc: '上传或接入待处理的源数据' },
{ id: 'preview', title: '数据预览', desc: '核对源文件与预览内容' },
{ id: 'generate', title: '开始生成', desc: '确认摘要并启动处理' },
{ id: 'results', title: '结果编辑与保存', desc: '检查、修改并保存结果' },
{ id: 'results', title: '编辑与保存', desc: '检查、修改并保存结果' },
] as const satisfies ReadonlyArray<{ id: StepId; title: string; desc: string }>
const currentStep = ref(0)
const currentStepId = computed<StepId>(() => WIZARD_STEPS[currentStep.value]?.id ?? 'create')
@@ -51,6 +55,9 @@ const task = reactive({ name: '', description: '' })
const processType = ref<ProcessType>('structured')
const structuredOptions = ref<StructuredProcessOptions>(createDefaultStructuredOptions())
const unstructuredOptions = ref<UnstructuredProcessOptions>(createDefaultUnstructuredOptions())
const modelSelectionOptions = computed<GenerationControlOptions>(() => (
processType.value === 'unstructured' ? unstructuredOptions.value : structuredOptions.value
))
const uploadedFiles = ref<UploadedDataFile[]>([])
const externalSource = reactive<ExternalDataSource>({
@@ -119,7 +126,8 @@ const previewFiles = computed(() => uploadedFiles.value.map((file) => {
}
}))
const primaryActionLabel = computed(() => {
if (currentStepId.value === 'create') return '继续:上传文件'
if (currentStepId.value === 'create') return '继续:选择大模型'
if (currentStepId.value === 'model') return '继续:上传文件'
if (currentStepId.value === 'upload') return '继续:数据预览'
if (currentStepId.value === 'preview') return '确认预览并继续'
if (currentStepId.value === 'results') return '保存任务'
@@ -144,6 +152,14 @@ function goToStep(stepId: StepId) {
if (nextStepIndex >= 0) currentStep.value = nextStepIndex
}
function updateModelSelectionOptions(value: GenerationControlOptions) {
if (processType.value === 'unstructured') {
unstructuredOptions.value = { ...unstructuredOptions.value, ...value }
return
}
structuredOptions.value = { ...structuredOptions.value, ...value }
}
const { persistDraft, restoreDraft } = useDataProcessDraft({
currentStepId,
task,
@@ -393,6 +409,12 @@ function resetSourceDataForProcessTypeChange() {
async function nextFromCreate() {
const valid = await taskSetupRef.value?.validate()
if (!valid) return
goToStep('model')
}
async function nextFromModel() {
const valid = await modelSelectionRef.value?.validate()
if (!valid) return
goToStep('upload')
}
@@ -504,6 +526,10 @@ async function handlePrimaryAction() {
await nextFromCreate()
return
}
if (currentStepId.value === 'model') {
await nextFromModel()
return
}
if (currentStepId.value === 'upload') {
nextFromUpload()
return
@@ -596,27 +622,31 @@ onMounted(() => {
<div class="wizard-main-inner">
<div class="wizard-steps-container">
<div class="custom-wizard-steps">
<div
v-for="(step, index) in WIZARD_STEPS"
:key="step.id"
class="step-item"
:class="{
'is-active': currentStep === index,
'is-completed': currentStep > index
}"
:aria-current="currentStep === index ? 'step' : undefined"
>
<div v-if="index !== 0" class="step-connector"></div>
<div class="step-node">
<div class="step-icon">
<i v-if="currentStep > index" class="fa fa-check" />
<span v-else>{{ index + 1 }}</span>
</div>
<div class="step-text">
<div class="step-title">{{ step.title }}</div>
<template v-for="(step, index) in WIZARD_STEPS" :key="step.id">
<div
v-if="index !== 0"
class="step-connector"
:class="{ 'is-active': currentStep >= index }"
></div>
<div
class="step-item"
:class="{
'is-active': currentStep === index,
'is-completed': currentStep > index
}"
:aria-current="currentStep === index ? 'step' : undefined"
>
<div class="step-node">
<div class="step-icon">
<i v-if="currentStep > index" class="fa fa-check" />
<span v-else>{{ index + 1 }}</span>
</div>
<div class="step-text">
<div class="step-title">{{ step.title }}</div>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
@@ -629,7 +659,14 @@ onMounted(() => {
v-model:process-type="processType"
v-model:structured-options="structuredOptions"
v-model:unstructured-options="unstructuredOptions"
:generation-models="generationModels"
/>
<ModelSelectionStep
v-else-if="currentStepId === 'model'"
ref="modelSelectionRef"
:options="modelSelectionOptions"
:models="generationModels"
@update:options="updateModelSelectionOptions"
/>
<SourceUploadStep