diff --git a/miniapp/pages/index/index.js b/miniapp/pages/index/index.js
index 015daaf..93a1d28 100644
--- a/miniapp/pages/index/index.js
+++ b/miniapp/pages/index/index.js
@@ -174,6 +174,10 @@ const DEFAULT_THEME_INDEX = (() => {
const index = themePresets.findIndex((item) => item && item.id === DEFAULT_THEME_ID);
return index >= 0 ? index : 0;
})();
+const THEME_ROW_HEIGHT_PX = 36;
+const THEME_VISIBLE_ROW_COUNT = 6;
+const THEME_LIST_HEIGHT_PX = THEME_ROW_HEIGHT_PX * THEME_VISIBLE_ROW_COUNT;
+const THEME_LIST_EDGE_SPACER_PX = (THEME_LIST_HEIGHT_PX - THEME_ROW_HEIGHT_PX) / 2;
/**
* 数值限制,避免 UI 参数导致布局异常。
@@ -186,6 +190,19 @@ function clampNumber(value, min, max, fallback) {
return Math.min(max, Math.max(min, normalized));
}
+/**
+ * 主题弹层打开时的滚动定位:
+ * 通过上下占位留白,让任意索引都可滚动到视图中心。
+ */
+function getThemeListScrollTopByIndex(index, totalCount) {
+ const total = Number(totalCount);
+ if (!Number.isFinite(total) || total <= 0) {
+ return 0;
+ }
+ const safeIndex = clampNumber(index, 0, total - 1, 0);
+ return safeIndex * THEME_ROW_HEIGHT_PX;
+}
+
/**
* 统一错误文案:
* - xlsx 解析能力缺失时,固定提示用户去“构建 npm”
@@ -286,17 +303,23 @@ function buildSankeyLayout(links, width, height, renderOptions) {
const sourceValueMap = {};
const targetValueMap = {};
+ const nodeColorIndexMap = {};
+ let nodeColorIndexCursor = 0;
links.forEach((link) => {
sourceValueMap[link.source] = (sourceValueMap[link.source] || 0) + Number(link.value || 0);
targetValueMap[link.target] = (targetValueMap[link.target] || 0) + Number(link.value || 0);
+ if (!Object.prototype.hasOwnProperty.call(nodeColorIndexMap, link.source)) {
+ nodeColorIndexMap[link.source] = nodeColorIndexCursor;
+ nodeColorIndexCursor += 1;
+ }
+ if (!Object.prototype.hasOwnProperty.call(nodeColorIndexMap, link.target)) {
+ nodeColorIndexMap[link.target] = nodeColorIndexCursor;
+ nodeColorIndexCursor += 1;
+ }
});
const sourceNames = Object.keys(sourceValueMap);
const targetNames = Object.keys(targetValueMap);
- const sourceIndexMap = {};
- sourceNames.forEach((name, index) => {
- sourceIndexMap[name] = index;
- });
const totalValue = sourceNames.reduce((sum, name) => sum + sourceValueMap[name], 0);
if (totalValue <= 0) {
return null;
@@ -371,7 +394,7 @@ function buildSankeyLayout(links, width, height, renderOptions) {
sy,
ty,
linkHeight,
- sourceIndex: Number.isFinite(sourceIndexMap[link.source]) ? sourceIndexMap[link.source] : 0
+ sourceIndex: Number.isFinite(nodeColorIndexMap[link.source]) ? nodeColorIndexMap[link.source] : 0
});
});
@@ -383,6 +406,7 @@ function buildSankeyLayout(links, width, height, renderOptions) {
targetNames,
sourcePos,
targetPos,
+ nodeColorIndexMap,
linkSegments
};
}
@@ -431,12 +455,15 @@ function buildSankeySvgText(links, width, height, renderOptions) {
layout.sourceNames.forEach((name, index) => {
const node = layout.sourcePos[name];
+ const colorIndex = Number.isFinite(layout.nodeColorIndexMap[name])
+ ? layout.nodeColorIndexMap[name]
+ : index;
const textY = node.y + getNodeLabelCenterY(node.h);
const textPlacement = getSvgLabelPlacement(layout, true, labelPositionMode);
segments.push(
``
+ )}" height="${formatSvgNumber(node.h)}" fill="${getNodeColor(colorIndex, themeColors)}" />`
);
segments.push(
``
+ )}" height="${formatSvgNumber(node.h)}" fill="${getNodeColor(colorIndex, themeColors)}" />`
);
segments.push(
`未加载文件,暂无列信息
-
-
+
+
源数据(link value)
-
-
- {{item}}
-
+
+
+
+
+
+ {{item}}
+
+
-
-
+
+
源标签(Source label)
-
-
- {{item}}
-
+
+
+
+
+
+ {{item}}
+
+
-
-
- 目标标签(target label)
-
-
-
- {{item}}
+
+ 目标标签(target label)
+
+
+
+
+
+
+ {{item}}
+
+
@@ -156,8 +177,17 @@
选择配色主题
-
+
+
+
diff --git a/miniapp/pages/index/index.wxss b/miniapp/pages/index/index.wxss
index 0027adc..13de006 100644
--- a/miniapp/pages/index/index.wxss
+++ b/miniapp/pages/index/index.wxss
@@ -315,6 +315,7 @@
color: #1d2129;
font-size: 14px;
font-weight: 500;
+ padding: 2px 0;
}
.field-title image {
@@ -322,16 +323,42 @@
height: 14px;
}
+.column-list {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+}
+
+.column-list-line {
+ position: absolute;
+ left: 8px;
+ top: 0;
+ bottom: 14px;
+ width: 1px;
+ background: #c9cdd4;
+}
+
.row {
- height: 24px;
- border-bottom: 1px solid #c9cdd4;
+ position: relative;
+ min-height: 24px;
display: flex;
align-items: center;
gap: 8px;
+ padding-left: 20px;
padding-bottom: 8px;
box-sizing: border-box;
}
+.row-link {
+ position: absolute;
+ left: 8px;
+ top: 9px;
+ width: 10px;
+ height: 1px;
+ background: #c9cdd4;
+}
+
.row image {
width: 18px;
height: 18px;
@@ -385,7 +412,7 @@
bottom: 0;
background: #fff;
border-radius: 16px 16px 0 0;
- padding: 12px 12px 16px;
+ padding: 12px 32px 32px;
z-index: 11;
box-sizing: border-box;
}
@@ -402,6 +429,10 @@
min-height: 216px;
}
+.theme-list-spacer {
+ height: 90px;
+}
+
.theme-row {
display: flex;
align-items: center;