Skip to content

Commit 035d2d4

Browse files
ieduerclaude
andcommitted
style: fix 数据/知识图谱 chart legibility, repaint 词典 with multi-color light theme, drop BETA, bump r37
- app.js: read chart text colors from CSS vars (--text / --text-dim) so 词频/概念广度 bar labels and axis terms stop using dark-theme #e0e0f0 / #a0a0c0 against the BDFZ light parchment; add white stroke halos around heatmap axis labels and 关联知识图谱 subgraph node text; flip getHeatmapTextStyle defaults toward light-theme contrast. - style.css: drop the dark text-shadow on .graph-label and replace it with a parchment stroke halo; restyle insight tabs / coverage chips / .graph-mode for the light palette. - dict.css + dict.js: rebuild 实虚词典 visuals on the BDFZ light parchment with rose / amber / sage / teal / violet panel washes (each side panel and chat surface now reads as a distinct region); widen panel scrollbars to 8px and add a fade-out gradient + animated 向下滑动查看更多 ↓ pill that JS toggles via has-overflow / scrolled-bottom on every .dict-panel-body, so 馆藏辞典原页 / 教育部修订本 / 教育部成语典 readers can see when there is more content below the visible cut. - HTML: remove BETA badges from index/chuzhong/dict/chuzhong-dict; bump asset cache busters to v=20260507a. - version.json + release_manifest.json: bump frontend to 2026.05.07-r37. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 938b015 commit 035d2d4

10 files changed

Lines changed: 632 additions & 227 deletions

File tree

