2026-07-13 15:28:48 +08:00
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
import { computed, ref, watch } from 'vue'
|
|
|
|
|
|
import type {
|
|
|
|
|
|
ChunkMethod,
|
|
|
|
|
|
GenerationControlOptions,
|
|
|
|
|
|
UnstructuredPreprocessOption,
|
|
|
|
|
|
UnstructuredProcessOptions,
|
|
|
|
|
|
} from './types'
|
|
|
|
|
|
import DatasetSplitEditor from './DatasetSplitEditor.vue'
|
|
|
|
|
|
import GenerationOptionsPanel from './GenerationOptionsPanel.vue'
|
|
|
|
|
|
|
|
|
|
|
|
const props = defineProps<{
|
|
|
|
|
|
options: UnstructuredProcessOptions
|
|
|
|
|
|
validationAttempted: boolean
|
2026-07-13 17:12:49 +08:00
|
|
|
|
qualityValidationMessage: string
|
2026-07-13 15:28:48 +08:00
|
|
|
|
chunkValidationMessage: string
|
|
|
|
|
|
}>()
|
|
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits<{
|
|
|
|
|
|
'update:options': [value: UnstructuredProcessOptions]
|
|
|
|
|
|
}>()
|
|
|
|
|
|
|
|
|
|
|
|
const SMART_PREPROCESS_OPTIONS: UnstructuredPreprocessOption[] = [
|
|
|
|
|
|
'clean_invalid_content',
|
|
|
|
|
|
'detect_document_structure',
|
|
|
|
|
|
'merge_short_content',
|
|
|
|
|
|
'filter_low_quality',
|
|
|
|
|
|
'deduplicate_content',
|
|
|
|
|
|
'preserve_context',
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
const CHUNK_METHODS: Array<{ value: ChunkMethod; label: string }> = [
|
|
|
|
|
|
{ value: 'semantic', label: '自动语义切分' },
|
|
|
|
|
|
{ value: 'heading', label: '按标题和段落' },
|
|
|
|
|
|
{ value: 'fixed', label: '按固定长度' },
|
|
|
|
|
|
{ value: 'custom', label: '自定义分隔符' },
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
const UNSTRUCTURED_NUMBER_LIMITS = {
|
|
|
|
|
|
chunkSize: { min: 200, max: 2000 },
|
|
|
|
|
|
chunkOverlap: { min: 0, max: 500 },
|
|
|
|
|
|
minChunkSize: { min: 20, max: 500 },
|
|
|
|
|
|
qaPairsPerChunk: { min: 1, max: 3 },
|
|
|
|
|
|
} as const
|
|
|
|
|
|
|
|
|
|
|
|
type UnstructuredNumberField = keyof typeof UNSTRUCTURED_NUMBER_LIMITS
|
|
|
|
|
|
|
|
|
|
|
|
const smartPreprocessEnabled = computed(() => SMART_PREPROCESS_OPTIONS.every(
|
|
|
|
|
|
(option) => props.options.preprocessOptions.includes(option),
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
|
|
const desensitizeEnabled = computed(() => props.options.preprocessOptions.includes('desensitize'))
|
|
|
|
|
|
|
|
|
|
|
|
const preserveSpecialContentEnabled = computed(() => (
|
|
|
|
|
|
props.options.preserveTables
|
|
|
|
|
|
&& props.options.preserveCodeBlocks
|
|
|
|
|
|
&& props.options.preserveLists
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
|
|
function updateField<K extends keyof UnstructuredProcessOptions>(
|
|
|
|
|
|
field: K,
|
|
|
|
|
|
value: UnstructuredProcessOptions[K],
|
|
|
|
|
|
) {
|
|
|
|
|
|
emit('update:options', { ...props.options, [field]: value })
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function updateGenerationOptions(value: GenerationControlOptions) {
|
|
|
|
|
|
emit('update:options', { ...props.options, ...value })
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function updateSmartPreprocess(value: string | number | boolean) {
|
|
|
|
|
|
const enabled = Boolean(value)
|
|
|
|
|
|
const remainingOptions = props.options.preprocessOptions.filter(
|
|
|
|
|
|
(option) => !SMART_PREPROCESS_OPTIONS.includes(option),
|
|
|
|
|
|
)
|
|
|
|
|
|
updateField(
|
|
|
|
|
|
'preprocessOptions',
|
|
|
|
|
|
enabled ? [...SMART_PREPROCESS_OPTIONS, ...remainingOptions] : remainingOptions,
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function updateDesensitize(value: string | number | boolean) {
|
|
|
|
|
|
const preprocessOptions: UnstructuredPreprocessOption[] = props.options.preprocessOptions.filter(
|
|
|
|
|
|
(option) => option !== 'desensitize',
|
|
|
|
|
|
)
|
|
|
|
|
|
if (Boolean(value)) preprocessOptions.push('desensitize')
|
|
|
|
|
|
updateField('preprocessOptions', preprocessOptions)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function updateSpecialContentProtection(value: string | number | boolean) {
|
|
|
|
|
|
const enabled = Boolean(value)
|
|
|
|
|
|
emit('update:options', {
|
|
|
|
|
|
...props.options,
|
|
|
|
|
|
preserveTables: enabled,
|
|
|
|
|
|
preserveCodeBlocks: enabled,
|
|
|
|
|
|
preserveLists: enabled,
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function updateUnstructuredNumber(field: UnstructuredNumberField, value: number | undefined) {
|
|
|
|
|
|
const limits = UNSTRUCTURED_NUMBER_LIMITS[field]
|
|
|
|
|
|
const parsedValue = Number(value)
|
|
|
|
|
|
const nextValue = Number.isFinite(parsedValue) ? parsedValue : limits.min
|
|
|
|
|
|
updateField(field, Math.min(limits.max, Math.max(limits.min, nextValue)))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function revealValidation() {
|
2026-07-13 16:39:16 +08:00
|
|
|
|
// Advanced settings are now flattened, no need to open toggle
|
2026-07-13 15:28:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
defineExpose({ revealValidation })
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<div class="form-section unstructured-options-section">
|
|
|
|
|
|
<div class="section-title-row">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<h3>预处理选项</h3>
|
|
|
|
|
|
<p>默认使用推荐策略,只需决定是否需要脱敏</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-07-13 16:16:50 +08:00
|
|
|
|
<div class="preprocess-option-grid">
|
|
|
|
|
|
<label class="preprocess-option" :class="{ 'is-checked': smartPreprocessEnabled }">
|
|
|
|
|
|
<el-checkbox
|
2026-07-13 15:28:48 +08:00
|
|
|
|
:model-value="smartPreprocessEnabled"
|
|
|
|
|
|
@update:model-value="updateSmartPreprocess"
|
|
|
|
|
|
/>
|
2026-07-13 16:16:50 +08:00
|
|
|
|
<span class="preprocess-option-copy">
|
|
|
|
|
|
<strong>智能预处理</strong>
|
|
|
|
|
|
<small>自动清理、解析、去重及保留上下文</small>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</label>
|
|
|
|
|
|
|
|
|
|
|
|
<label class="preprocess-option" :class="{ 'is-checked': desensitizeEnabled }">
|
|
|
|
|
|
<el-checkbox
|
2026-07-13 15:28:48 +08:00
|
|
|
|
:model-value="desensitizeEnabled"
|
|
|
|
|
|
@update:model-value="updateDesensitize"
|
|
|
|
|
|
/>
|
2026-07-13 16:16:50 +08:00
|
|
|
|
<span class="preprocess-option-copy">
|
|
|
|
|
|
<strong>敏感信息脱敏</strong>
|
|
|
|
|
|
<small>处理姓名、手机号等隐私信息</small>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</label>
|
2026-07-13 16:39:16 +08:00
|
|
|
|
|
|
|
|
|
|
<label class="preprocess-option" :class="{ 'is-checked': preserveSpecialContentEnabled }">
|
|
|
|
|
|
<el-checkbox
|
|
|
|
|
|
:model-value="preserveSpecialContentEnabled"
|
|
|
|
|
|
@update:model-value="updateSpecialContentProtection"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<span class="preprocess-option-copy">
|
|
|
|
|
|
<strong>保护表格、代码和列表</strong>
|
|
|
|
|
|
<small>避免切分点破坏特殊内容块的完整性</small>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</label>
|
2026-07-13 15:28:48 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="form-section chunk-options-section">
|
|
|
|
|
|
<div class="section-title-row">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<h3>切分选项</h3>
|
|
|
|
|
|
<p>以语义完整为优先,将长文档拆成可独立生成问答的内容块</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="chunk-settings-grid is-basic">
|
|
|
|
|
|
<label class="config-field">
|
|
|
|
|
|
<span class="config-field-label">切分方式</span>
|
|
|
|
|
|
<el-select
|
|
|
|
|
|
:model-value="options.chunkMethod"
|
|
|
|
|
|
aria-label="切分方式"
|
|
|
|
|
|
@update:model-value="updateField('chunkMethod', $event)"
|
|
|
|
|
|
>
|
|
|
|
|
|
<el-option
|
|
|
|
|
|
v-for="method in CHUNK_METHODS"
|
|
|
|
|
|
:key="method.value"
|
|
|
|
|
|
:label="method.label"
|
|
|
|
|
|
:value="method.value"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
<small>推荐使用自动语义切分,在长度限制内优先保留完整句段</small>
|
|
|
|
|
|
</label>
|
|
|
|
|
|
|
|
|
|
|
|
<label class="config-field">
|
|
|
|
|
|
<span class="config-field-label">切片长度</span>
|
|
|
|
|
|
<span class="unit-input">
|
|
|
|
|
|
<el-input-number
|
|
|
|
|
|
:model-value="options.chunkSize"
|
|
|
|
|
|
:min="200"
|
|
|
|
|
|
:max="2000"
|
|
|
|
|
|
:step="50"
|
|
|
|
|
|
:precision="0"
|
|
|
|
|
|
controls-position="right"
|
|
|
|
|
|
aria-label="切片长度"
|
|
|
|
|
|
@update:model-value="updateUnstructuredNumber('chunkSize', $event)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<span>Token</span>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
<small>单个切片的目标上限,默认 800 Token</small>
|
|
|
|
|
|
</label>
|
|
|
|
|
|
|
|
|
|
|
|
<label class="config-field">
|
|
|
|
|
|
<span class="config-field-label">重叠长度</span>
|
|
|
|
|
|
<span class="unit-input">
|
|
|
|
|
|
<el-input-number
|
|
|
|
|
|
:model-value="options.chunkOverlap"
|
|
|
|
|
|
:min="0"
|
|
|
|
|
|
:max="500"
|
|
|
|
|
|
:step="10"
|
|
|
|
|
|
:precision="0"
|
|
|
|
|
|
controls-position="right"
|
|
|
|
|
|
aria-label="重叠长度"
|
|
|
|
|
|
@update:model-value="updateUnstructuredNumber('chunkOverlap', $event)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<span>Token</span>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
<small>在相邻切片中最多重复保留的上下文,默认 100 Token</small>
|
|
|
|
|
|
</label>
|
|
|
|
|
|
<label class="config-field">
|
|
|
|
|
|
<span class="config-field-label">最小切片长度</span>
|
|
|
|
|
|
<span class="unit-input">
|
|
|
|
|
|
<el-input-number
|
|
|
|
|
|
:model-value="options.minChunkSize"
|
|
|
|
|
|
:min="20"
|
|
|
|
|
|
:max="500"
|
|
|
|
|
|
:step="10"
|
|
|
|
|
|
:precision="0"
|
|
|
|
|
|
controls-position="right"
|
|
|
|
|
|
aria-label="最小切片长度"
|
|
|
|
|
|
@update:model-value="updateUnstructuredNumber('minChunkSize', $event)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<span>Token</span>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
<small>过短的尾部内容会尽量并入前一个切片</small>
|
|
|
|
|
|
</label>
|
|
|
|
|
|
|
|
|
|
|
|
<label v-if="options.chunkMethod === 'custom'" class="config-field">
|
|
|
|
|
|
<span class="config-field-label">自定义分隔符</span>
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
:model-value="options.customDelimiter"
|
|
|
|
|
|
maxlength="40"
|
|
|
|
|
|
show-word-limit
|
|
|
|
|
|
placeholder="例如:--- 或 ###"
|
|
|
|
|
|
aria-label="自定义分隔符"
|
|
|
|
|
|
@update:model-value="updateField('customDelimiter', $event)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<small>系统会优先在分隔符位置结束当前切片</small>
|
|
|
|
|
|
</label>
|
|
|
|
|
|
</div>
|
2026-07-13 16:39:16 +08:00
|
|
|
|
|
|
|
|
|
|
<p class="chunk-estimation-note">
|
|
|
|
|
|
Token 数为轻量估算值,实际长度以训练使用的模型分词器为准。
|
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p v-if="chunkValidationMessage" class="option-validation-message" role="alert">
|
|
|
|
|
|
{{ chunkValidationMessage }}
|
|
|
|
|
|
</p>
|
2026-07-13 15:28:48 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="form-section generation-options-section">
|
|
|
|
|
|
<div class="section-title-row">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<h3>生成选项</h3>
|
|
|
|
|
|
<p>只保留会直接影响输出的核心设置</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="generation-option-list">
|
|
|
|
|
|
<GenerationOptionsPanel
|
|
|
|
|
|
:options="options"
|
|
|
|
|
|
section="quality"
|
2026-07-13 17:12:49 +08:00
|
|
|
|
:validation-message="validationAttempted ? qualityValidationMessage : ''"
|
2026-07-13 15:28:48 +08:00
|
|
|
|
@update:options="updateGenerationOptions"
|
|
|
|
|
|
/>
|
2026-07-13 16:39:16 +08:00
|
|
|
|
|
2026-07-13 15:28:48 +08:00
|
|
|
|
|
|
|
|
|
|
<div class="generation-option-row">
|
|
|
|
|
|
<div class="generation-option-copy">
|
|
|
|
|
|
<strong>每个切片生成数量</strong>
|
|
|
|
|
|
<small>每个内容切片最多生成 3 个不同角度的问答对</small>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<el-input-number
|
|
|
|
|
|
:model-value="options.qaPairsPerChunk"
|
|
|
|
|
|
:min="1"
|
|
|
|
|
|
:max="3"
|
|
|
|
|
|
:step="1"
|
|
|
|
|
|
:precision="0"
|
|
|
|
|
|
controls-position="right"
|
|
|
|
|
|
aria-label="每个切片生成数量"
|
|
|
|
|
|
@update:model-value="updateUnstructuredNumber('qaPairsPerChunk', $event)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<DatasetSplitEditor
|
|
|
|
|
|
:model-value="options.datasetSplit"
|
|
|
|
|
|
aria-label-prefix="非结构化"
|
|
|
|
|
|
@update:model-value="updateField('datasetSplit', $event)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
|
.form-section {
|
|
|
|
|
|
padding: 0 0 26px;
|
|
|
|
|
|
margin-bottom: 26px;
|
|
|
|
|
|
border-bottom: 1px solid #edf0f5;
|
|
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
border-bottom: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
h3 {
|
|
|
|
|
|
margin: 0 0 16px;
|
|
|
|
|
|
color: #2f3747;
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
font-weight: 650;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.section-title-row {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
gap: 16px;
|
|
|
|
|
|
|
|
|
|
|
|
h3 {
|
|
|
|
|
|
margin-bottom: 5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
p {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
color: #8a93a3;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.generation-option-list {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-13 16:16:50 +08:00
|
|
|
|
.preprocess-option-grid {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
|
}
|
2026-07-13 15:28:48 +08:00
|
|
|
|
|
2026-07-13 16:16:50 +08:00
|
|
|
|
.preprocess-option {
|
|
|
|
|
|
display: flex;
|
2026-07-13 16:39:16 +08:00
|
|
|
|
gap: 10px;
|
2026-07-13 16:16:50 +08:00
|
|
|
|
width: 100%;
|
|
|
|
|
|
min-height: 64px;
|
|
|
|
|
|
margin-right: 0;
|
|
|
|
|
|
padding: 12px 14px;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
border: 1px solid #e2e5ec;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
transition: border-color 0.18s ease, background-color 0.18s ease;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
border-color: #b7b2f7;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.is-checked {
|
|
|
|
|
|
background: #fafaff;
|
|
|
|
|
|
border-color: #8b82f4;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-checkbox__input) {
|
|
|
|
|
|
margin-top: 3px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-checkbox__label) {
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
padding-left: 10px;
|
|
|
|
|
|
white-space: normal;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.preprocess-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;
|
2026-07-13 15:28:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.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;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.chunk-settings-grid {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.config-field {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
align-content: start;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
padding: 14px;
|
|
|
|
|
|
color: #344054;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border: 1px solid #e2e5ec;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
|
|
|
|
|
|
> small {
|
|
|
|
|
|
color: #8a93a3;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-select),
|
|
|
|
|
|
:deep(.el-input) {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.config-field-label {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.unit-input {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
color: #7b8495;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-input-number) {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.option-validation-message {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
margin: 8px 0 0;
|
|
|
|
|
|
color: #dc2626;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.chunk-estimation-note {
|
|
|
|
|
|
margin: 9px 0 0;
|
|
|
|
|
|
color: #8a93a3;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 900px) {
|
2026-07-13 16:39:16 +08:00
|
|
|
|
.chunk-settings-grid {
|
2026-07-13 15:28:48 +08:00
|
|
|
|
grid-template-columns: minmax(0, 1fr);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.generation-option-row {
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-13 16:39:16 +08:00
|
|
|
|
.compact-option-list .generation-option-row {
|
2026-07-13 15:28:48 +08:00
|
|
|
|
align-items: center;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
}
|
2026-07-13 16:16:50 +08:00
|
|
|
|
|
|
|
|
|
|
.preprocess-option-grid {
|
|
|
|
|
|
grid-template-columns: minmax(0, 1fr);
|
|
|
|
|
|
}
|
2026-07-13 15:28:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
</style>
|