我自己第一次被 Spaces 与 Pages 折腾到凌晨,是在一个 S/4HANA 项目的 Fiori Launchpad 2.0 升级测试里。开发系统的采购员工作台明明配置得整整齐齐,等我把同一个请求传到质量系统,用户登录后却连 Space 都看不到。主管问我“页面配置怎么还能传丢?”,我当时只能看着空白的启动台发愣。后来才明白,Fiori Launchpad 里 Spaces 与 Pages 的传输机制和 ABAP 代码传输根本不是一回事,目录、页面、空间、授权角色之间的对象关系只要有一层没理清,传输过去就是给你看一个“干净”的启动台。
这篇内容我会从对象关系讲到项目落地,把里面涉及的技术逻辑、实际操作步骤和我在现场踩过的坑完整拆一遍。适合刚开始负责 Fiori 配置传输的 ABAP 顾问、Fiori/UX 顾问、Basis 运维,以及正在做 Fiori 内容推广但总被“页面不显示”困扰的项目团队。
1. Space 与 Page 不是“新文件夹”,它们是导航装配层
1.1 用户眼中的空间和页面,其实是系统眼中的显示容器
如果你只是以终端用户身份登录过 Fiori Launchpad,你会觉得 Space 就是一个左上角的下拉区域,点进去之后里面有一个或多个 Page,Page 上面放着各种 App 磁贴。看起来像一个稍微高级一点的菜单分组。
但从配置和传输的角度看,Space 和 Page 的本质是一层“导航装配容器”。Space 在最高层定义了一个业务职责领域,比如“采购专员空间”“仓库主管空间”“财务月结空间”。Page 是在这个领域内部进一步切分的显示工作台,比如采购专员空间下可以有“日常采购任务”页面和“采购分析”页面。而页面上真正被用户点击的每一个磁贴,才对应到底层的 Fiori 应用或者一组应用集合。
这层容器不维护任何业务数据,里面装的也不是应用本身,它只维护“谁应该看到什么布局”的菜单关系。所以我一直和团队强调,Space/Page 在做传输时,本质上是在传输“配置关系”,而不是传输“应用功能”。应用功能可能早就通过 ABAP 传输请求过去了,但如果这层装配关系缺失,用户的前端就是空白。
1.2 为什么项目里老有人搞混目录、空间、页面、磁贴
出现混淆的根本原因是旧版 Fiori Launchpad 和 2.0 的术语完全变了。在旧版 Fiori 里大家习惯说的是 Catalog(目录)和 Group(组)。Catalog 管的是应用集合与权限赋值,Group 管的是用户启动页上磁贴的目视排列。新版引入 Spaces 与 Pages 之后,很多人想当然地认为“Space 就是原来的 Group,Page 就是原来的 Catalog”,这个直觉在某种层面上接近,但技术上又不完全一致。
我给同事做培训时会用最简单的话解释:
- Catalog 是后端的“应用抽屉”,存的是应用与权限引用关系。
- Group 是启动页显示的“磁贴抽屉”,控制哪些磁贴按什么顺序显示。
- Space 是用户角度可见的“工作空间”,可以包含多个 Page。
- Page 是 Space 内部的“页面布局”,用来承载一组能完成业务任务的目录或磁贴。
这里的装配层级是:用户分配到 PFCG 角色,角色关联 Space,Space 里挂 Page,Page 里挂 Catalog 或 App。如果这个链条里任何一个关节没有挂上,用户进入 Launchpad 后一定会出现要么找不到空间,要么页面空白的问题。
1.3 和我经历过的经典目录模式比,到底好在哪
传统模式里,你给一个用户分配了多个 Catalog 后,Launchpad 上所有 Catalog 里的磁贴会全部堆在“我的主页”上,用户需要不停地查找和筛选。想要调整布局,只能动 Group。Group 一多,配置非常分散,而且很难按业务职责做清晰的隔离。
Spaces 模式针对这种场景做了很大改进:每个 Space 可以独立配置,包含的 Page 也可以为某个岗位角色量身打造。这样“采购员”进来看到的是采购员工作台,“仓库主管”进来看到的是仓库主管工作台,彼此不干扰。但从项目实施角度来看,这种架构导致配置对象数量暴增,Space/Page/Catalog/应用的引用关系形成了一张很密的网。假如项目团队还用原来“目录传一下就行”的思路去传输,必然会在目标系统里翻车。
所以在深入传输机制之前,必须先接受这个前提:Spaces 与 Pages 是 Fiori Launchpad 2.0 的显示组装层,它本身并不实现业务权限,只是把后端已经授权的应用资源按业务场景重新布局,传输时既要传“布局关系”,又要保证“背后引用的资源在目标系统里已经存在”。理解到这一层,后面所有问题都能顺下来。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 把对象关系拆成“四层引用”,才能知道传输时真正要带什么
2.1 一张关系图讲清 Space/Page 和应用权限的引用链
我习惯用下面这条引用链来梳理 Fiori Launchpad 内容:
PFCG 角色 → Space → Page → 业务目录/Catalog → 目标映射(Target Mapping) → Fiori 应用
每次配置 Fiori 内容时,项目组最常犯的错误是只看中间三层:创建了 Space,挂上 Page,Page 里加了 Catalog,然后就觉得万事大吉。但这条链的所有环节在系统里是独立存在的对象。传输 Space/Page 时,目标映射和业务目录并不一定会跟着你的请求走。
举个例子你就明白了。开发系统里有一个自定义应用 ZMM_PO_APPROVE,它对应的 Target Mapping 叫 ZMM_PO_APPROVE_TM,业务目录叫 ZMM_PURCHASE_CAT。我在开发系统的 FLP 配置界面里新建了一个名为“采购审批”的 Space,里面挂了一个“待办处理”的 Page,Page 引用 ZMM_PURCHASE_CAT。保存时我创建一个传输请求,只把这个 Space/Page 放入其中。传输到质量系统后,页面看起来是配置好了,但质量系统里如果没有 Target Mapping ZMM_PO_APPROVE_TM、没有业务目录 ZMM_PURCHASE_CAT,也没有目标应用本身的 BSP 服务,那用户仍然看不到磁贴,或者点开之后直接报错。
2.2 PFCG 角色在这条链中的真正作用不是分配页面
很多刚接触 Spaces 的同事都会问一个问题:Space 要不要在 PFCG 里分配?答案是要的,但必须理解 PFCG 分配 Space 背后的机制。
PFCG 角色里有一个“Launchpad Spaces”或者说“空间”配置区域,维护的是该角色能访问哪些 Space。用户登录 Fiori Launchpad 后,前端会调用当前用户的角色,读取角色下挂载的 Space 列表,再展示给用户。没有角色分配,Space 即使传到了生产系统,对用户也不可见。
换句话讲,Space 的传输是“内容导入”层面的动作,而角色分配是“权限分配”层面的动作。内容可以跟随传输请求从开发传到测试再传到生产,但角色中 Space 的分配关系通常由安全顾问在目标系统中通过 PFCG 维护。有些企业用传输工具批量传角色,但那属于安全配置传输,和 Fiori Space/Page 的配置传输是两个通道。如果两个通道不同步,也会出现开发系统能看到,生产系统看不到的情况。
2.3 Catalog(目录)在 Space 模式下继续存在的价值
有人问:既然有了 Space/Page,Catalog 是不是可以退休了?我在项目里看到的情况是,Catalog 仍然是必不可少的,因为 Page 不能直接引用一个“应用”,Page 只能引用一个 Catalog 或一个磁贴组。Catalog 在 Page 和底层应用之间提供了很关键的中间层。
Catalog 另一个重要价值是维护权限与可见性。在 PFCG 角色中,你除了要分配 Space,还要分配对应的 Catalog 作为权限。Catalog 里的应用若没有授权给用户,即使磁贴显示出来了,点进去也一定会提示没有权限。所以 Space/Page 在项目管理上其实是把“导航可见性”和“操作权限”两件事分开了:
- Space/Page 决定用户打开 Launchpad 后能不能看到某个入口。
- Catalog 与角色授权决定用户点进去之后能不能真正使用。
传输的时候如果把这两件事混在一起,是一个非常危险的理解偏差。只传 Space/Page,会得到“能看到页面但无法运行应用”的结果;只传 Catalog,会得到“后端有权限但用户前端根本找不到入口”的结果。项目落地的目标是在目标系统里让两者对齐。
2.4 客户端与语言在对象关系里带来的额外维度
和 ABAP 程序传输不同,Fiori Launchpad 配置数据的存储维度多了一个“语言”维度。Space 的名称、Page 的标题这些前端展示文本,在不同的登录语言下可能是不同的。如果你开发系统里配置时用的是中文,传输后目标系统的登录语言是英文,用户可能看到 Space 列表里出现一个名字为空的 Space,或者 Page 标题显示成技术名。
这个问题的本质原因是,页面文本属于语言相关的字段。你在传输请求里打包时,默认带的通常只是当前登录语言对应的文本。如果项目要求中英文同时上线,你需要确保把要发布的语言版本一起维护并包含进请求,或者在传输后在目标系统检查翻译状态。我在项目里就碰到过 Space 列表里出现空白块的现象,结果不是权限问题,而是英文登录用户没有对应英文描述。
3. 传输请求里的 Space/Page 到底传了什么
3.1 配置保存时是怎么“挂”到传输请求上的
Fiori Launchpad 内容管理界面(就是很多顾问习惯叫的 FLP Content Manager)在保存 Space 或 Page 时,系统会弹出一个提示,要求你把更改分配给一个传输请求。如果当前登录的客户端是开发系统,并且配置对象已分配到自定义包,系统会让用户手工输入或选择请求号;如果对象还在临时包,系统会提示先做对象目录条目调整。
这个机制和 SE80 里保存程序时挂传输请求非常类似,本质是标准的 Change and Transport System(CTS,变更与传输系统)。区别在于,这里传输的对象不是源代码、不是数据字典,而是 Fiori 配置表里的记录内容。这些记录内容在系统底层存在 /UI2/ 开头的配置表里,并带上了自定义的 Key。
所以之后 Basis 在传输日志里看到的内容可能不像传程序那样是一个个 R3TR PROG 对象,而是一长串以 FPM、UI2、LPD_CUST 等开头的对象或者配置表条目。一开始不熟悉的人会以为自己传错了,其实这是正常的。
3.2 代码传输与配置传输的核心差异:依赖不跟随
很多传输出问题的根源在于项目团队沿用了 ABAP 传输的思维。ABAP 程序传输时,如果程序引用了一个结构体或者函数组,开发环境会帮你检查依赖,要求你把依赖对象包进同一个请求,否则激活都会报错。Space/Page 的传输不会做这样强制的依赖检查。
你可以顺利保存一个 Page,Page 里引用了一个不存在的 Catalog;系统不会阻止你,只是最终用户端一片空白。你也可以把一个 Space 从一个系统传到另一个系统,但 Space 里引用的 Page 并没有创建;导入过程可能显示成功,但功能完全不可用。这种“弱依赖”是 Fiori 配置传输容易出现问题的最主要技术原因。
所以在项目落地时,我给自己定了一条规矩:传输请求的标题里只能写一句话,但这句话对应的不是一个页面,而是完整的“页面及依赖目录清单”。配置和传输计划中必须单独维护一份依赖清单,逐项核对 Catalog、Target Mapping、应用服务、Space、Page。
3.3 直接改配置与真正“传输”之间的边界
在开发系统里修改一个 Space 名称,这个时候如果保存后选了请求,修改就进入了 CTS。等你释放请求并通过 STMS 导入目标系统后,目标系统里的 Space 名称才会发生变化。
但有几种操作不会经过标准传输:
- 在客户端本地直接执行各类 Function Module 或通过 SM30 修改表数据。
- 通过 Fiori 前台用户设置创建的个性化内容,例如个人把某个磁贴移动到其他分组。这些内容放在用户的个人数据区域,不属于管理员配置。
- 仅在某个前端系统或网关系统里手工维护的设置,但没有进入 ABAP 后端的统一请求。
这给项目带来的启发是,如果现场顾问或运维人员图省事,直接在生产系统里用 SM30 之类的工具改配置,短期内能解决问题,但开发系统下一次正常传输过来时,会把生产系统的修改直接覆盖掉。这种问题在项目维护期特别常见。正确做法是所有 Space/Page 配置的修改都必须回到开发系统,走完请求再导到生产,否则你维护的是一套谁也说不清最终状态的生产配置。
3.4 传输后目标系统是否还需要额外的激活动作
大多数情况下,Fiori Launchpad 配置数据的导入不需要像 ABAP 程序那样再去 SE80 激活。CTS 导入时会把配置数据直接更新到目标系统的数据库中。但这不意味着导入后马上就能让所有用户看到最新效果,因为 Fiori Launchpad 前端有缓存机制。
这里有三个地儿需要关注:
- Fiori 前端服务器(如果单独部署)对 Launchpad 配置有缓存。
- 浏览器端也有本地存储的Launchpad设置。
- 用户会话开启状态下,某些 Space/Page 列表不会实时刷新。
项目里如果刚导完配置就去测试,经常会发现生产用户端看不到新 Space。这时候先别急着怀疑传输失败,等几分钟让缓存同步,或者让用户重新登录一次,Fiori 配置一般能正常出现。强烈不建议每次传输后都要求所有用户清浏览器缓存,而是把“传输完成 + 缓存窗口 + 用户重新登录”作为标准发布步骤。
4. 从配置环境到生产环境:可以直接照抄的落地流程
4.1 准备阶段:先理清系统角色与目录清单
任何一个 Fiori Space/Page 传输,都不建议直接开始点点点。我建议在开发系统做任何配置之前,先建一张表格,列出如下字段:
业务场景、Space 名称、Page 名称、页面中引用的 Catalog、Catalog 中包含的 Target Mapping、目标应用技术名称、目标应用对应的前端服务、需要授权的 PFCG 角色。
这张表不是给文档归档用的,而是后面真正创建传输请求时用来核对依赖的核验清单。没有这个清单,Fiori 顾问在配置的时候往往只记得“页面能用”,等到了生产环境很难排查缺了什么。
4.2 在开发系统创建 Space/Page 并挂到传输请求
具体操作对于有 Fiori 基础的人并不复杂,我这里把项目里推荐的标准步骤写一下:
- 登录开发系统,进入 Fiori Launchpad 内容管理应用。
- 在 Space 区域创建新的 Space,填入 ID、标题及描述,选择归属的业务范围。
- 创建 Page,在 Page 中通过添加目录或直接添加应用磁贴来组装页面。
- 把 Page 分配到目标 Space 下,注意检查 Space 是按“页面集合”还是“固定页面”模式展示。如果选择固定页面模式,必须指定默认页面,否则用户点进 Space 后不知道该显示哪个页面。
- 保存时选择自定义传输请求,而不是保存到当前请求之外。
- 对引用到的 Catalog 做单独检查,确认 Catalog 自身是否也在传输范围内。Catalog 的修改要进入自己的传输请求。
- 通过 SE03/传输组织器检查请求对象列表,确认 Space、Page、相关配置对象都包含在请求中。
这里最容易忽略的是第 6 步。很多初学者总认为在页面里引用了 Catalog,就等于把这个 Catalog 也传了。实际上 Catalog 和被页面引用是两套关系。Catalog 本身如果不存在于目标系统,这个引用在导入时并不会把 Catalog 顺带带过去。
4.3 角色与权限绑定:目标系统里必须补上的动作
传输请求导入到质量系统或生产系统后,Space/Page 才会有内容记录,但用户能不能看到,取决于安全顾问在 PFCG 角色中的分配。如果你的项目还没有把角色作为传输内容一并纳入管理,通常需要在目标系统中做这一步:
- 找到对应的业务角色或复合角色。
- 在角色菜单配置区域打开 Fiori Launchpad 空间页。
- 添加从开发系统传输过来的 Space 标识。
- 继续检查角色授权中是否包含了页面引用的 Catalog。
- 保存并生成参数文件,再重新分配用户或等待用户权限数据同步。
这里建议反复强调的是:如果页面里引用的 Catalog 之前已经作为授权加入了 PFCG 角色,而 Space/Page 是通过传输加入的,那顺序上先有 Catalog 授权再绑定 Space 会让用户看到的效果最稳定。如果反过来,用户先看到了 Space,点进去每个磁贴都报权限错误,容易引起业务人员对系统上线的信任危机。
4.4 通过测试账号做完整的用户视角验证
很多团队在测试传输结果时,用的是管理员账号。管理员账号的权限和普通业务用户不同,更容易掩盖授权问题,所以我不建议只用管理员测试。
标准验证路径大概是这样的:
- 在质量系统中找一个测试业务用户,该用户的 PFCG 角色已经配置好。
- 让该用户通过 Fiori 入口登录 Launchpad。
- 确认左上角空间切换器里能看到目标 Space,且名称语言正确。
- 进入 Space,检查默认 Page 展示正常,Page 内磁贴数量和顺序与开发系统一致。
- 随机点开一个有业务数据的应用,确认能正常加载,不会因为 Target Mapping 缺失或服务没有激活而报错。
- 如果多个岗位角色需要不同的 Space,同样用对应的账号做一遍。
这套冒烟测试应该在质量系统做完并截图归档,再安排生产系统导入。否则一旦问题到了生产环境,排查窗口会非常短,业务等待时间长,项目组压力也大。
4.5 发布与缓存策略
生产系统导入前,建议和 Basis、前端运维团队确认缓存刷新策略。如果 SAP 提供了 Fiori 缓存刷新工具,可以按运维窗口执行,避免每个用户在第一次访问时都因为老旧缓存而看到空的 Space 列表。如果项目没有强制刷新机制,则在发布计划里写明“用户需要重新登录或清理 Launchpad 本地缓存”,这个信息同时要让服务台知晓,以免用户报障时一线人员不知道怎么回答。
我经历过最稳妥的做法是:把 Fiori 内容配置的导入窗口安排在非高频使用时段(例如晚上),导入后立即执行一次相关缓存清理,第二天早上由测试账号先登录确认,再通知业务关键用户使用。这样既降低了对业务的影响,也给了项目组一个自然可靠的验证周期。
5. 上线后最常出现的几个“传了却不显示”的问题
5.1 Space 完全没出现在用户空间列表里
场景:传输日志显示成功,质量系统里用管理员也能在配置界面看到 Space,但某个测试用户登录后看不到。
排查思路从两个方向走:一是该用户的 PFCG 角色里是否已经绑定了 Space;二是用户权限数据是否已经生成最新版本。在项目里,第二种情况往往发生在角色调整之后没有执行用户缓冲同步;第一种情况则属于安全顾问漏配。
还有一种不太常见的原因:前端调用的缓存服务还没有更新。如果角色配置无误,通常让该用户退出重新登录或者清一下本机的旧缓存就会好。
不要一上来就怀疑传输丢了,先看角色,再看权限生成,最后再看缓存。这三个原因把目标概率覆盖掉八成以上。
5.2 Page 能打开但里面磁贴是空的
场景:Space 正常显示,点进去 Page 也在,但 Page 上一片空白,或者只显示几个标题。
优先检查 Page 里引用的 Catalog 是否在目标系统存在,以及该 Catalog 里面是否挂载了可用的磁贴和 Target Mapping。一个很常见的现场情况是开发环境里的 Catalog 属于本地定制,没有和 Space/Page 一起放到传输请求中,其他系统里根本不存在这个 Catalog ID。
其次检查当前测试用户是否对该 Catalog 有授权。Page 上的磁贴是否显示与 Catalog 的授权有关,没有授权的情况下系统不会渲染出对应磁贴。别在这里走弯路去查什么前端代码,多半原因在权限或目录引用上。
5.3 磁贴能显示,点击应用后却报“目标没有定义”或 403
“目标没有定义”这类错误,一般和语义对象或者说 Target Mapping 缺失有关。Space/Page 只是告诉前端应该放一个“审批待办”的磁贴在那里,前端要通过内部的语义对象跳转关系找到具体的应用入口。如果这个跳转关系在目标系统不存在,用户点击时就会失去方向。
403 则通常与网关服务、CSRF 令牌或前端服务配置有关。常见场景是 Fiori 前端服务器到后端系统的通信设置不完整,或者某些 OData 服务的 SICF 节点没有激活。这类问题已经不是 Space/Page 本身的范围,而是 Fiori 应用运行环境问题。但项目落地时你很难让用户理解这些区别,所以在排查时要有全链路意识,从页面显示问题逐步追溯到后端服务的激活状态。
5.4 名称变成技术名或变成了空字符串
这个问题我前面提到过,基本是语言版本没传过去。目标系统里如果只有中文文本,而用户登录英文或德文界面,显示控件的文本兜底不到,就会以技术名或空白方式出现。
处理方式是在开发系统检查和补全目标语言描述,把语言相关的文本一起包含在请求中重新传输。如果项目已经多语言并行,我建议一上来就把 Space、Page、Catalog 描述用两种以上语言维护好,而不是先只做中文、等上线后再补。等到上线后补语言,等于又要重新走一次传输流程,时间成本翻倍。
5.5 排查时最实用的一张自查清单
每当我接到“为什么生产 Fiori 看不到 XX Space”的工单时,都会按下面这个顺序做检查,效率比在系统里乱点高很多:
- 传输请求是否已经成功导入生产系统?查 STMS 导入日志。
- 目标系统中配置界面能否看到该 Space/Page?
- 用户所属 PFCG 角色是否包含了该 Space?
- 角色的权限参数文件是否已经重新生成并同步到用户主数据?
- Page 引用的 Catalog 是否已在目标系统存在?
- 用户对该 Catalog 是否具备授权?
- 目标应用对应的 ICF 服务和 OData 服务是否激活?
- 前端缓存是否已过期或清理?
- 登录用户的语言环境是否有对应描述文本?
这张清单的顺序基本符合“从配置、到授权、再到运行环境”的逻辑。照着来,通常能在十几分钟内定位问题。如果所有检查项都通过但还是不显示,那就需要收集 Fiori Launchpad 的前端网络日志和后端 application log 做进一步分析,这时候一般不再是配置传输层面的常见问题了。
我在实际项目里还养成了一个习惯:每次做传输发布时,我都会先把要导入的请求号和依赖清单截图保存,然后在导入后用一个测试角色做一遍完整点击,甚至会把最终用户登录的 Space 列表截图和开发系统并排对比。这样真出了问题,基线证据都在手上,排查就不用靠猜。这个习惯帮我避免过好几次“传完了才知道漏目录”的尴尬,也同样建议所有搞 Fiori 项目落地的同事保留。
