You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Balkan OrgChartJS自定义编辑表单添加PDF导出功能

自定义OrgChartJS编辑表单的PDF导出解决方案

问题说明

我使用Balkan的OrgChartJS制作了自定义编辑表单,但目前无法将该表单导出为PDF。默认编辑表单自带PDF导出选项,但不清楚如何为包含HTML、CSS和图片的自定义编辑表单添加该功能。

现有JS代码

var chart;
fetch('url', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    },
    body: JSON.stringify({ rootId: rootNodeId })
})
.then(response => response.json())
.then(data => {
    var myNodes = data.d;
    console.log(myNodes);

    OrgChart.scroll.smooth = 8;
    OrgChart.scroll.speed = 12;

    OrgChart.templates.ana.field_0 = '<text class="field_0 style="font-size:20px !important; font-family=verdana, Arial !important;" fill="#ffffff" x="120" y="30" text-anchor="middle">{val}</text>';
    OrgChart.templates.ana.field_1 = '<text class="field_1 style="font-size:14px;font-family=verdana, Arial !important;" fill="#ffffff" x="120" y="50" text-anchor="middle">{val}</text>';
    OrgChart.templates.ana.field_2 = '<text class="field_2 style="font-size:14px;font-family=verdana, Arial !important;" fill="#ffffff" x="150" y="80" text-anchor="middle">DOJ: {val}</text>';
    OrgChart.templates.ana.field_3 = '<text class="field_3 style="font-size:14px;font-family=verdana, Arial !important;" fill="#ffffff" x="150" y="100" text-anchor="middle">Division: {val}</text>';
    OrgChart.templates.ana.img_0 = '<image preserveAspectRatio="xMidYMid slice" xlink:href="{val}" x="-10" y="65" width="60" height="60"></image>';

    var editForm = function () {
        this.nodeId = null;
    };

    editForm.prototype.init = function (obj) {
        var that = this;
        this.obj = obj;
        this.editForm = document.getElementById("editForm");
        this.nameInput = document.getElementById("Name");
        this.titleInput = document.getElementById("Designation");
        this.imgInput = document.getElementById("Photo");
        this.dojInput = document.getElementById("DOJ");
        this.divisionInput = document.getElementById("Division");

        this.cancelButton = document.getElementById("close");

        this.cancelButton.addEventListener("click", function () {
            that.hide();
        });
    };

    editForm.prototype.show = function (nodeId) {
        this.nodeId = nodeId;

        var left = document.body.offsetWidth / 2 - 150;

        this.editForm.style.left = left + "px";
        var node = chart.get(nodeId);
        if (!node) return;
        this.imgInput.src = node.Photo ? node.Photo : "#";
        this.nameInput.innerHTML = node.Name ? node.Name : "";
        this.titleInput.textContent = node.Designation ? node.Designation : "";
        this.dojInput.textContent = node.DOJ ? node.DOJ : "";
        this.divisionInput.textContent = node.Division ? node.Division : "";
        this.editForm.style.display = "flex";
        this.editForm.style.minHeight = "70vh";
        this.editForm.style.background = "transparent";
        

        OrgChart.animate(this.editForm, {
            opacity: 0
        }, {
            opacity: 1
        }, 300, OrgChart.anim.inOutSin);
    };

    editForm.prototype.hide = function (showldUpdateTheNode) {
        this.editForm.style.display = "none";
        this.editForm.style.opacity = 0;

    };

    OrgChart.miniMap.opacity = 0.8;
    OrgChart.miniMap.border = '2px solid #039BE5';
    OrgChart.miniMap.width = 80;
    OrgChart.miniMap.height = 75;
    OrgChart.miniMap.padding = 10;
    OrgChart.miniMap.top = '15px';
    OrgChart.miniMap.position = {
        top: 'padding',
        left: 'padding',
        right: 'undefined',
        bottom: 'undefined'
    };

    // ***************************************************************************
    chart = new OrgChart(document.getElementById('tree'), {
        lazyLoading:false,
        miniMap: true,
        mouseScrool: OrgChart.none,
        mouseScrool: OrgChart.action.scroll,
        padding: 70,
        enableSearch: true,
        layout: OrgChart.tree,
        align: OrgChart.ORIENTATION,
        toolbar: {
            layout: true,
            zoom: true,
            fit: true,
            expandAll: true,
            fullScreen:true
        },
        menu: {
            export_pdf: {
                text: "Export PDF",
                icon: OrgChart.icon.pdf(24,24,"#7A7A7A"),
                onClick: pdf
            },
            pdfPreview: {
                text: "PDF Preview",
                icon: OrgChart.icon.pdf(24, 24, "#7A7A7A"),
                onClick: preview
            }
        },
        nodeBinding: {
            field_0: "Name",
            field_1: "Designation",
            field_2: "DOJ",
            field_3: "Division",
            img_0: "Photo"
        },
        editUI: new editForm(),
        nodes: myNodes
        
    });
});

