128 lines
4.0 KiB
TypeScript
128 lines
4.0 KiB
TypeScript
|
|
import { reactive, ref, type Ref } from 'vue'
|
||
|
|
import { ElMessage } from 'element-plus'
|
||
|
|
import { createResults } from './previewModel'
|
||
|
|
import type {
|
||
|
|
GenerationState,
|
||
|
|
PreviewItem,
|
||
|
|
ProcessType,
|
||
|
|
ResultItem,
|
||
|
|
StructuredProcessOptions,
|
||
|
|
UnstructuredProcessOptions,
|
||
|
|
} from './types'
|
||
|
|
|
||
|
|
interface GenerationBindings {
|
||
|
|
previewItems: Ref<PreviewItem[]>
|
||
|
|
processType: Ref<ProcessType>
|
||
|
|
structuredOptions: Ref<StructuredProcessOptions>
|
||
|
|
unstructuredOptions: Ref<UnstructuredProcessOptions>
|
||
|
|
dirty: Ref<boolean>
|
||
|
|
}
|
||
|
|
|
||
|
|
export function useDataProcessGeneration(bindings: GenerationBindings) {
|
||
|
|
const results = ref<ResultItem[]>([])
|
||
|
|
const selectedResultId = ref<string | null>(null)
|
||
|
|
const generation = reactive<GenerationState>({
|
||
|
|
status: 'idle',
|
||
|
|
progress: 0,
|
||
|
|
message: '确认摘要后即可开始生成,过程中可查看实时进度。',
|
||
|
|
})
|
||
|
|
let generationTimer: ReturnType<typeof setInterval> | null = null
|
||
|
|
|
||
|
|
function stopGenerationTimer() {
|
||
|
|
if (generationTimer) clearInterval(generationTimer)
|
||
|
|
generationTimer = null
|
||
|
|
}
|
||
|
|
|
||
|
|
function resetDownstream() {
|
||
|
|
stopGenerationTimer()
|
||
|
|
generation.status = 'idle'
|
||
|
|
generation.progress = 0
|
||
|
|
generation.message = '确认摘要后即可开始生成,过程中可查看实时进度。'
|
||
|
|
results.value = []
|
||
|
|
selectedResultId.value = null
|
||
|
|
}
|
||
|
|
|
||
|
|
function startGeneration() {
|
||
|
|
stopGenerationTimer()
|
||
|
|
generation.status = 'running'
|
||
|
|
generation.progress = 0
|
||
|
|
generation.message = '正在应用预览修改并生成标准化结果,请稍候。'
|
||
|
|
|
||
|
|
generationTimer = setInterval(() => {
|
||
|
|
generation.progress = Math.min(100, generation.progress + 8)
|
||
|
|
if (generation.progress < 100) return
|
||
|
|
|
||
|
|
stopGenerationTimer()
|
||
|
|
generation.status = 'success'
|
||
|
|
results.value = createResults(
|
||
|
|
bindings.previewItems.value,
|
||
|
|
bindings.processType.value === 'structured'
|
||
|
|
? bindings.structuredOptions.value
|
||
|
|
: bindings.processType.value === 'unstructured'
|
||
|
|
? bindings.unstructuredOptions.value
|
||
|
|
: undefined,
|
||
|
|
)
|
||
|
|
generation.message = `已完成 ${results.value.length.toLocaleString()} 条数据处理,可进入结果页检查。`
|
||
|
|
selectedResultId.value = results.value[0]?.id ?? null
|
||
|
|
bindings.dirty.value = true
|
||
|
|
ElMessage.success('数据处理完成')
|
||
|
|
}, 180)
|
||
|
|
}
|
||
|
|
|
||
|
|
function stopGeneration() {
|
||
|
|
stopGenerationTimer()
|
||
|
|
generation.status = 'failed'
|
||
|
|
generation.message = '任务已停止,预览修改仍然保留,可以重新生成。'
|
||
|
|
}
|
||
|
|
|
||
|
|
function updateResultField(id: string, field: 'instruction' | 'input' | 'output', value: string) {
|
||
|
|
const item = results.value.find((entry) => entry.id === id)
|
||
|
|
if (!item) return
|
||
|
|
item[field] = value
|
||
|
|
const valid = item.instruction.trim() && item.output.trim()
|
||
|
|
item.error = valid ? undefined : 'Instruction 和 Output 不能为空'
|
||
|
|
const changed = item.instruction !== item.originalInstruction
|
||
|
|
|| item.input !== item.originalInput
|
||
|
|
|| item.output !== item.originalOutput
|
||
|
|
item.status = item.error ? 'invalid' : changed ? 'modified' : 'valid'
|
||
|
|
bindings.dirty.value = true
|
||
|
|
}
|
||
|
|
|
||
|
|
function restoreResult(id: string) {
|
||
|
|
const item = results.value.find((entry) => entry.id === id)
|
||
|
|
if (!item) return
|
||
|
|
item.instruction = item.originalInstruction
|
||
|
|
item.input = item.originalInput
|
||
|
|
item.output = item.originalOutput
|
||
|
|
item.error = undefined
|
||
|
|
item.status = 'valid'
|
||
|
|
bindings.dirty.value = true
|
||
|
|
}
|
||
|
|
|
||
|
|
function validateResults() {
|
||
|
|
let firstInvalidId: string | null = null
|
||
|
|
for (const item of results.value) {
|
||
|
|
if (!item.instruction.trim() || !item.output.trim()) {
|
||
|
|
item.error = 'Instruction 和 Output 不能为空'
|
||
|
|
item.status = 'invalid'
|
||
|
|
firstInvalidId ??= item.id
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (firstInvalidId) selectedResultId.value = firstInvalidId
|
||
|
|
return firstInvalidId == null
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
generation,
|
||
|
|
results,
|
||
|
|
selectedResultId,
|
||
|
|
resetDownstream,
|
||
|
|
restoreResult,
|
||
|
|
startGeneration,
|
||
|
|
stopGeneration,
|
||
|
|
stopGenerationTimer,
|
||
|
|
updateResultField,
|
||
|
|
validateResults,
|
||
|
|
}
|
||
|
|
}
|