frontend/assets/app.js

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,13 +1902,14 @@ function renderGraphNew(data, container, mode) {
19021902
.attr('stroke-width', d => d.type === 'subject' ? 2.5 : 1)
19031903
.style('transition', 'filter 0.2s, fill-opacity 0.2s');
19041904

1905-
// Labels
1905+
// Labels — fill comes from the .graph-label CSS rule (theme-aware),
1906+
// stroke halo keeps them legible on both dark and light backgrounds.
19061907
node.append('text')
19071908
.attr('class', 'graph-label')
19081909
.attr('dy', d => d.r + 14)
19091910
.attr('text-anchor', 'middle')
19101911
.attr('font-size', d => d.type === 'subject' ? 13 : 10)
1911-
.attr('font-weight', d => d.type === 'subject' ? 700 : 400)
1912+
.attr('font-weight', d => d.type === 'subject' ? 700 : 500)
19121913
.text(d => d.id);
19131914

19141915
// Weight badges for concepts
@@ -2533,6 +2534,16 @@ function getSubjColors() {
25332534
return colors;
25342535
}
25352536

2537+
// Theme-aware chart colors. Reads CSS variables so charts stay readable
2538+
// whether the page is on the dark base palette or the BDFZ light parchment refresh.
2539+
function getChartColors() {
2540+
const cs = getComputedStyle(document.documentElement);
2541+
const text = (cs.getPropertyValue('--text') || '').trim() || '#3a3530';
2542+
const dim = (cs.getPropertyValue('--text-dim') || '').trim() || '#7a716a';
2543+
const muted = (cs.getPropertyValue('--text-muted') || '').trim() || '#a89d96';
2544+
return { text, dim, muted };
2545+
}
2546+
25362547
async function loadInsights() {
25372548
if (insightsLoaded) return;
25382549
insightsLoaded = true;
@@ -2604,14 +2615,17 @@ function renderFreqBars(container, data) {
26042615
.transition().duration(600).delay((d, i) => i * 20)
26052616
.attr('width', d => x(d.count));
26062617

2618+
const chartColors = getChartColors();
2619+
26072620
// Labels
26082621
g.selectAll('.bar-label').data(data).join('text')
26092622
.attr('class', 'bar-label')
26102623
.attr('x', d => x(d.count) + 5)
26112624
.attr('y', d => y(d.term) + y.bandwidth() / 2)
26122625
.attr('dy', '0.35em')
2613-
.attr('fill', '#a0a0c0')
2626+
.attr('fill', chartColors.dim)
26142627
.attr('font-size', '11px')
2628+
.attr('font-weight', '600')
26152629
.text(d => d.count.toLocaleString());
26162630

26172631
// Y axis labels
@@ -2621,8 +2635,9 @@ function renderFreqBars(container, data) {
26212635
.attr('y', d => y(d.term) + y.bandwidth() / 2)
26222636
.attr('dy', '0.35em')
26232637
.attr('text-anchor', 'end')
2624-
.attr('fill', '#e0e0f0')
2638+
.attr('fill', chartColors.text)
26252639
.attr('font-size', '12px')
2640+
.attr('font-weight', '600')
26262641
.attr('cursor', 'pointer')
26272642
.text(d => d.term)
26282643
.on('click', (e, d) => {
@@ -2648,13 +2663,13 @@ async function loadHeatmap() {
26482663
function getHeatmapTextStyle(fillColor) {
26492664
const color = d3.color(fillColor);
26502665
if (!color) {
2651-
return { fill: '#f8fbff', stroke: 'rgba(0,0,0,0.35)' };
2666+
return { fill: '#3a3530', stroke: 'rgba(255,255,255,0.85)' };
26522667
}
26532668
const luminance = (0.299 * color.r + 0.587 * color.g + 0.114 * color.b) / 255;
2654-
if (luminance >= 0.66) {
2655-
return { fill: '#17202a', stroke: 'rgba(255,255,255,0.55)' };
2669+
if (luminance >= 0.55) {
2670+
return { fill: '#1f2933', stroke: 'rgba(255,255,255,0.85)' };
26562671
}
2657-
return { fill: '#f8fbff', stroke: 'rgba(0,0,0,0.35)' };
2672+
return { fill: '#fbfaf5', stroke: 'rgba(0,0,0,0.45)' };
26582673
}
26592674

26602675
function renderHeatmap(container, data) {
@@ -2708,33 +2723,43 @@ function renderHeatmap(container, data) {
27082723
}
27092724
}
27102725

2711-
// Axis labels
2726+
// Axis labels — subject-tinted text with stroke halo so it stays
2727+
// legible against any background luminance.
2728+
const axisFallback = getChartColors().text;
27122729
subjects.forEach((s, i) => {
2730+
const tint = getSubjColors()[s] || axisFallback;
27132731
svg.append('text')
27142732
.attr('x', margin.left + i * cellSize + cellSize / 2 - 1)
27152733
.attr('y', margin.top - 8)
27162734
.attr('text-anchor', 'middle')
2717-
.attr('fill', getSubjColors()[s] || '#ccc')
2735+
.attr('fill', tint)
2736+
.attr('stroke', 'rgba(255, 255, 255, 0.7)')
2737+
.attr('stroke-width', 3)
2738+
.attr('paint-order', 'stroke')
27182739
.attr('font-size', '12px')
2719-
.attr('font-weight', '500')
2740+
.attr('font-weight', '700')
27202741
.text(s);
27212742
svg.append('text')
27222743
.attr('x', margin.left - 8)
27232744
.attr('y', margin.top + i * cellSize + cellSize / 2)
27242745
.attr('dy', '0.35em')
27252746
.attr('text-anchor', 'end')
2726-
.attr('fill', getSubjColors()[s] || '#ccc')
2747+
.attr('fill', tint)
2748+
.attr('stroke', 'rgba(255, 255, 255, 0.7)')
2749+
.attr('stroke-width', 3)
2750+
.attr('paint-order', 'stroke')
27272751
.attr('font-size', '12px')
2728-
.attr('font-weight', '500')
2752+
.attr('font-weight', '700')
27292753
.text(s);
27302754
});
27312755

27322756
// Caption
27332757
svg.append('text')
27342758
.attr('x', W / 2).attr('y', H + 5)
27352759
.attr('text-anchor', 'middle')
2736-
.attr('fill', '#888')
2760+
.attr('fill', getChartColors().dim)
27372761
.attr('font-size', '11px')
2762+
.attr('font-weight', '600')
27382763
.text(`共 ${data.total_concepts} 个跨学科学术术语`);
27392764
}
27402765

@@ -2814,13 +2839,16 @@ function renderBreadth(container, concepts) {
28142839
.transition().duration(500).delay((d, i) => i * 15)
28152840
.attr('width', d => x(d.subjects));
28162841

2842+
const breadthColors = getChartColors();
2843+
28172844
g.selectAll('.breadth-val').data(concepts).join('text')
28182845
.attr('class', 'breadth-val')
28192846
.attr('x', d => x(d.subjects) + 5)
28202847
.attr('y', d => y(d.term) + y.bandwidth() / 2)
28212848
.attr('dy', '0.35em')
2822-
.attr('fill', '#a0a0c0')
2849+
.attr('fill', breadthColors.dim)
28232850
.attr('font-size', '11px')
2851+
.attr('font-weight', '600')
28242852
.text(d => `${d.subjects} 科`);
28252853

28262854
svg.selectAll('.breadth-label').data(concepts).join('text')
@@ -2829,8 +2857,9 @@ function renderBreadth(container, concepts) {
28292857
.attr('y', d => y(d.term) + y.bandwidth() / 2)
28302858
.attr('dy', '0.35em')
28312859
.attr('text-anchor', 'end')
2832-
.attr('fill', '#e0e0f0')
2860+
.attr('fill', breadthColors.text)
28332861
.attr('font-size', '12px')
2862+
.attr('font-weight', '600')
28342863
.attr('cursor', 'pointer')
28352864
.text(d => d.term)
28362865
.on('click', (e, d) => {
@@ -2905,12 +2934,16 @@ function renderSearchSubgraph(container, data) {
29052934
.attr('stroke', d => d.type === 'center' ? '#a29bfe' : 'none')
29062935
.attr('stroke-width', 2);
29072936

2937+
const subgraphColors = getChartColors();
29082938
node.append('text')
29092939
.attr('dy', d => d.type === 'center' ? 28 : 22)
29102940
.attr('text-anchor', 'middle')
2911-
.attr('fill', '#e0e0f0')
2941+
.attr('fill', subgraphColors.text)
2942+
.attr('stroke', 'rgba(255, 255, 255, 0.9)')
2943+
.attr('stroke-width', 2.4)
2944+
.attr('paint-order', 'stroke')
29122945
.attr('font-size', d => d.type === 'center' ? '13px' : d.type === 'subject' ? '12px' : '10px')
2913-
.attr('font-weight', d => d.type === 'center' ? '700' : '400')
2946+
.attr('font-weight', d => d.type === 'center' ? '700' : '500')
29142947
.text(d => d.id);
29152948

29162949
sim.on('tick', () => {

0 commit comments

Comments
 (0)