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

核心机制
- 字段代理渲染 :利用
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再可编辑、必填情况下自定义渲染
- 动态事件绑定:通过行索引实现按钮与对应数据的关联
- 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. 实施过程
- 首先在流程明细表中创建一个操作字段

- 在代码块中贴如E.代码展示中的代码即可

- 效果展示

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字体规范
- 保持与系统一致的视觉风格