统一思维导图颜色为主题紫色#660874

- 将所有连线颜色统一为#660874深紫色
- 将根节点背景色从#9C88FF改为#660874统一主题色
- 统一选中状态和强调色为#660874
- 与页面AI助手图标颜色保持一致
This commit is contained in:
lixinran 2025-10-10 18:16:25 +08:00
parent 4af977e33a
commit 35766881dd
7 changed files with 181 additions and 138 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -23,8 +23,8 @@
flex-direction: column; flex-direction: column;
} }
</style> </style>
<script type="module" crossorigin src="/assets/index-3e4825f7.js"></script> <script type="module" crossorigin src="/assets/index-3cfab743.js"></script>
<link rel="stylesheet" href="/assets/index-0f0d7625.css"> <link rel="stylesheet" href="/assets/index-356fe347.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

View File

@ -143,6 +143,46 @@
import { ref, onMounted, onUnmounted, nextTick } from 'vue'; import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import MindElixir from '../lib/mind-elixir/dist/MindElixir.js'; import MindElixir from '../lib/mind-elixir/dist/MindElixir.js';
import '../lib/mind-elixir/dist/style.css'; import '../lib/mind-elixir/dist/style.css';
//
const customTheme = {
name: 'Light Purple',
type: 'light',
palette: [
'#660874', // - 线使
'#660874', //
'#660874', //
'#660874', //
'#660874', //
'#660874', //
'#660874', //
'#660874', //
'#660874', //
'#660874' //
],
cssVar: {
'--node-gap-x': '30px',
'--node-gap-y': '10px',
'--main-gap-x': '65px',
'--main-gap-y': '45px',
'--root-radius': '30px',
'--main-radius': '20px',
'--root-color': '#ffffff',
'--root-bgcolor': '#660874', //
'--root-border-color': 'rgba(0, 0, 0, 0)',
'--main-color': '#444446',
'--main-bgcolor': '#ffffff',
'--topic-padding': '3px',
'--color': '#777777',
'--bgcolor': '#f6f6f6',
'--selected': '#660874', //
'--accent-color': '#660874', //
'--panel-color': '#444446',
'--panel-bgcolor': '#ffffff',
'--panel-border-color': '#eaeaea',
'--map-padding': '50px',
},
};
import { mindmapAPI } from '../api/mindmap.js'; import { mindmapAPI } from '../api/mindmap.js';
import { import {
smartRenderNodeContent, smartRenderNodeContent,
@ -354,6 +394,7 @@ const loadMindmapData = async (data, keepPosition = false, shouldCenterRoot = tr
try { try {
if (mindmapEl.value) { if (mindmapEl.value) {
console.log('🔍 创建Mind Elixir实例设置markdown函数'); console.log('🔍 创建Mind Elixir实例设置markdown函数');
mindElixir.value = new MindElixir({ mindElixir.value = new MindElixir({
el: mindmapEl.value, el: mindmapEl.value,
direction: MindElixir.RIGHT, direction: MindElixir.RIGHT,
@ -366,6 +407,7 @@ const loadMindmapData = async (data, keepPosition = false, shouldCenterRoot = tr
infinite: true, infinite: true,
maxScale: 5, maxScale: 5,
minScale: 0.1, minScale: 0.1,
theme: customTheme, //
markdown: (text, nodeObj) => { markdown: (text, nodeObj) => {
// markdown // markdown
if (text.includes('|') || text.includes('**') || text.includes('`') || text.includes('#') || text.includes('![')) { if (text.includes('|') || text.includes('**') || text.includes('`') || text.includes('#') || text.includes('![')) {
@ -426,6 +468,7 @@ const loadMindmapData = async (data, keepPosition = false, shouldCenterRoot = tr
infinite: true, infinite: true,
maxScale: 5, maxScale: 5,
minScale: 0.1, minScale: 0.1,
theme: customTheme, //
markdown: (text, nodeObj) => { markdown: (text, nodeObj) => {
// markdown // markdown
if (text.includes('|') || text.includes('**') || text.includes('`') || text.includes('#') || text.includes('![')) { if (text.includes('|') || text.includes('**') || text.includes('`') || text.includes('#') || text.includes('![')) {
@ -488,6 +531,7 @@ const loadMindmapData = async (data, keepPosition = false, shouldCenterRoot = tr
infinite: true, infinite: true,
maxScale: 5, maxScale: 5,
minScale: 0.1, minScale: 0.1,
theme: customTheme, //
markdown: (text, nodeObj) => { markdown: (text, nodeObj) => {
// markdown // markdown
if (text.includes('|') || text.includes('**') || text.includes('`') || text.includes('#') || text.includes('![')) { if (text.includes('|') || text.includes('**') || text.includes('`') || text.includes('#') || text.includes('![')) {

View File

@ -180,15 +180,15 @@ class TableToSVGConverter {
// 计算总宽度 // 计算总宽度
const totalWidth = columnWidths.reduce((sum, width) => sum + width, 0) const totalWidth = columnWidths.reduce((sum, width) => sum + width, 0)
// 计算行高,考虑多行文本 // 计算行高,大幅减少
this.cellHeight = Math.max(35, this.fontSize * 2) // 恢复原来的行高 this.cellHeight = Math.max(15, this.fontSize * 1.0) // 大幅减少行高
// 为每行计算实际高度(考虑多行文本) // 为每行计算实际高度(考虑多行文本)
const rowHeights: number[] = new Array(maxRows).fill(this.cellHeight) const rowHeights: number[] = new Array(maxRows).fill(this.cellHeight)
structure.forEach(cell => { structure.forEach(cell => {
const lines = cell.content.split('\n').length const lines = cell.content.split('\n').length
const cellHeight = Math.max(this.cellHeight, lines * this.fontSize * 1.4 + 10) const cellHeight = Math.max(this.cellHeight, lines * this.fontSize * 1.0 + 2)
// 更新这一行涉及的行的高度 // 更新这一行涉及的行的高度
for (let row = cell.row; row < cell.row + cell.rowspan; row++) { for (let row = cell.row; row < cell.row + cell.rowspan; row++) {
@ -198,16 +198,6 @@ class TableToSVGConverter {
const totalHeight = rowHeights.reduce((sum, height) => sum + height, 0) const totalHeight = rowHeights.reduce((sum, height) => sum + height, 0)
console.log('📊 TableToSVGConverter calculateLayout 计算结果:', {
maxCols,
maxRows,
totalWidth,
totalHeight,
rowHeights,
columnWidths,
cellHeight: this.cellHeight,
fontSize: this.fontSize
})
return { return {
totalWidth, totalWidth,
@ -220,23 +210,29 @@ class TableToSVGConverter {
} }
// 生成SVG元素 // 生成SVG元素
generateSVG(structure: any[], layout: any, x: number, y: number) { generateSVG(structure: any[], layout: any, x: number, y: number, actualTableHeight?: number) {
const svgGroup = document.createElementNS(ns, 'g') const svgGroup = document.createElementNS(ns, 'g')
// 使用实际表格高度而不是计算高度,避免底部空白过大
const rectHeight = actualTableHeight || layout.totalHeight
// 绘制表格边框 // 绘制表格边框
const tableRect = document.createElementNS(ns, 'rect') const tableRect = document.createElementNS(ns, 'rect')
setAttributes(tableRect, { setAttributes(tableRect, {
x: x + '', x: x + '',
y: y + '', y: y + '',
width: layout.totalWidth + '', width: layout.totalWidth + '',
height: layout.totalHeight + '', height: rectHeight + '',
fill: 'white', fill: 'white',
stroke: '#ccc', stroke: '#ccc',
'stroke-width': '1' 'stroke-width': '1'
}) })
svgGroup.appendChild(tableRect) svgGroup.appendChild(tableRect)
console.log('📊 TableToSVGConverter 创建表格背景rect:', { console.log('📊 TableToSVGConverter 创建表格背景rect:', {
x, y, width: layout.totalWidth, height: layout.totalHeight x, y, width: layout.totalWidth, height: rectHeight,
calculatedHeight: layout.totalHeight,
actualHeight: actualTableHeight,
heightDifference: layout.totalHeight - rectHeight
}) })
// 绘制垂直网格线(使用动态列宽) // 绘制垂直网格线(使用动态列宽)
@ -248,7 +244,7 @@ class TableToSVGConverter {
x1: currentX + '', x1: currentX + '',
y1: y + '', y1: y + '',
x2: currentX + '', x2: currentX + '',
y2: y + layout.totalHeight + '', y2: y + rectHeight + '',
stroke: '#ccc', stroke: '#ccc',
'stroke-width': '1' 'stroke-width': '1'
}) })
@ -348,10 +344,10 @@ class TableToSVGConverter {
} }
// 转换表格为SVG // 转换表格为SVG
convert(x: number, y: number) { convert(x: number, y: number, actualTableHeight?: number) {
const structure = this.analyzeStructure() const structure = this.analyzeStructure()
const layout = this.calculateLayout(structure) const layout = this.calculateLayout(structure)
return this.generateSVG(structure, layout, x, y) return this.generateSVG(structure, layout, x, y, actualTableHeight)
} }
} }
@ -565,8 +561,8 @@ function generateSvgTextUsingForeignObject(tpc: HTMLElement, tpcStyle: CSSStyleD
div.innerHTML = cleanedHtml div.innerHTML = cleanedHtml
// 应用样式,确保与思维导图显示一致 // 应用样式,确保与思维导图显示一致
const paddingTop = parseInt(tpcStyle.paddingTop) || 8 const paddingTop = 15 // 统一顶部间距
const paddingBottom = parseInt(tpcStyle.paddingBottom) || 8 const paddingBottom = 15 // 统一底部间距
const paddingLeft = parseInt(tpcStyle.paddingLeft) || 8 const paddingLeft = parseInt(tpcStyle.paddingLeft) || 8
const paddingRight = parseInt(tpcStyle.paddingRight) || 8 const paddingRight = parseInt(tpcStyle.paddingRight) || 8
@ -581,10 +577,9 @@ function generateSvgTextUsingForeignObject(tpc: HTMLElement, tpcStyle: CSSStyleD
box-sizing: border-box; box-sizing: border-box;
overflow: visible; overflow: visible;
text-align: center !important; text-align: center !important;
line-height: 1.4;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: flex-start; justify-content: center;
align-items: center; align-items: center;
position: relative; position: relative;
` `
@ -787,8 +782,13 @@ function convertDivToSvg(mei: MindElixirInstance, tpc: HTMLElement, useForeignOb
const fontSize = parseFloat(tpcStyle.fontSize) || 14 const fontSize = parseFloat(tpcStyle.fontSize) || 14
const fontFamily = tpcStyle.fontFamily || 'Arial, sans-serif' const fontFamily = tpcStyle.fontFamily || 'Arial, sans-serif'
// 获取实际DOM元素的尺寸用于精确的rect高度
const rect = tpc.getBoundingClientRect()
const actualHeight = rect.height
const converter = new TableToSVGConverter(table, fontSize, fontFamily) const converter = new TableToSVGConverter(table, fontSize, fontFamily)
const tableSVG = converter.convert(x, y) const tableSVG = converter.convert(x, y, actualHeight)
// 直接返回表格SVG不创建额外的背景rect // 直接返回表格SVG不创建额外的背景rect
return tableSVG return tableSVG