原理:使用npm的mmdc命令,将有mermaid内容的Markdown文件生成图片。
用命令行也就一句话的事:
mmdc -i xxx.md -o xxx.jpg
环境:mmdc 11.4.2
遗留问题:这个mmdc 生成图片指定宽度 --width 不生效,只能用--scale 按比例缩放。
成果界面:
mermaid代码:
graph TD
A[开始] --> B[吃饭]
B --> C[睡觉]
C --> D[打豆豆]
D --> B
D --> E[结束]
生成图片
使用vscode AIcode插件+deepseek辅助开发。
完整代码如下:
import sys
import os
import subprocess
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QTextEdit, QPushButton, QFileDialog, QLineEdit, QMessageBox, QHBoxLayout, QLabel, QComboBox, QSplitter
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QImage, QPixmap
class MermaidApp(QMainWindow):
def __init__(self):
super().__init__()
self.output_dir = os.path.dirname(os.path.abspath(__file__)) # 默认保存路径为程序所在目录
self.file_counter = 1
self.initUI()
def initUI(self):
self.setWindowTitle("Mermaid 图表生成器")
self.setGeometry(100, 100, 800, 600)
# 主布局
main_widget = QWidget()
self.setCentralWidget(main_widget)
layout = QVBoxLayout()
# 使用QSplitter实现可调整大小的代码和图表区域
splitter = QSplitter(Qt.Horizontal)
# Mermaid代码输入
self.code_input = QTextEdit()
self.code_input.setPlainText("""graph TD
A[开始] --> B[吃饭]
B --> C[睡觉]
C --> D[打豆豆]
D --> B
D --> E[结束]""")
# 图表显示区域
self.image_label = QLabel()
self.image_label.setAlignment(Qt.AlignCenter)
# 添加组件到splitter
splitter.addWidget(self.code_input)
splitter.addWidget(self.image_label)
# 设置初始比例 60:40
splitter.setSizes([600, 400])
layout.addWidget(splitter)
# 按钮布局
btn_layout = QHBoxLayout()
# 生成按钮
self.generate_btn = QPushButton("生成图表")
self.generate_btn.clicked.connect(self.generate_diagram)
btn_layout.addWidget(self.generate_btn)
# 保存按钮
self.save_btn = QPushButton("保存图表")
self.save_btn.clicked.connect(self.save_diagram)
btn_layout.addWidget(self.save_btn)
layout.addLayout(btn_layout)
# 保存路径设置
path_layout = QHBoxLayout()
# 图片格式选择
self.format_combo = QComboBox()
self.format_combo.addItems(["PNG (*.png)", "JPEG (*.jpg)"])
path_layout.addWidget(self.format_combo)
# 缩放比例设置
scale_layout = QHBoxLayout()
scale_layout.addWidget(QLabel("缩放比例:"))
self.scale_combo = QComboBox()
self.scale_combo.addItems(["1", "1.5", "2", "2.5", "3"])
self.scale_combo.setCurrentIndex(2) # 默认选择2倍
scale_layout.addWidget(self.scale_combo)
path_layout.addLayout(scale_layout)
# 路径显示
self.path_label = QLabel()
self.path_label.setText(f"保存路径: {self.output_dir}")
path_layout.addWidget(self.path_label)
self.modify_btn = QPushButton("修改")
self.modify_btn.clicked.connect(self.select_output_dir)
path_layout.addWidget(self.modify_btn)
layout.addLayout(path_layout)
main_widget.setLayout(layout)
def generate_diagram(self):
mermaid_code = self.code_input.toPlainText()
if not mermaid_code.strip():
self.show_message("错误", "请输入Mermaid代码")
return
# 使用mermaid-cli生成图表
temp_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), "temp.mmd")
with open(temp_file, "w", encoding="utf-8") as f:
f.write(mermaid_code)
output_file = "diagram.png"
config_file = "mermaid-config.json"
try:
# 创建配置文件
with open(config_file, "w") as f:
f.write('{"theme": "default", "fontFamily": "Microsoft YaHei"}')
# 获取缩放比例
scale = self.scale_combo.currentText()
# 生成图表
subprocess.run([
"C:/Users/Administrator/AppData/Roaming/npm/mmdc.cmd",
"-i", temp_file,
"-o", output_file,
"--configFile", config_file,
"--scale", scale
], check=True)
# 显示生成的图表
image = QImage(output_file)
# 清理临时文件
os.remove(config_file)
except subprocess.CalledProcessError as e:
self.show_message("错误", f"生成图表失败: {str(e)}")
return
self.image_label.setPixmap(QPixmap.fromImage(image))
def save_diagram(self):
if not os.path.exists("diagram.png"):
self.show_message("错误", "请先生成图表")
return
# 获取选择的格式
selected_format = self.format_combo.currentText()
format_map = {
"PNG (*.png)": "png",
"JPEG (*.jpg)": "jpg"
}
ext = format_map[selected_format]
# 生成自动递增的文件名
while True:
filename = f"diagram_{self.file_counter}.{ext}"
file_path = os.path.join(self.output_dir, filename)
if not os.path.exists(file_path):
break
self.file_counter += 1
try:
image = QImage("diagram.png")
image.save(file_path)
self.show_message("成功", f"图表已保存至 {file_path}")
self.file_counter += 1
except Exception as e:
self.show_message("错误", f"保存失败: {str(e)}")
def select_output_dir(self):
dir_path = QFileDialog.getExistingDirectory(
self,
"选择保存路径",
self.output_dir
)
if dir_path:
self.output_dir = dir_path
self.path_label.setText(f"保存路径: {dir_path}")
def show_message(self, title, message):
msg = QMessageBox()
msg.setIcon(QMessageBox.Information)
msg.setText(message)
msg.setWindowTitle(title)
msg.exec_()
def main():
app = QApplication(sys.argv)
window = MermaidApp()
window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
打包了一个可执行文件地址:
https://download.csdn.net/download/bobodadao/90460665
可能需要单独安装mmdc 环境 百度搜:window 安装 nodejs mmdc