【泛微OA Ecology 9.0】流程弹窗显示嵌入页面

案例背景

流程审批时,需要查看另一个页面的内容而不离开当前页面;想要查看另一个页面详情的同时保留当前页面状态。实现更好的用户体验,避免频繁跳转页面

这里以一个模拟案例分步说明实现方案及演示。

实现方案说明

1、在页面上新增一个浏览按钮,可参考【泛微OA Ecology 9.0】通过JavaScript 流程表单创建自定义按钮_泛微自定义按钮-优快云博客

2、创建模态框容器&CSS样式

3、JS创建模态框相关调用函数

4、绑定按钮点击事件(按实际需求设定)

详细实现步骤

创建模态框容器

// 创建模态框结构
        var modal = $(`
            <div id="performanceModal" class="performance-modal">
                <div class="modal-container">
                    <div class="modal-header">
                        <h3>明细数据</h3>
                        <button class="close-btn">&times;</button>
                    </div>
                    <div class="modal-body">
                        <iframe id="performanceFrame"></iframe>
                    </div>
                    <div class="modal-footer">
                        <button class="new-window-btn">
                            <svg width="14" height="14" viewBox="0 0 24 24">
                                <path d="M19 19H5V5h7V3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/>
                            </svg>
                            在新窗口打开
                        </button>
                    </div>
                </div>
            </div>
        `);
// 将模态框添加到页面 ===
        $("body").append(modal);

构建模态框CSS样式

以下可参考,实际按需进行调整

<style>
/* === 1. 模态框基础样式 === */
.performance-modal {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0,0,0,0.6); /* 半透明黑色背景 */
    z-index: 9999; /* 确保在最上层 */
    display: none; /* 默认隐藏 */
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.3s ease; /* 淡入动画 */
}

/* 激活状态的模态框 */
.performance-modal.active {
    display: flex;
    opacity: 1;
}

/* === 2. 模态框容器 === */
.modal-container {
    background: white;
    border-radius: 8px;
    width: 80%;
    height: 80%;
    max-width: none;
    max-height: none;
    display: flex;
    flex-direction: column; /* 垂直布局 */
    box-shadow: 0 5px 15px rgba(0,0,0,0.3); /* 阴影效果 */
    transform: translateY(-20px); /* 初始位置偏上 */
    transition: transform 0.3s ease; /* 下落动画 */
}

/* 激活状态的容器 */
.performance-modal.active .modal-container {
    transform: translateY(0); /* 回到正常位置 */
}

/* === 3. 模态框头部 === */
.modal-header {
    padding: 16px 20px;
    border-bottom: 1px solid #eee; /* 底部边框 */
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.modal-header h3 {
    margin: 0;
    font-size: 18px;
    color: #333;
}

/* 关闭按钮样式 */
.close-btn {
    background: none;
    border: none;
    font-size: 24px;
    cursor: pointer;
    color: #666;
    padding: 0 8px;
}

/* === 4. 模态框主体 === */
.modal-body {
    flex: 1; /* 占据剩余空间 */
    min-height: 600px;
    overflow: hidden;
    padding: 0;
}

/* iframe样式 */
#performanceFrame {
    width: 100%;
    height: 100%;
    border: none;
    display: block;
}

/* === 5. 模态框底部 === */
.modal-footer {
    padding: 12px 20px;
    border-top: 1px solid #eee; /* 顶部边框 */
    text-align: right;
}

/* 新窗口打开按钮 */
.new-window-btn {
    background: none;
    border: none;
    color: #1890ff; /* 主题蓝色 */
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    padding: 5px 10px;
    border-radius: 4px;
}

/* 鼠标悬停效果 */
.new-window-btn:hover {
    background: #f0faff; /* 浅蓝色背景 */
}

/* === 6. 加载动画 === */
.loading-spinner {
    display: inline-block;
    width: 12px;
    height: 12px;
    border: 2px solid rgba(0,0,0,0.2);
    border-radius: 50%;
    border-top-color: #000; /* 顶部边框颜色不同,形成旋转效果 */
    animation: spin 1s linear infinite; /* 无限旋转动画 */
    margin-right: 8px;
}

/* 旋转动画定义 */
@keyframes spin {
    to { transform: rotate(360deg); }
}
</style>

模态框调用相关函数

// === 1. 显示模态框函数 ===
function showModal(url) {
    const $modal = $('#performanceModal');
    const $iframe = $('#performanceFrame');

    // 先清空iframe再重新加载,避免缓存问题
    $iframe.attr('src', 'about:blank');
    setTimeout(() => {
        $iframe.attr('src', url);
        $modal.addClass('active');
    }, 100);
}

