diff --git a/docs/project_context.md b/docs/project_context.md
index 45f76a2..ad0e739 100644
--- a/docs/project_context.md
+++ b/docs/project_context.md
@@ -814,3 +814,8 @@
- CellData「规则设置」弹窗不再整体滚动;高级匹配、目标表、主键字段和主键表达式固定显示,图形化模式下仅来源列表滚动。
- “添加来源”按钮固定在来源列表下方,始终可见;弹窗底部保存按钮也保持可见。
- 验证:`frontend` `npm run build` 通过;构建产物已清理。
+
+## 2026-06-25:图形化来源支持折叠
+
+- CellData 图形化映射中每个来源卡片支持展开/收起,来源头展示目录与 CSV 前缀摘要;“添加来源”按钮移动到映射规则标题区右侧。
+- 验证:`frontend` `npm run build` 通过;构建产物已清理。
diff --git a/frontend/src/components/SettingsPanel.vue b/frontend/src/components/SettingsPanel.vue
index a798500..a96c1fa 100644
--- a/frontend/src/components/SettingsPanel.vue
+++ b/frontend/src/components/SettingsPanel.vue
@@ -719,6 +719,7 @@
映射规则
+ 添加来源
图形化
JSON
@@ -743,40 +744,43 @@
@@ -833,6 +837,7 @@ interface MappingFieldForm {
interface MappingSourceForm {
band: string;
file_prefix: string;
+ collapsed: boolean;
fields: MappingFieldForm[];
}
@@ -1500,6 +1505,7 @@ function applyCellDataMappingForm(mapping: Record) {
cellDataMappingForm.sources.push({
band: String(source.band || ''),
file_prefix: String(source.file_prefix || ''),
+ collapsed: false,
fields: Object.entries(fields).map(([target, rule]) => {
if (typeof rule === 'object' && rule !== null && 'value' in rule) {
return { target, mode: 'value', value: String((rule as Record).value ?? '') };
@@ -1536,7 +1542,14 @@ function mappingFormToJson(): Record {
}
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) {
diff --git a/frontend/src/styles.css b/frontend/src/styles.css
index 6525e4e..4325c4a 100644
--- a/frontend/src/styles.css
+++ b/frontend/src/styles.css
@@ -1722,6 +1722,29 @@ select {
.cell-data-source-header {
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 {