Ecology9明细表中添加操作按钮与弹窗功能技术分享

A. 概述

大家好呀,我又来了! 在Ecology9系统中,我们经常会与遇到一些需求,需要在明细表格中添加操作按钮,并通过点击按钮弹出对话框来实现更多功能。这个东西在标准的weaJs中是无法实现的,需要加入原生JS来实现,本文将详细介绍如何通过自定义渲染字段的方式,在明细表中添加"查看"按钮,并实现点击弹出数据表格的功能。

B. 实现逻辑

逻辑不难,简单划分为下面的流程图

核心机制

  1. 字段代理渲染 :利用WfForm.proxyFieldComp接口将普通文本框字段重写为按钮组件

ecology最低版本要求:KB900190407

此接口仅对单行文本框字段类型生效,即数据库字段类型为varchar

显示效果、事件、字段值交互都可自行控制,通过接口3.3修改的可编辑字段值也会正常入库

此接口传入的组件,产品会传入此字段依赖的相关props,具体可通过React Developer Tools自行抓取,按需调用

proxyFieldComp: function(fieldMark, el, range)

参数说明

|-----------|------------|--------|-------------------------------------|
| 参数 | 参数类型 | 必须 | 说明 |
| fieldMark | String | 是 | 字段标示,格式field${字段ID}_${明细行号} |
| el | React Comp | 是 | 渲染的组件 |
| range | String | 否 | 作用范围,默认全部,(1:只读、2:可编辑、3:必填),组合后逗号分隔 |

样例

javascript 复制代码
WfForm.proxyFieldComp("field111", React.createElement("div",{
  style:{background:"red"}, 
  children:"子内容"
}));
//字段111在只读、可编辑、必填情况下自定义渲染

WfForm.proxyFieldComp("field222_1", "<div>自定义渲染字段</div>", "2,3");
//明细某行字段222再可编辑、必填情况下自定义渲染
  1. 动态事件绑定:通过行索引实现按钮与对应数据的关联
  2. DOM动态创建:使用纯JavaScript创建弹窗组件,避免页面刷新

C. 代码详解

1. 初始化与事件注册

javascript 复制代码
let czDt1 = WfForm.convertFieldNameToId("cz", "detail_1"); // 操作字段id

jQuery(document).ready(function () {
  // 初始化加载明细表中已有的操作按钮
  addButton();
  // 监听明细表行添加事件
  WfForm.registerAction(WfForm.ACTION_ADDROW+"1", function(index){
    addButton();
  });
});

功能说明

  • 页面加载完成后立即初始化按钮
  • 注册明细表行添加事件,确保新增行也具备操作按钮
  • 使用convertFieldNameToId获取字段ID,确保代码可维护性

2. 按钮添加功能

javascript 复制代码
function addButton() {
    debugger
    var rowArr = WfForm.getDetailAllRowIndexStr("detail_1").split(",");
    for (var i = 0; i < rowArr.length; i++) {
        var rowIndex = rowArr[i];
        if (rowIndex !== "") {
            // 使用标准的方法:将字段组件重写成按钮组件
            WfForm.proxyFieldComp(czDt1 + "_" + rowIndex, 
                "<button onclick='showTable(\"" + rowIndex + "\")' class='search-button'>查看</button>", 
                "1,2,3,4");
        }
    }
}

关键参数说明

  • czDt1 + "_" + rowIndex:构造字段标识,格式为field${字段ID}_${明细行号}
  • "1,2,3,4":作用范围,表示在只读、可编辑、必填、隐藏状态下都显示按钮

3. 弹窗触发与数据处理

javascript 复制代码
function showTable(rowIndex) {
  // 示例数据
  const sampleData = [
    {姓名: '张三', 年龄: '28', 城市: '北京', 职业: '软件工程师'},
    {姓名: '李四', 年龄: '32', 城市: '上海', 职业: '产品经理'},
    {姓名: '王五', 年龄: '25', 城市: '广州', 职业: 'UI设计师'},
    {姓名: '赵六', 年龄: '30', 城市: '深圳', 职业: '数据分析师'}
  ];
  createTablePopup("点击的明细表行下标:" + rowIndex , sampleData)
}

数据处理流程

4. 弹窗组件实现

