[Feature] 支持将同一动态路由(不同 params)合并为单个标签页,且该配置需能在 dynamic(后端下发)路由模式下生效

Author: guo0588Created Sep 17, 2026Updated Sep 17, 2026

描述

中后台大量详情类页面使用动态参数路由,例如 src/views/order/details/[id].vue。 用户在列表页依次点开不同记录时,每换一个 id 就会新增一个标签页(/details/5114/details/5115/details/5116 …),标签栏很快被同一页面的 N 个实例占满。

业务期望:这类路由只保留一个标签页,再次打开不同 id 时复用(并刷新)已有标签页,而不是继续新增。

现状与问题

1. meta.multiTab 只能区分 query,区分不了 params

typescript
// src/store/modules/tab/shared.ts
export function getTabIdByRoute(route: App.Global.TabRoute) {
  const { path, query = {}, meta } = route;

  let id = path;

  if (meta.multiTab) {
    const queryKeys = Object.keys(query).sort();
    const qs = queryKeys.map(key => `${key}=${query[key]}`).join('&');

    id = `${path}?${qs}`;
  }

  return id;
}

这里的 path已解析的实际路径/details/5114/details/5115 天然就是两个不同 path,永远不会进入 multiTab 分支。multiTab 实际只对 /a?x=1/a?x=2 这类"同 path 不同 query"有效。

2. 语义上只有"正向"开关,没有"反向"开关

multiTab = true 表示"允许多开"。但当同一路由默认就会被拆成多个标签页时(动态 params 场景),没有任何配置项能把它们合并为一个。

3. dynamic 模式下,meta.multiTab 根本传不进来(关键)

动态路由的 meta 是白名单映射,后端下发的字段只保留这 6 个:

typescript
// src/store/modules/route/index.ts
newRoute.meta = {
  title: routeMeta?.title,
  keepAlive: routeMeta.noCache,
  localIcon: routeMeta.icon && routeMeta.icon !== '#' ? routeMeta.icon : defaultIcon,
  href: routeMeta.href,
  hideInMenu: routeMeta.hidden,
  activeMenu: routeMeta.activeMenu
};

multiTab 不在映射列表内 → 后端下发的 multiTab 被丢弃 → meta.multiTab 恒为 undefined。(另:全仓搜索 multiTab 只有类型声明与读取两处,模板内置路由里没有任何一个实际配置过它。)

建议的解决方案

  1. 提供一种方式,让"同一路由 + 不同 params/query"只保留一个标签页;
  2. 该配置在 dynamic(后端下发)路由模式下同样生效;
  3. 切换参数时,已有标签页内容需要刷新(不能停留在上一个 id 的数据)。

替代方案

No response

额外的上下文

No response