
本文介绍如何通过服务端过滤与客户端跳转参数协同,实现在仪表盘页选中某工单后,自动跳转至工单详情页并高亮显示对应行,同时兼容直接访问详情页时默认选中首行的场景。
本文介绍如何通过服务端过滤与客户端跳转参数协同,实现在仪表盘页选中某工单后,自动跳转至工单详情页并高亮显示对应行,同时兼容直接访问详情页时默认选中首行的场景。
要实现跨页面的 Kendo Grid 行级联动(即:仪表盘页选中某行 → 跳转至工单页 → 工单页 Grid 自动定位并选中相同 TicketID 的行),核心思路是将选中状态从客户端行为转化为服务端数据契约,避免依赖前端 DOM 操作或 URL 片段传递(易失效、不安全、难维护)。以下是经过验证的生产级解决方案:
✅ 推荐方案:服务端过滤 + 视图模型驱动
-
仪表盘页:点击行时携带 TicketID 跳转
在Onchange事件中获取选中项 ID,并重定向至工单页,附带TicketID查询参数:TP.ClientSite.Banking.Banking.Onchange = function (e) { var grid = $("#ClientOpenTicketsDashboard").data("kendoGrid"); var selectedItem = grid.dataItem(grid.select()); if (selectedItem && selectedItem.TicketID) { window.location.href = "/Ticket/Ticket/Details?ticketId=" + selectedItem.TicketID; } }; -
工单页控制器:接收 TicketID 并注入 ViewModel
修改DetailsAction,支持可选的ticketId参数,并将其传入视图模型:public async Task<IActionResult> Details(Guid? ticketId = null) { var vm = new OverviewTicketSystemModel(); if (ticketId.HasValue) { vm.TargetTicketID = ticketId.Value; // 新增属性:用于前端 Grid 过滤 vm.Ticket = await _TicketApiClient.GetTicketByIDAsync(ticketId.Value); } return View(vm); }✅ 注意:
OverviewTicketSystemModel需新增public Guid? TargetTicketID { get; set; }属性。 -
工单页视图:为 Grid 启用服务端过滤
利用 Kendo DataSource 的.Filter()方法,仅请求匹配TargetTicketID的单条记录(而非全量加载再前端筛选):@(Html.Kendo().Grid<TP.Objects.Entities.Generic.Ticket>() .Name("ClientOpenTicketsTicketPage") .Columns(columns => { /* ...保持原有列定义... */ }) .Selectable(x => x.Enabled(true)) .Events(events => events .Change("TP.ClientSite.Banking.Banking.OnchangeForClientOpenTickets") .DataBound("onDataBoundForClientOpenGrid") ) .DataSource(dataSource => dataSource .Custom() .PageSize(1000) .ServerPaging(true) .Transport(transport => transport .Read(read => read .TPApiUrl("/Ticketing/TicketApi/GetClientOpenTicketsPaged") .Data("GetUserID") ) ) .Schema(schema => schema .Data("Data") .Total("Total") .Errors("Errors") .Model(m => m.Id("TicketID")) ) // ? 关键:服务端过滤,确保只返回目标工单 .Filter(filters => filters .Add(t => t.TicketID).IsEqualTo(Model.TargetTicketID ?? Guid.Empty) ) ) .Deferred(true) )⚠️ 注意:
Guid.Empty作为兜底值可避免空值引发异常;若TargetTicketID为空,该过滤条件将匹配所有记录(此时需配合前端逻辑处理默认选中)。 -
优化 DataBound 逻辑:智能选中
更新onDataBoundForClientOpenGrid,仅当有明确目标 ID 时才选中对应行;否则选中首行(满足“直接访问时默认选中第一行”的需求):function onDataBoundForClientOpenGrid(e) { var grid = $("#ClientOpenTicketsTicketPage").data("kendoGrid"); grid.tbody.find(">tr").addClass("custom-row-gap"); var targetId = '@(Model.TargetTicketID?.ToString() ?? "null")'; var selectedRow; if (targetId !== 'null') { // 查找匹配 TicketID 的行(服务端已过滤,通常仅1行) selectedRow = grid.tbody.find(`>tr[data-uid="${grid.dataSource.view()[0]?.uid}"]`); } else { // 直接访问:选中第一行 selectedRow = grid.tbody.find(">tr").first(); } if (selectedRow.length) { grid.select(selectedRow); selectedRow.trigger("click"); // 确保触发 Change 事件 } }
? 关键优势与注意事项
- 性能可靠:服务端过滤大幅减少传输数据量,避免客户端遍历千行数据查找 ID;
- 状态一致:无论从仪表盘跳转还是直接访问,页面初始状态均由服务端决定,无竞态风险;
-
SEO 友好:URL 含语义化参数(
?ticketId=xxx),便于调试与分享; -
兼容性保障:
TargetTicketID为可空类型,未提供时自动回退至全量数据+首行选中; -
安全提示:服务端必须校验
TicketID所属用户权限(如_TicketApiClient.GetTicketByIDAsync内部已做鉴权)。
通过以上设计,您不仅解决了跨页行定位问题,更构建了可扩展、易维护的工单导航体系。

















