diff --git a/public/static/plugs/ulthon-admin/admin-table.js b/public/static/plugs/ulthon-admin/admin-table.js index 84ba31f..347a286 100644 --- a/public/static/plugs/ulthon-admin/admin-table.js +++ b/public/static/plugs/ulthon-admin/admin-table.js @@ -25,6 +25,57 @@ return originalTableReloadData.apply(this, arguments); }; + // 受控表渲染接线(加载期执行一次):store 的 fetch/reload 只负责取数与状态、 + // 不触发渲染,这里在唯一的数据到达点(store.reload 的成功回调)注入引擎 + // 纯渲染——首屏/搜索/排序/switch 回滚/删除刷新全部经 shim 汇入 reload。 + // 渲染必须走备份的原引擎引用:走 table.reloadData 会被上方 shim 路由回 + // store 造成请求循环。initSort 透传保持表头排序箭头(与引擎 url 模式的 + // listenTableSort 行为一致)。受控表分页条由 render() 内的 + // syncControlledPager 自管:store 的 pager.jump 在内部直呼 fetch,外部 + // 注入不了渲染回调,故 register 时不传 pagerElem 使 store 分页静默跳过, + // laypage 的 jump 经 shim(table.reloadData)回 store.reload 形成闭环。 + var syncControlledPager = function (tableId) { + var state = window.UA_TABLE_STORE.dataProvider.getState(tableId); + if (!state) { + return; + } + layui.laypage.render({ + elem: 'ua-store-pager-' + tableId, + count: state.count, + curr: state.page.curr, + limit: state.page.limit, + limits: state.limits, + layout: ['count', 'prev', 'page', 'next', 'limit', 'skip'], + jump: function (obj, first) { + if (!first) { + table.reloadData(tableId, { + page: {curr: obj.curr, limit: obj.limit} + }); + } + } + }); + }; + + if (window.UA_TABLE_STORE) { + var storeReload = window.UA_TABLE_STORE.reload; + window.UA_TABLE_STORE.reload = function (tableId, opts) { + opts = opts || {}; + var userDone = opts.done; + opts.done = function (res) { + originalTableReloadData.call(table, tableId, { + data: res.data, + totalRow: res.totalRow, + initSort: opts.initSort + }); + syncControlledPager(tableId); + if (typeof userDone === 'function') { + userDone(res); + } + }; + return storeReload(tableId, opts); + }; + } + ua.table = { // 受控/非受控分发入口(后续任务直呼改造的定义点):非受控路径走备份的 // 原引擎引用,不经过上方已包装的 table.reloadData,避免递归 @@ -165,39 +216,52 @@ parseData = options.parseData; } - options.parseData = function (res) { + if (options.controlled === true) { + // 受控灰度模式:数据请求与分页职责移交 UA_TABLE_STORE,引擎只做 + // 纯渲染(空数据起步、关闭引擎分页,由 store 的 laypage 自绘)。 + // 选择态注入(rowDisableCallback / URL selectedIds / LAY_CHECKED + // 跨页回显)由 store.fetch 的 injectSelectionMarks 承接,故不装 + // 引擎 parseData。默认关闭——未显式 controlled:true 的页面保持 + // 引擎 url 模式,行为与历史版本完全一致。 + delete options.url; + delete options.parseData; + options.data = []; + options.page = false; + } else { + options.parseData = function (res) { - // 初始化已经选择的值 - if (selectMode == 'checkbox' || selectMode == 'radio') { - if (typeof options.rowDisableCallback == 'function') { - for (let index = 0; index < res.data.length; index++) { - const dataItem = res.data[index]; + // 初始化已经选择的值 + if (selectMode == 'checkbox' || selectMode == 'radio') { + if (typeof options.rowDisableCallback == 'function') { + for (let index = 0; index < res.data.length; index++) { + const dataItem = res.data[index]; - var rowDisableResult = options.rowDisableCallback(dataItem); - if (rowDisableResult === false || rowDisableResult === true) { - res.data[index].LAY_DISABLED = rowDisableResult; + var rowDisableResult = options.rowDisableCallback(dataItem); + if (rowDisableResult === false || rowDisableResult === true) { + res.data[index].LAY_DISABLED = rowDisableResult; + } + } + } + + var selectedIds = ua.getQueryVariable('selectedIds', ''); + + if (selectedIds.length > 0) { + var selectedIdArr = selectedIds.split(','); + + for (let index = 0; index < res.data.length; index++) { + const dataItem = res.data[index]; + + if (selectedIdArr.indexOf(dataItem.id.toString()) > -1) { + res.data[index].LAY_DISABLED = true; + } } } } - var selectedIds = ua.getQueryVariable('selectedIds', ''); - - if (selectedIds.length > 0) { - var selectedIdArr = selectedIds.split(','); - - for (let index = 0; index < res.data.length; index++) { - const dataItem = res.data[index]; - - if (selectedIdArr.indexOf(dataItem.id.toString()) > -1) { - res.data[index].LAY_DISABLED = true; - } - } - } - } - - res = parseData(res); - return res; - }; + res = parseData(res); + return res; + }; + } // 初始化表格 @@ -221,6 +285,50 @@ // 监听表格选择器 ua.table.listenTableSelectConfirm(options); + // 受控模式接线(在共享监听挂载之后):注册 store、自建分页容器、 + // 同步勾选事件、首屏取数。搜索/排序/switch/编辑等既有监听的 + // table.reloadData 调用经 shim 自动分流到 store.reload(渲染由顶部 + // 接线层注入的 done 承接),此处无需逐点改造。 + if (options.controlled === true) { + // 分页容器挂在引擎视图容器之后(表格容器外),不与引擎分页共存。 + // 注意 layui render 后原 table 元素被移出视图(成为 view 的兄弟 + // 节点),不能用 closest 向上找 view + var pagerId = 'ua-store-pager-' + options.id; + $('#' + pagerId).remove(); + $(options.elem).siblings('.layui-table-view').first().after( + '
' + ); + + window.UA_TABLE_STORE.register(options.id, { + indexUrl: options.init.indexUrl, + where: options.where, + page: {curr: 1, limit: options.limit}, + limits: options.limits, + selectMode: selectMode, + rowDisableCallback: options.rowDisableCallback + // 不传 pagerElem:store 的 pager.jump 内部直呼 fetch 无法 + // 触发引擎渲染,分页条由接线层 syncControlledPager 自管 + }); + + // 引擎勾选事件 → store 选中集合:跨页勾选回显(LAY_CHECKED 注入) + // 的数据源。layui 2.10 事件回调 obj.data 是当次操作的单行对象 + // (type=all 时不含可用行数据),全选场景以 store 的当页数据为准 + //(selection.checkAll 缺省即当页数据,禁用行由其内部跳过) + table.on('checkbox(' + options.layFilter + ')', function (obj) { + if (obj.type === 'all') { + window.UA_TABLE_STORE.selection.checkAll(options.id, undefined, obj.checked); + } else { + window.UA_TABLE_STORE.selection.set(options.id, obj.data); + } + }); + table.on('radio(' + options.layFilter + ')', function (obj) { + window.UA_TABLE_STORE.selection.set(options.id, obj.data); + }); + + // 首屏取数:经接线后的 store.reload 触发 fetch + 引擎纯渲染 + window.UA_TABLE_STORE.reload(options.id); + } + return newTable; }, renderToolbar: function (data, elem, tableId, init) {