现有ASPX代码

<div id="editForm" style="
        position:absolute;
        top:50%;
        left:50%;
        margin-top:-50px;
        margin-left:-50px;
        display:none;
        opacity:0;
        text-align:center;
        border: transparent;
        width:300px;
        background-color:#fff;
        z-index: 10000;
        border-radius:15px;
        filter:drop-shadow(5px 5px 5px #909090);
        ">
        <div class="card">
            <div class="imgBx">
                <img id="Photo" src="" />
            </div>
            <div class="content">
                <span id="close">X</span>
                <div class="details">
                    <h3 id="Name">Name</h3>
                    <h3 id="Designation">Designation</h3>
                    <div class="data">
                        <h4 id="DOJ"></h4><br /> <div class="span">Date Of Joining</div>
                        <h4 id="Division"></h4><br /> <div class="span">Division</div>
                    </div>
                </div>
            </div>
            
        </div>
        
        
    </div>

    <div id="tree" class="chart-container"></div>

解决方案

OrgChart自带的PDF导出仅针对组织结构图,自定义编辑表单是独立的HTML元素,需要通过前端库捕捉表单视觉内容并生成PDF。这里使用html2canvas(将HTML转为Canvas)和jsPDF(生成PDF)实现:

步骤1:添加库依赖

在页面中引入两个库的本地脚本(避免外链):

<script src="html2canvas.min.js"></script>
<script src="jspdf.umd.min.js"></script>

步骤2:修改ASPX表单,添加导出按钮

在editForm的.content区域内添加导出按钮:

<div class="content">
    <span id="close">X</span>
    <button id="exportFormBtn" style="margin:10px; padding:8px 16px; cursor:pointer;">导出表单为PDF</button>
    <!-- 原有内容保持不变 -->
</div>

步骤3:修改JS代码,添加导出逻辑

在editForm.prototype.init方法中添加导出按钮的事件监听,并新增导出方法:

editForm.prototype.init = function (obj) {
    var that = this;
    this.obj = obj;
    this.editForm = document.getElementById("editForm");
    this.nameInput = document.getElementById("Name");
    this.titleInput = document.getElementById("Designation");
    this.imgInput = document.getElementById("Photo");
    this.dojInput = document.getElementById("DOJ");
    this.divisionInput = document.getElementById("Division");
    this.cancelButton = document.getElementById("close");
    // 新增导出按钮引用
    this.exportButton = document.getElementById("exportFormBtn");

    this.cancelButton.addEventListener("click", function () {
        that.hide();
    });
    // 绑定导出按钮点击事件
    this.exportButton.addEventListener("click", function () {
        that.exportFormToPdf();
    });
};

// 新增PDF导出方法
editForm.prototype.exportFormToPdf = function () {
    const formElement = this.editForm;
    // 用html2canvas渲染表单
    html2canvas(formElement, {
        scale: 2, // 提高导出清晰度
        useCORS: true, // 处理跨域图片(若图片来自外部域名)
        logging: false
    }).then(canvas => {
        // 初始化jsPDF
        const pdf = new jspdf.jsPDF('p', 'mm', 'a4');
        const imgWidth = 210; // A4宽度(mm)
        const imgHeight = canvas.height * imgWidth / canvas.width;
        let position = 0;

        // 将Canvas添加到PDF
        pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, position, imgWidth, imgHeight);
        
        // 若表单内容过长,自动分页
        let heightLeft = imgHeight;
        while (heightLeft >= 297) { // A4高度(mm)
            position = heightLeft - imgHeight;
            pdf.addPage();
            pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, position, imgWidth, imgHeight);
            heightLeft -= 297;
        }

        // 保存PDF,文件名包含节点ID
        pdf.save(`employee_form_${this.nodeId}.pdf`);
    }).catch(err => {
        console.error('导出失败:', err);
    });
};

关键说明

  • 若表单中的图片来自外部域名,需确保服务器配置了CORS允许跨域访问,否则html2canvas无法渲染图片
  • 调整scale参数可控制导出清晰度,数值越高越清晰但文件越大
  • 可根据表单实际尺寸修改PDF的页面尺寸和图片位置参数

内容的提问来源于stack exchange,提问作者Raj Shukla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 13:57:00