javascript 复制代码
function createTablePopup(title, data) {
  // 创建遮罩层
  const overlay = document.createElement('div');
  overlay.style.cssText = `
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0,0,0,0.5);
        display: flex;
        justify-content: center;
        align-items: center;
        z-index: 10000;
    `;

  // 创建弹窗容器
  const popup = document.createElement('div');
  popup.style.cssText = `
        background: white;
        padding: 25px;
        border-radius: 10px;
        box-shadow: 0 5px 15px rgba(0,0,0,0.3);
        width: 80%;
        max-width: 700px;
        max-height: 80%;
        overflow: auto;
        position: relative;
    `;

  // 创建关闭按钮
  const closeBtn = document.createElement('button');
  closeBtn.textContent = '×';
  closeBtn.style.cssText = `
        position: absolute;
        top: 15px;
        right: 20px;
        background: #e74c3c;
        border: none;
        border-radius: 50%;
        width: 25px;
        height: 25px;
        font-size: 18px;
        cursor: pointer;
        color: white;
        display: flex;
        align-items: center;
        justify-content: center;
    `;
  closeBtn.onclick = function () {
    document.body.removeChild(overlay);
  };

  // 创建标题
  const titleEl = document.createElement('h2');
  titleEl.textContent = title;
  titleEl.style.cssText = `
        margin-top: 0;
        color: #2c3e50;
        border-bottom: 2px solid #E7F3FC;
        padding-bottom: 10px;
    `;

  // 创建表格
  const table = document.createElement('table');
  table.style.cssText = `
        border-collapse: collapse;
        width: 100%;
        margin-top: 15px;
        font-size: 14px;
    `;

  // 创建表头
  const thead = document.createElement('thead');
  const headerRow = document.createElement('tr');

  // 获取表头数据
  const headers = Object.keys(data[0]);

  headers.forEach(header => {
    const th = document.createElement('th');
    th.textContent = header;
    th.style.cssText = `
            border: 1px solid #ddd;
            padding: 12px;
            background-color: #E7F3FC;
            color: black;
            text-align: left;
            font-size: 12pt;
            font-family: Microsoft YaHei;
            color: black;
        `;
    headerRow.appendChild(th);
  });
  thead.appendChild(headerRow);
  table.appendChild(thead);

  // 创建表格主体
  const tbody = document.createElement('tbody');
  data.forEach((rowData, index) => {
    const row = document.createElement('tr');
    if (index % 2 === 0) {
      row.style.backgroundColor = '#f9f9f9';
    }

    headers.forEach(header => {
      const td = document.createElement('td');
      td.textContent = rowData[header];
      td.style.cssText = `
                border: 1px solid #ddd;
                padding: 10px 12px;
            `;
            row.appendChild(td);
        });
        tbody.appendChild(row);
    });
    table.appendChild(tbody);
    
    // 组装弹窗
    popup.appendChild(closeBtn);
    popup.appendChild(titleEl);
    popup.appendChild(table);
    overlay.appendChild(popup);
    
    // 添加到页面
    document.body.appendChild(overlay);
    
    // 点击遮罩层关闭
    overlay.onclick = function (e) {
        if (e.target === overlay) {
            document.body.removeChild(overlay);
        }
    };
}

D. 实施过程

  1. 首先在流程明细表中创建一个操作字段
  1. 在代码块中贴如E.代码展示中的代码即可
  1. 效果展示

E. 代码展示

javascript 复制代码
let czDt1 = WfForm.convertFieldNameToId("cz", "detail_1"); // 操作字段id

jQuery(document).ready(function () {
    // 初始化加载明细表中已有的操作按钮
    addButton();
    // 监听明细表行添加事件
    WfForm.registerAction(WfForm.ACTION_ADDROW+"1", function(index){
        addButton();
    });
});

function addButton() {
    debugger
    var rowArr = WfForm.getDetailAllRowIndexStr("detail_1").split(",");
    for (var i = 0; i < rowArr.length; i++) {
        var rowIndex = rowArr[i];
        if (rowIndex !== "") {
            // 使用标准的方法:将字段组件重写成按钮组件
            WfForm.proxyFieldComp(czDt1 + "_" + rowIndex, "<button onclick='showTable(\"" + rowIndex + "\")' class='search-button'>查看</button>", "1,2,3,4");
        }
    }
}