// === 2. 关闭模态框事件 ===
$(document).on('click', '#performanceModal .close-btn, #performanceModal', function (e) {
    // 点击关闭按钮或模态框外部时关闭
    if ($(e.target).closest('.modal-container').length === 0 || $(e.target).hasClass('close-btn')) {
        $('#performanceModal').removeClass('active');
        $('#performanceFrame').attr('src', 'about:blank');
    }
});

// === 3. ESC键关闭模态框 ===
$(document).keyup(function (e) {
    if (e.key === "Escape") {
        $('#performanceModal').removeClass('active');
    }
});

完整代码

案例说明:

        点击页面上【查看明细数据】按钮,根据表单上"field111"和"field222"两个字段的值,请求后端接口获取对应明细数据的"id"。

        将获取到的"id"与模块卡片页面的URL进行拼接,生成一个完整的跳转URL并进行跳转。

JavaScript实现

'use strict';
// 使用初始化标志确保只执行一次
if (!window.performanceModalInitialized) {
    window.performanceModalInitialized = true;

    jQuery(document).ready(function ($) {
        // === 1. 创建UI元素 ===
        // 创建 查看明细数据 按钮
        var button = $(`
            <button id="performanceBtn"
                    title="查看明细数据"
                    type="button"
                    class="ant-btn ant-btn-primary">
                查看明细数据
            </button>
        `);

        // 创建模态框结构
        var modal = $(`
            <div id="performanceModal" class="performance-modal">
                <div class="modal-container">
                    <div class="modal-header">
                        <h3>明细数据</h3>
                        <button class="close-btn">&times;</button>
                    </div>
                    <div class="modal-body">
                        <iframe id="performanceFrame"></iframe>
                    </div>
                    <div class="modal-footer">
                        <button class="new-window-btn">
                            <svg width="14" height="14" viewBox="0 0 24 24">
                                <path d="M19 19H5V5h7V3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/>
                            </svg>
                            在新窗口打开
                        </button>
                    </div>
                </div>
            </div>
        `);

        // === 2. 将元素添加到页面 ===
        $("#ckmx").append(button); // 添加按钮到表单'ckmx'位置
        $("body").append(modal);

        // === 3. 绑定按钮点击事件 ===
        button.on("click", async function () {
            // 保存原始按钮内容,用于恢复
            var originalHtml = button.html();

            // 显示加载状态
            button.prop('disabled', true)
                .html('<span class="loading-spinner"></span> 加载中...');

            try {
                // 3.1 获取明细数据ID
                const performanceId = await fetchPerformanceData();

                // 3.2 构建详情页URL
                const targetUrl = buildPerformanceUrl(performanceId);

                // 3.3 显示模态框
                showModal(targetUrl);

                // 3.4 绑定新窗口打开按钮事件
                $('.new-window-btn').off('click').on('click', function () {
                    window.open(targetUrl, '_blank');
                });

            } catch (error) {
                // 错误处理
                console.error("操作失败:", error);
                alert("获取明细数据失败: " + error.message);
            } finally {
                // 恢复按钮状态
                button.prop('disabled', false).html(originalHtml);
            }
        });

        // === 4. 关闭模态框事件 ===
        $(document).on('click', '#performanceModal .close-btn, #performanceModal', function (e) {
            // 点击关闭按钮或模态框外部时关闭
            if ($(e.target).closest('.modal-container').length === 0 || $(e.target).hasClass('close-btn')) {
                $('#performanceModal').removeClass('active');
                $('#performanceFrame').attr('src', 'about:blank');
            }
        });

        // === 5. ESC键关闭模态框 ===
        $(document).keyup(function (e) {
            if (e.key === "Escape") {
                $('#performanceModal').removeClass('active');
            }
        });

        // === 6. 数据获取函数 ===
        async function fetchPerformanceData() {
            // 6.1 获取表单数据
            const param1 = WfForm.getFieldValue("field111"); // 获取必填字段1
            const param2 = WfForm.getFieldValue("field222"); // 获取必填字段2

            // 6.2 验证必填字段
            if (!param1 || !param2) throw new Error("请填写完整信息");

            // 6.3 请求明细数据
            const result = await $.ajax({
                type: "POST",
                url: "/api/performance/getPrevious", // 以实际接口链接为准,请替换为实际URL
                data: {
                    param1, param2
                },
                dataType: "json"
            });

            // 6.4 验证返回结果
            if (!result?.[0]?.id) throw new Error("未获取到明细数据");

            return result[0].id;
        }

        // === 7. URL构建函数 ===
        function buildPerformanceUrl(id) {
            return `/spa/cube/index.html#/main/cube/card?type=0&modeId=49&formId=-113&opentype=0&customid=59&billid=${id}`; //以实际链接为准,请替换为实际URL
        }

        // === 8. 显示模态框函数 ===
        function showModal(url) {
            const $modal = $('#performanceModal');
            const $iframe = $('#performanceFrame');

            // 先清空iframe再重新加载,避免缓存问题
            $iframe.attr('src', 'about:blank');
            setTimeout(() => {
                $iframe.attr('src', url);
                $modal.addClass('active');
            }, 100);
        }
    });
}

