| name | ewa-listframe |
| description | Use when: 编写 EWA ListFrame 列表前端 JS 代码、行数据操作、选中行、翻页排序、检索过滤、展开行详情、动态列、底部汇总、行内编辑。按任务组织,含完整代码示例。 |
| trigger | ewa-listframe, EWA ListFrame, 列表操作, 行数据, SelectChecked, GetRowKey, AddPreRow, 翻页, 排序, 检索, 展开行, 动态列, 底部汇总, 行内编辑, EWA_ListFrameClass |
EWA ListFrame 操作指南
面向前端 JS 开发者的 EWA ListFrame 列表操作参考。按任务组织,每个场景给完整可用的代码。
ewa 变量 = EWA.F.FOS['@SYS_FRAME_UNID'] — 当前 ListFrame 实例。
列表帧容器 ID 为 #EWA_LF_@SYS_FRAME_UNID。
参考示例
示例配置在缓存目录 /Users/admin/java/ewa_page_cached_pf2023/scripts_cached/examples/:
index.xml # 首页列表
member_card.xml # 会员卡(合并列 + ReloadAfter)
product_cat.xml # 产品分类(Tree)
sysatts.xml # 文件附件(MergeExp + DOM 操作)
自动触发:当用户要求编写 ListFrame 相关代码时,先读取示例参考实际用法:
read_file /Users/admin/java/ewa_page_cached_pf2023/scripts_cached/examples/member_card.xml
框架文档参考
遇到 ListFrame 配置、luButtons/luSearch 等概念不确定时,读取框架文档获取权威解释:
| 文档 | 说明 |
|---|
framework/emp-script/docs/zhcn/LISTFRAME_EXECUTION.md | ListFrame 执行流程(分页/搜索/排序/按钮重绘) |
framework/emp-script/docs/zhcn/EWA_PARAMETERS.md | EWA URL 参数(EWA_LU_BUTTONS 等) |
framework/emp-script/docs/zhcn/EWA_TEMPLATE_REFERENCE.md | XML 模板属性完整参考(ListUI/Set) |
| 易错概念 | 正确含义 |
|---|
luButtons="1" | 重绘按钮到工具栏(不是"启用按钮") |
自动触发:当对 ListUI 属性、按钮行为、URL 参数等概念不确定时,先 read_file 对应框架文档再操作。
速查表
| 任务 | 方法 | 优先级 |
|---|
| 🔥 获取选中行键值 | ewa.SelectChecked() | 高频 |
| 🔥 从 DOM 获取行信息 | ewa.GetRowKey() / ewa.GetRow() | 高频 |
| 🔥 刷新列表 | ewa.Reload() | 高频 |
| 🔥 调用后端 Action | ewa.DoAction() | 高频 |
| 🔥 翻页 / 排序 | ewa.Goto() / ewa.Sort() | 高频 |
| 📋 打开检索对话框 | ewa.Search() | 中频 |
| 📋 内联检索栏 | ewa.ShowSearch() | 中频 |
| 📋 展开行详情 | ewa.AddPreRow() | 中频 |
| 📋 动态添加列 | ewa.AddColumns() | 中频 |
| 📋 底部汇总 | ewa.SubBottoms() | 中频 |
| 📋 合并列 | ewa.Merge() / ewa.MergeExp() | 中频 |
| 📋 行内编辑 | ewa.ShowEdit() | 中频 |
| 🔧 局部刷新 | ewa.replaceRowsData() | 低频 |
| 🔧 固定表头/列 | ewa.stickyHeaders() / ewa.stickyColumns() | 低频 |
1. 行数据操作
获取选中行键值
var keys = ewa.SelectChecked();
var rows = ewa.SelectCheckedRows();
var inputs = ewa.SelectCheckedInputs();
从 DOM 元素获取所在行信息
var rowKey = ewa.GetRowKey(buttonEl);
var tr = ewa.GetRow(buttonEl);
获取行内字段值
function getObj(exp){
return exp ? $('#EWA_LF_@SYS_FRAME_UNID').find(exp) : $('#EWA_LF_@SYS_FRAME_UNID');
}
var value = getObj('#FIELD_NAME').text();
var value = getObj('#FIELD_NAME input').val();
ewa.SelectCheckedRows().forEach(function(tr){
var key = ewa.GetRowKey(tr);
var name = $(tr).find('#FIELD_NAME').text();
console.log(key, name);
});
行点击事件
ewa.MDownEvent = function(frameUnid, tr, key, newTr, evt){
console.log("行键值:", key);
};
ewa.AddPreRowCheck = function(tr, key, evt){
return true;
};
双击行触发按钮
ewa.DblClick(0);
2. 翻页与排序
翻页
ewa.Goto(2);
ewa.Goto(1, refUrl);
排序
ewa.Sort("CREATE_DATE");
ewa.Sort("CREATE_DATE desc");
排序有 500ms 防抖。URL 参数 EWA_LF_ORDER 控制排序字段。
切换每页条数
ewa.NewPageSize(50);
3. 检索
打开检索对话框
ewa.Search();
显示内联检索栏
ewa.ShowSearch();
ewa.ShowSearch(true);
清除检索
ewa.SearchClear();
标记检索关键词
ewa.SearchMark();
日期范围检索
ewa.SearchFilterDate("Today");
ewa.SearchFilterDate("Week");
ewa.SearchFilterDate("Month");
ewa.SearchFilterDate("Quarter");
ewa.SearchFilterDate("Year");
ewa.SearchFilterDate("Today-EOM");
ewa.SearchFilterDate("Clear");
URL 参数初始化检索
var u = ewa.getUrlClass();
u.RemoveEwa();
u.AddParameter("ewa_search", "FIELD_NAME[lk]关键词,STATUS[eq]1");
ewa.Reload(u.GetUrl());
4. 展开行详情
基本展开行模式
ewa.AddPreRow(function(frameUnid, tr, key, newTr, evt){
var u = new EWA_UrlClass(ewa.getUrlClass().GetUrl());
u.AddParameter("itemname", "DETAIL.LF.View");
u.AddParameter("id", key);
$Install(u.GetUrl(), newTr.cells[0].id, function(){});
});
自定义展开前检查
ewa.AddPreRowCheck = function(tr, key, evt){
if (!hasPermission(key)) {
$Tip("无权限查看");
return false;
}
return true;
};
展开行关闭事件
ewa.AddPreRowCloseBeforeEvent = function(frameUnid, tr, key, newTr, evt){
};
ewa.AddPreRowCloseEvent = function(frameUnid, tr, key, newTr, evt){
};
5. 选中行模式
单选模式
ewa.SelectSingle();
多选模式
ewa.SelectMulti();
全选 / 取消全选
ewa.CheckedAll();
ewa.CheckedAllAfter = function(){
var count = ewa.SelectCheckedRows().length;
$Tip("已选中 " + count + " 行");
};
禁用自动点击选中
ewa.IsNotMDownAutoChecked = true;
单选 + checkbox 多选混合模式
luSelect="S"(单选)+ 每行加 <input type="checkbox"> 可实现:点行 = 单选,点 checkbox = 多选。
原理:checkMDownEnable() 检测到点击目标是 INPUT 时返回 false,行选择流程不执行,checkbox 原生 toggle 不受干扰。点击行(TD)时,mDownAutoCheck() 自动勾选当前行 checkbox。
<ListUI><Set luSelect="S"/></ListUI>
<XItem Name="CK">
<Tag><Set Tag="checkbox"/></Tag>
<DataItem><Set DataField="ID"/></DataItem>
</XItem>
SelectChecked() 优先从 checkbox 的 checked 状态取值,所以混合模式下能正确返回所有勾选行的 ID。
6. 动态列操作
添加列
ewa.AddColumns([
{
colId: "NEW_COL",
colText: "新列",
colHtml: "@@VALUE",
colType: "span"
}
]);
ewa.AddColumns([
{ colId: "ACTIONS", colText: "操作", colHtml: '<button onclick="doAction(@@ID)">编辑</button>' }
], "ACTIONS", "操作", "", "span", [
{ Name: "class", Value: "action-col" }
]);
显示/隐藏列
ewa.ShowHiddenColumn(3, "block");
ewa.ShowHiddenColumn(3, "none");
ewa.ShowHiddenColumns([1, 3, 5], "none");
固定表头 / 固定列
ewa.stickyHeaders();
ewa.stickyColumns(2);
注意:stickyHeaders 和 stickyColumns 互斥,不能同时使用。
7. 底部汇总
对列求和
ewa.SubBottoms("AMOUNT,QANTITY");
重新计算汇总
ewa.reCalcBottoms();
8. 合并列
重要:ewa.Merge / ewa.MergeExp 等数据加载后需要渲染的操作,必须放在 ewa.ReloadAfter 函数内,确保每次列表刷新后都能正确执行:
ewa.ReloadAfter = function(httpReferer) {
ewa.Merge('COL_A', 'COL_B', ' ~ ');
ewa.Merge('COL_C', 'COL_D', '<br>');
};
简单合并
ewa.Merge("FROM_COL_ID", "TO_COL_ID");
表达式合并
var exp = "@@NAME (@AGE) - @@DEPT";
ewa.MergeExp("TO_COL_ID", exp);
批量合并
ewa.Merges([
{ from: "COL_A", to: "COL_B", str: "@@COL_A @@COL_B" },
{ from: "COL_C", to: "COL_D", header: true }
]);
合并表头
ewa.mergeHeaders("FROM_ID", "合并后的标题", 2);
9. 行内编辑
显示编辑控件
ewa.ShowEdit(cellElement);
编辑完成
编辑完成后框架自动触发 OnListFrameUpdateCell Action。
10. 局部刷新(不重载页面)
基于数据对比的局部刷新
ewa.replaceRowsData(
searchExp,
function(sourceTd, targetTd){
targetTd.innerHTML = sourceTd.innerHTML;
},
httpReferer,
function(changedTrClones){
console.log(changedTrClones.length + " 行已更新");
},
true
);
基于 HTML 的局部刷新
ewa.replaceRowsWithDataHtml(
newHtmlString,
function(sourceTd, targetTd){
targetTd.innerHTML = sourceTd.innerHTML;
},
httpReferer,
function(changedTrClones){},
true
);
GOTCHA:需要 URL 参数 ewa_row_sign=yes 启用 MD5 行签名对比,才能跳过未变化的行。
刷新页面(局部)
ewa.refreshPage(httpReferer, callBack, isStopReload);
11. 添加行
追加新行
ewa.AddRow(["单元格1", "单元格2", "单元格3"]);
插入展开行
var newTr = ewa.newRowOneTd(currentTr);
12. 按钮映射
按钮点击映射
ewa.BindButton("BUTTON_A", "BUTTON_B");
13. 调用后端 Action
带行键值的 Action
ewa.DoAction(buttonEl, "UAct0", "确认删除?", "删除成功");
批量操作选中行
var keys = ewa.SelectChecked();
if (!keys) {
$Tip("请先选中要操作的行");
return;
}
ewa.DoAction(this, "BatchAction", "确认批量操作?", "操作完成");
批量操作 — 弹出对话框
ewa.ext_batchAction = function(){
var ids = ewa.SelectChecked();
if(!ids){ $Tip("请先勾选要操作的记录"); return; }
var u1 = ewa.getUrlClass();
u1.RemoveEwa();
u1.AddParameter("MC_IDS_BATCH", ids);
u1.AddParameter("EWA_MTYPE", "N");
EWA.UI.Dialog.OpenReloadClose("@SYS_FRAME_UNID", "@xmlName", "TARGET_FRAME.F.NM", false, u1.GetParas());
};
关键:传给弹窗前必须 u1.RemoveEwa(),否则弹窗会继承当前列表的 XMLNAME/ITEMNAME,导致加载错误的模板。
14. 新建 / 修改记录
方式一:框架自动生成的 ext_NewOrModifyOrCopy
ListFrame 创建时框架自动注入此方法(定义在 EwaDefine.xml 模板中):
ewa.ext_NewOrModifyOrCopy("N");
ewa.ext_NewOrModifyOrCopy("M", "id=123");
ewa.ext_NewOrModifyOrCopy("C", "id=123");
优势:可添加额外参数,如 EWA_IN_DIALOG:
ewa.ext_NewOrModifyOrCopy = function(mtype, pkParas){
const u1 = new EWA_UrlClass(ewa.Url);
u1.RemoveEwa();
u1.AddParameter("EWA_MTYPE", mtype);
u1.AddParameter("EWA_IN_DIALOG", "1");
let paras = u1.GetParas();
if(pkParas) paras += '&' + pkParas;
EWA.UI.Dialog.OpenReloadClose('@SYS_FRAME_UNID', '@xmlName', 'TABLE_NAME.F.NM', false, paras);
};
方式二:内置方法 RecordNew / RecordModify
ewa.RecordNew("@xmlName", "ITEM.F.N", "extra_param1=v1");
ewa.RecordModify("@xmlName", "ITEM.F.M", "extra_param1=v1");
15. 分组显示
分组折叠/展开
ewa.GroupShowHidden(this);
16. 组合检索框
ewa.composeSearchTexts();
17. 导出数据
ewa.DownloadData("excel");
ewa.DownloadData("csv");
ewa.DownloadData("pdf", "ExportAction");
18. 工具方法
获取 URL 对象
var u = ewa.getUrlClass();
u.AddParameter("EWA_MTYPE", "N");
ewa.Reload(u.GetUrl());
带参数重新加载
ewa.changeTag("param1=v1¶m2=v2");
切换按钮显示位置
ewa.ReShow();
ewa.ReShowWithNoButtons();
ewa.ReShowButtonsInDailogTitle();
19. EWA_ URL 参数速查
高频实用
| 参数 | 说明 | 示例 |
|---|
EWA_IN_DIALOG | 1 = 固定高度窗口打开,内容自适应滚动 | u1.AddParameter("EWA_IN_DIALOG", "1") |
EWA_P_BEHAVIOR | 行为链:RELOAD_PARENT,CLOSE_SELF | EWA_P_BEHAVIOR=RELOAD_PARENT,CLOSE_SELF |
EWA_PARENT_FRAME | 父帧 UNID,配合行为链使用 | EWA_PARENT_FRAME=@SYS_FRAME_UNID |
EWA_SEARCH | 高级检索表达式 | ewa_search=FIELD[lk]关键词,STATUS[eq]1 |
EWA_NO_CONTENT | 1 = 仅执行不输出内容 | 用于纯后端操作 |
EWA_JSON_FIELD_CASE | JSON 字段大小写:lower/upper | EWA_JSON_FIELD_CASE=lower |
EWA_RECYCLE | NO = 隐藏回收箱 | EWA_RECYCLE=NO |
EWA_PAGESIZE | 每页条数 | EWA_PAGESIZE=50 |
EWA_IS_SPLIT_PAGE | yes/no 强制分页开关 | EWA_IS_SPLIT_PAGE=no |
少用但好用
| 参数 | 说明 | 示例 |
|---|
EWA_HIDDEN_FIELDS | 按条件隐藏字段,在 <LogicShow> 中配置 | <Set HiddenFields="FIELD_A,FIELD_B" Name="rule" ParaExp="'@MODE'='VIEW'"/> |
EWA_FRAME_UNID_PREFIX | 更改帧 UNID 前缀,避免同页面多个帧冲突 | EWA_FRAME_UNID_PREFIX=my_prefix_ |
EWA_LANG | 语言切换:zhcn/enus,会保留到 session | EWA_LANG=enus |
EWA_FRAMESET_NO | 1 = 不显示 frame 框架 | EWA_FRAMESET_NO=1 |
EWA_WIDTH / EWA_HEIGHT | 覆盖帧尺寸 | EWA_WIDTH=900&EWA_HEIGHT=600 |
EWA_HIDDEN_FIELDS 按条件隐藏字段
在 XML 的 <LogicShow> 中配置,根据参数条件动态隐藏字段:
<LogicShow>
<Set HiddenFields="FIELD_A,FIELD_B" Name="hideInView" ParaExp="'@MODE'='VIEW'"/>
<Set HiddenFields="butAdd,butDelete" Name="hideButtons" ParaExp="'@EWA_AJAX'='DOWN_DATA'"/>
</LogicShow>
ParaExp 使用 SQL 表达式语法,支持 and/or/1=2(永远隐藏)等。
常见陷阱
| 陷阱 | 解决 |
|---|
| 列表帧选择器前缀 | 用 #EWA_LF_@SYS_FRAME_UNID,不是 #EWA_FRAME_ |
SelectChecked() 返回空 | 检查 IsTrSelect 是否启用(调用 SelectSingle() 或 SelectMulti()) |
| 局部刷新不生效 | URL 需带 ewa_row_sign=yes 启用 MD5 行签名 |
stickyHeaders 和 stickyColumns 冲突 | 两者互斥,只能用其中一个 |
| DoAction 无响应 | ListFrame 的 DoAction 有 1000ms 防抖(APP 模式) |
| 检索条件不清除 | 调用 ewa.SearchClear() 清除检索 |
getUrlClass().GetParameter() 取不到值 | EWA 的 URL 参数优先用 ewa.Url 上的 EWA_UrlClass 实例获取:let u = ewa.getUrlClass(); u.GetParameter("KEY") |
| 批量操作需要多选模式 | XML 中 <ListUI> 设置 luSelect="M" 启用多选,单条模式 luSelect="S" |
| 按钮 URL 缺少上下文路径 | JS 中拼接 URL 用 EWA.CP + '/path',不要硬编码 /path |