function showTable(rowIndex) {
    // 示例数据
    const sampleData = [
        {姓名: '张三', 年龄: '28', 城市: '北京', 职业: '软件工程师'},
        {姓名: '李四', 年龄: '32', 城市: '上海', 职业: '产品经理'},
        {姓名: '王五', 年龄: '25', 城市: '广州', 职业: 'UI设计师'},
        {姓名: '赵六', 年龄: '30', 城市: '深圳', 职业: '数据分析师'}
    ];
    createTablePopup("点击的明细表行下标:" + rowIndex , sampleData)
}
// 弹窗表格创建函数
function createTablePopup(title, data) {
    // 创建遮罩层
    const overlay = document.createElement('div');
    overlay.style.cssText = `
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: rgba(0,0,0,0.5);
                display: flex;
                justify-content: center;
                align-items: center;
                z-index: 10000;
            `;

    // 创建弹窗容器
    const popup = document.createElement('div');
    popup.style.cssText = `
                background: white;
                padding: 25px;
                border-radius: 10px;
                box-shadow: 0 5px 15px rgba(0,0,0,0.3);
                width: 80%;
                max-width: 700px;
                max-height: 80%;
                overflow: auto;
                position: relative;
            `;

    // 创建关闭按钮
    const closeBtn = document.createElement('button');
    closeBtn.textContent = '×';
    closeBtn.style.cssText = `
                position: absolute;
                top: 15px;
                right: 20px;
                background: #e74c3c;
                border: none;
                border-radius: 50%;
                width: 25px;
                height: 25px;
                font-size: 18px;
                cursor: pointer;
                color: white;
                display: flex;
                align-items: center;
                justify-content: center;
            `;
    closeBtn.onclick = function () {
        document.body.removeChild(overlay);
    };

    // 创建标题
    const titleEl = document.createElement('h2');
    titleEl.textContent = title;
    titleEl.style.cssText = `
                margin-top: 0;
                color: #2c3e50;
                border-bottom: 2px solid #E7F3FC;
                padding-bottom: 10px;
            `;

    // 创建表格
    const table = document.createElement('table');
    table.style.cssText = `
                border-collapse: collapse;
                width: 100%;
                margin-top: 15px;
                font-size: 14px;
            `;

    // 创建表头
    const thead = document.createElement('thead');
    const headerRow = document.createElement('tr');

    // 获取表头数据
    const headers = Object.keys(data[0]);

    headers.forEach(header => {
        const th = document.createElement('th');
        th.textContent = header;
        th.style.cssText = `
                    border: 1px solid #ddd;
                    padding: 12px;
                    background-color: #E7F3FC;
                    color: black;
                    text-align: left;
                    font-size: 12pt;
                    font-family: Microsoft YaHei;
                    color: black;
                `;
        headerRow.appendChild(th);
    });
    thead.appendChild(headerRow);
    table.appendChild(thead);

    // 创建表格主体
    const tbody = document.createElement('tbody');
    data.forEach((rowData, index) => {
        const row = document.createElement('tr');
        if (index % 2 === 0) {
            row.style.backgroundColor = '#f9f9f9';
        }

        headers.forEach(header => {
            const td = document.createElement('td');
            td.textContent = rowData[header];
            td.style.cssText = `
                        border: 1px solid #ddd;
                        padding: 10px 12px;
                    `;
            row.appendChild(td);
        });
        tbody.appendChild(row);
    });
    table.appendChild(tbody);

    // 组装弹窗
    popup.appendChild(closeBtn);
    popup.appendChild(titleEl);
    popup.appendChild(table);
    overlay.appendChild(popup);

    // 添加到页面
    document.body.appendChild(overlay);

    // 点击遮罩层关闭
    overlay.onclick = function (e) {
        if (e.target === overlay) {
            document.body.removeChild(overlay);
        }
    };
}

F. 技术要点

1. 字段代理渲染的优势

  • 无侵入式修改:不需要修改原始HTML结构
  • 状态兼容:支持只读、可编辑、必填等多种字段状态
  • 动态更新:自动响应明细表行的增删操作

2. 弹窗设计特点

  • 响应式布局:自适应不同屏幕尺寸
  • 用户体验:支持点击遮罩层关闭,提供明确的关闭按钮
  • 数据可视化:清晰的表格布局,隔行变色提高可读性

3. 样式规范

  • 使用Ecology9标准配色(#E7F3FC)
  • 符合Microsoft YaHei字体规范
  • 保持与系统一致的视觉风格
相关推荐
dkgee2 小时前
如何禁止Chrome的重新启动即可更新窗口弹窗提示
前端·chrome
天若有情6732 小时前
新闻通稿 | 软件产业迈入“智能重构”新纪元:自主进化、人机共生与责任挑战并存
服务器·前端·后端·重构·开发·资讯·新闻
香香爱编程2 小时前
electron对于图片/视频无法加载的问题
前端·javascript·vue.js·chrome·vscode·electron·npm
程序猿_极客3 小时前
【期末网页设计作业】HTML+CSS+JavaScript 蜡笔小新 动漫主题网站设计与实现(附源码)
前端·javascript·css·html·课程设计·期末网页设计
zl_vslam3 小时前
SLAM中的非线性优-3D图优化之轴角在Opencv-PNP中的应用(一)
前端·人工智能·算法·计算机视觉·slam se2 非线性优化
CDwenhuohuo3 小时前
用spark-md5实现切片上传前端起node模拟上传文件大小,消耗时间
前端
阿桂有点桂4 小时前
React使用笔记(持续更新中)
前端·javascript·react.js·react
自由日记4 小时前
实例:跳动的心,火柴人
前端·css·css3
柯腾啊4 小时前
一文简单入门 Axios
前端·axios·apifox