CSS样式

<style>
/* === 1. 模态框基础样式 === */
.performance-modal {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0,0,0,0.6); /* 半透明黑色背景 */
    z-index: 9999; /* 确保在最上层 */
    display: none; /* 默认隐藏 */
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.3s ease; /* 淡入动画 */
}

/* 激活状态的模态框 */
.performance-modal.active {
    display: flex;
    opacity: 1;
}

/* === 2. 模态框容器 === */
.modal-container {
    background: white;
    border-radius: 8px;
    width: 80%;
    height: 80%;
    max-width: none;
    max-height: none;
    display: flex;
    flex-direction: column; /* 垂直布局 */
    box-shadow: 0 5px 15px rgba(0,0,0,0.3); /* 阴影效果 */
    transform: translateY(-20px); /* 初始位置偏上 */
    transition: transform 0.3s ease; /* 下落动画 */
}

/* 激活状态的容器 */
.performance-modal.active .modal-container {
    transform: translateY(0); /* 回到正常位置 */
}

/* === 3. 模态框头部 === */
.modal-header {
    padding: 16px 20px;
    border-bottom: 1px solid #eee; /* 底部边框 */
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.modal-header h3 {
    margin: 0;
    font-size: 18px;
    color: #333;
}

/* 关闭按钮样式 */
.close-btn {
    background: none;
    border: none;
    font-size: 24px;
    cursor: pointer;
    color: #666;
    padding: 0 8px;
}

/* === 4. 模态框主体 === */
.modal-body {
    flex: 1; /* 占据剩余空间 */
    min-height: 600px;
    overflow: hidden;
    padding: 0;
}

/* iframe样式 */
#performanceFrame {
    width: 100%;
    height: 100%;
    border: none;
    display: block;
}

/* === 5. 模态框底部 === */
.modal-footer {
    padding: 12px 20px;
    border-top: 1px solid #eee; /* 顶部边框 */
    text-align: right;
}

/* 新窗口打开按钮 */
.new-window-btn {
    background: none;
    border: none;
    color: #1890ff; /* 主题蓝色 */
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    padding: 5px 10px;
    border-radius: 4px;
}

/* 鼠标悬停效果 */
.new-window-btn:hover {
    background: #f0faff; /* 浅蓝色背景 */
}

/* === 6. 加载动画 === */
.loading-spinner {
    display: inline-block;
    width: 12px;
    height: 12px;
    border: 2px solid rgba(0,0,0,0.2);
    border-radius: 50%;
    border-top-color: #000; /* 顶部边框颜色不同,形成旋转效果 */
    animation: spin 1s linear infinite; /* 无限旋转动画 */
    margin-right: 8px;
}

/* 旋转动画定义 */
@keyframes spin {
    to { transform: rotate(360deg); }
}
</style>

关键点说明

  1. 初始化控制:使用window.performanceModalInitialized确保脚本只执行一次

  2. UI构建

    • 动态创建按钮和模态框元素

    • 模态框包含header、body和footer三部分

    • body部分使用iframe加载外部内容

  3. 数据获取

    • 从表单获取查询信息

    • 通过AJAX请求获取建模表单的数据ID

  4. 交互逻辑

    • 按钮点击时显示加载状态

    • 成功获取数据后显示模态框

    • 支持新窗口打开

    • 多种关闭方式(按钮、点击外部、ESC键)

  5. 动画效果

    • 模态框淡入淡出

    • 内容区域下落动画

    • 加载旋转动画

  6. 错误处理

    • 表单验证

    • 数据获取验证

    • 友好的错误提示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值