style: 图形化映射来源支持折叠
This commit is contained in:
@@ -814,3 +814,8 @@
|
|||||||
- CellData「规则设置」弹窗不再整体滚动;高级匹配、目标表、主键字段和主键表达式固定显示,图形化模式下仅来源列表滚动。
|
- CellData「规则设置」弹窗不再整体滚动;高级匹配、目标表、主键字段和主键表达式固定显示,图形化模式下仅来源列表滚动。
|
||||||
- “添加来源”按钮固定在来源列表下方,始终可见;弹窗底部保存按钮也保持可见。
|
- “添加来源”按钮固定在来源列表下方,始终可见;弹窗底部保存按钮也保持可见。
|
||||||
- 验证:`frontend` `npm run build` 通过;构建产物已清理。
|
- 验证:`frontend` `npm run build` 通过;构建产物已清理。
|
||||||
|
|
||||||
|
## 2026-06-25:图形化来源支持折叠
|
||||||
|
|
||||||
|
- CellData 图形化映射中每个来源卡片支持展开/收起,来源头展示目录与 CSV 前缀摘要;“添加来源”按钮移动到映射规则标题区右侧。
|
||||||
|
- 验证:`frontend` `npm run build` 通过;构建产物已清理。
|
||||||
|
|||||||
@@ -719,6 +719,7 @@
|
|||||||
<div class="cell-data-section-title">
|
<div class="cell-data-section-title">
|
||||||
<strong>映射规则</strong>
|
<strong>映射规则</strong>
|
||||||
<n-space size="small">
|
<n-space size="small">
|
||||||
|
<n-button v-if="cellDataMappingMode === 'form'" size="small" @click="addCellDataMappingSource">添加来源</n-button>
|
||||||
<n-radio-group v-model:value="cellDataMappingMode" size="small" @update:value="switchCellDataMappingMode">
|
<n-radio-group v-model:value="cellDataMappingMode" size="small" @update:value="switchCellDataMappingMode">
|
||||||
<n-radio-button value="form">图形化</n-radio-button>
|
<n-radio-button value="form">图形化</n-radio-button>
|
||||||
<n-radio-button value="json">JSON</n-radio-button>
|
<n-radio-button value="json">JSON</n-radio-button>
|
||||||
@@ -743,14 +744,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="cell-data-source-list">
|
<div class="cell-data-source-list">
|
||||||
<div v-for="(source, sourceIndex) in cellDataMappingForm.sources" :key="sourceIndex" class="cell-data-source-card">
|
<div v-for="(source, sourceIndex) in cellDataMappingForm.sources" :key="sourceIndex" class="cell-data-source-card">
|
||||||
<div class="cell-data-source-header">
|
<div class="cell-data-source-header" @click="toggleCellDataMappingSource(sourceIndex)">
|
||||||
|
<div class="cell-data-source-title">
|
||||||
|
<span class="cell-data-source-toggle">{{ source.collapsed ? '▶' : '▼' }}</span>
|
||||||
<strong>来源 {{ sourceIndex + 1 }}</strong>
|
<strong>来源 {{ sourceIndex + 1 }}</strong>
|
||||||
<n-button quaternary circle size="small" type="error" @click="removeCellDataMappingSource(sourceIndex)">
|
<span>{{ source.band || '未填写目录' }} / {{ source.file_prefix || '未填写前缀' }}</span>
|
||||||
|
</div>
|
||||||
|
<n-button quaternary circle size="small" type="error" @click.stop="removeCellDataMappingSource(sourceIndex)">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon><CloseOutline /></n-icon>
|
<n-icon><CloseOutline /></n-icon>
|
||||||
</template>
|
</template>
|
||||||
</n-button>
|
</n-button>
|
||||||
</div>
|
</div>
|
||||||
|
<template v-if="!source.collapsed">
|
||||||
<div class="cell-data-source-meta">
|
<div class="cell-data-source-meta">
|
||||||
<n-form-item label="目录">
|
<n-form-item label="目录">
|
||||||
<n-input v-model:value="source.band" placeholder="如 2.6G" />
|
<n-input v-model:value="source.band" placeholder="如 2.6G" />
|
||||||
@@ -772,11 +778,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<n-button size="small" @click="addCellDataMappingField(sourceIndex)">添加字段</n-button>
|
<n-button size="small" @click="addCellDataMappingField(sourceIndex)">添加字段</n-button>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cell-data-mapping-actions">
|
|
||||||
<n-button size="small" @click="addCellDataMappingSource">添加来源</n-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
@@ -833,6 +837,7 @@ interface MappingFieldForm {
|
|||||||
interface MappingSourceForm {
|
interface MappingSourceForm {
|
||||||
band: string;
|
band: string;
|
||||||
file_prefix: string;
|
file_prefix: string;
|
||||||
|
collapsed: boolean;
|
||||||
fields: MappingFieldForm[];
|
fields: MappingFieldForm[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1500,6 +1505,7 @@ function applyCellDataMappingForm(mapping: Record<string, unknown>) {
|
|||||||
cellDataMappingForm.sources.push({
|
cellDataMappingForm.sources.push({
|
||||||
band: String(source.band || ''),
|
band: String(source.band || ''),
|
||||||
file_prefix: String(source.file_prefix || ''),
|
file_prefix: String(source.file_prefix || ''),
|
||||||
|
collapsed: false,
|
||||||
fields: Object.entries(fields).map(([target, rule]) => {
|
fields: Object.entries(fields).map(([target, rule]) => {
|
||||||
if (typeof rule === 'object' && rule !== null && 'value' in rule) {
|
if (typeof rule === 'object' && rule !== null && 'value' in rule) {
|
||||||
return { target, mode: 'value', value: String((rule as Record<string, unknown>).value ?? '') };
|
return { target, mode: 'value', value: String((rule as Record<string, unknown>).value ?? '') };
|
||||||
@@ -1536,7 +1542,14 @@ function mappingFormToJson(): Record<string, unknown> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addCellDataMappingSource() {
|
function addCellDataMappingSource() {
|
||||||
cellDataMappingForm.sources.push({ band: '', file_prefix: '', fields: [] });
|
cellDataMappingForm.sources.push({ band: '', file_prefix: '', collapsed: false, fields: [] });
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleCellDataMappingSource(index: number) {
|
||||||
|
const source = cellDataMappingForm.sources[index];
|
||||||
|
if (source) {
|
||||||
|
source.collapsed = !source.collapsed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeCellDataMappingSource(index: number) {
|
function removeCellDataMappingSource(index: number) {
|
||||||
|
|||||||
@@ -1722,6 +1722,29 @@ select {
|
|||||||
|
|
||||||
.cell-data-source-header {
|
.cell-data-source-header {
|
||||||
grid-template-columns: minmax(0, 1fr) auto;
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell-data-source-title {
|
||||||
|
display: flex;
|
||||||
|
min-width: 0;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell-data-source-title span:last-child {
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
color: var(--td-text-color-secondary);
|
||||||
|
font-size: 12px;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell-data-source-toggle {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
color: var(--td-text-color-placeholder);
|
||||||
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cell-data-source-meta {
|
.cell-data-source-meta {
|
||||||
|
|||||||
Reference in New Issue
Block a user