十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Fiori Launchpad导航体系详解:Intent、Cross-App与Inner-App全解析

Fiori Launchpad导航体系详解:Intent、Cross-App与Inner-App全解析 前一阵子帮客户排查 Fiori 导航问题用户在销售订单应用里点了一个按钮满心期待跳到联系人主数据页面结果页面纹丝不动后端日志躺着一句No handler found for intent。排查了大半天最后发现是 target mapping 里参数名多了一个空格。那之后我就特别想写一篇把 Fiori Launchpad 导航体系彻底讲透的文章——因为太多人把 Intent-Based Navigation、Cross-App、Inner-App 这三个词挂在嘴边真到了配置时却分不清谁管谁、参数往哪传、路由怎么写。这篇文章就把我这些年做 Fiori 实施和运维时对导航体系的理解一次讲清楚从 Intent-Based Navigation 的语义 URL 到底怎么解析到 Cross-App 跨应用跳转如何做到“应用之间互不知道对方存在”再到 Inner-App 内部路由跟外部导航怎么配合。无论是刚接触 Fiori 的 BTP 开发者还是被客户各种跳转需求折磨的顾问这篇文章都能让你少走弯路。1. Fiori Launchpad 导航体系全景三个层级一次理清Fiori Launchpad 作为 SAP 新一代业务入口它的导航机制跟传统 SAP GUI 完全不同。传统方式是你记住一个事务代码比如 VA03然后直接敲进去系统知道你要干嘛。Fiori 不是这套逻辑它强调的是“我要完成什么业务意图”而不是“我要打开哪个程序”。这个转变听起来简单实际上是把导航的整个设计逻辑倒过来了。1.1 导航在 Fiori 架构里到底分几层先框定一个边界避免后面越聊越乱。很多刚接触 Fiori 的小伙伴会把“导航”当成一个笼统的概念导致排查问题时找不到下手点。在我自己的实践里Fiori 的导航体系实际上是三个层次同时在工作Intent-Based Navigation这是 Fiori 世界里的“通用语言”所有入口tile、链接、外部 URL最终都会转化成一个语义化的 Intent由 Launchpad 负责解释并路由到对应的应用。Cross-App Navigation应用与应用之间的跳转。比如从销售订单列表跳到客户主数据页或者在采购订单里打开供应商详情。它解决的是“跨系统边界”的业务流串联问题。Inner-App Navigation单个 Fiori 应用内部的页面切换。比如列表页到详情页、详情页到编辑页、向导的下一步上一步。这部分通常由 SAPUI5 自身的路由机制负责跟 Launchpad 无关。三个层次各管一段却有一条主线贯穿Intent意图。就算是最内部的页面跳转在 Fiori 的架构哲学里也最好是围绕业务对象和动作来组织这样才能在需要把一个内部页面暴露给外部应用时不至于重新设计。1.2 为什么 SAP 要“绕这么大一圈”设计导航早期我给客户讲 Fiori 导航时经常被问一个问题为什么不能用简单的 URL 跳转把我们原来的 WebGUI 链接包一下这个问题背后其实是对 SAP 设计哲学的不理解。我举一个例子。一家企业做了很多年 SAP积累了几十个自开发 Web 应用既有老的 SAPUI5 应用也有后来基于 CAP 或者 BTP 写的新应用。如果每个应用都互相硬编码 URL 去跳转一旦某个应用部署路径变了所有引用它的地方全部要改这不是维护成本的问题是根本维护不动的问题。Intent-Based Navigation 的妙处在于应用 A 永远不知道应用 B 的 URL它只知道自己要表达“查看这个销售订单”这个语义即SalesOrder-display。至于这个语义最终由哪个应用来处理是 Launchpad 在启动时通过 target mapping 匹配出来的。所以就有了一个非常实用的效果业务意图和物理实现完全解耦。你可以今天用一个旧应用响应这个意图明天换了新应用只要在 Launchpad 后台改一下映射所有入口全部指向新应用A 和用户都无感知。理解了这层设计逻辑后面所有配置和排查就都有了“为什么”的答案。2. Intent-Based NavigationFiori 导航的“通用语言”这一节是整个导航体系的地基。如果你只想读一章那就读这章。我后来带团队做导航方案时几乎所有的规范和文档都是围绕这一层来定的。2.1 核心概念拆解语义对象、动作与参数Intent-Based Navigation 里三个最基础的概念每一个都必须搞透Semantic Object语义对象业务实体的抽象命名比如SalesOrder销售订单、Customer客户、Material物料、PurchaseOrder采购订单。它不是表名不是程序名而是业务人员能理解的对象名。Action动作对语义对象做的操作比如display查看、create创建、edit编辑、approve审批。Parameters参数执行动作所需的关键信息最典型的比如SalesOrderID1000123、CustomerIDC123。这样组合出来的一个完整 Intent 长这样SalesOrder-display?SalesOrderID1000123在 Fiori Launchpad 里这个 Intent 会被编码进 URL。所以你在浏览器地址栏看到 Fiori 应用的链接往往是一长串hash格式的路径比如https://yourhost/sap/bc/ui5_ui5/ui2/ushell/shells/abap/FioriLaunchpad.html?sap-client100#SalesOrder-displaySalesOrderID1000123#后面的部分就是 Intent 的 URL 编码形态。这个设计也带来了一个很实用的能力用户可以把任何一个 Fiori 页面以深链接Deep Link的方式收藏、分享、甚至插入到邮件里别人点开后直接落到同一个业务页面。2.2 语义 URL 在 Launchpad 里是怎么被解析的很多人配置过 target mapping但不知道点下 tile 之后Launchpad 后端到底做了一系列什么样的工作。我用一个顺序把它理出来用户点击 tile 或者输入深链接Launchpad 前端拿到 Intent。前端调用 SAP Gateway 的 Launchpad 服务把 Intent 发给后端。后端根据当前用户、PFCG 角色、Fiori 目录与分组找到 Intent 对应的 target mapping 配置。比对 target mapping 里定义的 semantic object、action以及参数映射规则。解析目标应用的 URL 类型UI5 应用、Web 应用、SAP GUI 事务等生成完整的应用启动 URL。前端在新标签页或当前页加载这个 URL应用启动并从 Intent 里读取入参。这里面最容易踩坑的一步就是第 4 步的“比对”。因为 target mapping 里面的语义对象、动作、参数名跟应用 manifest.json 里配置的 inbound 定义必须完全一致哪怕是大小写不一样都会直接匹配失败。我踩过一次应用端定义的是SalesOrderLaunchpad 里配置成了salesorder结果同一套配置在开发环境怎么点都没问题因为那里 Launchpad 配置也是小写一传到测试环境就全部 404排查到深夜。为了防止这种问题我后来在团队里立了一个规矩所有语义对象和动作的命名在项目启动的第一天就写好一份命名规范表前端开发、Launchpad 配置顾问、业务方评审必须用同一份表任何改动要先更新表再改配置。2.3 入站参数如何传递并驱动应用启动普通情况下应用启动后 Fiori 框架会把整个 Intent 通过 URL 参数传给应用。这里要分为两类应用来看一类是Fiori Elements 应用。这类应用在 manifest.json 里通过sap.ui5.routing配置了路由框架会自动把 Intent 参数映射到路由参数。通常你要做的就是在 manifest.json 的routing里声明路由和参数Fiori Elements 会自动处理大部分情况。另一类是自由 SAPUI5 应用。这类应用需要在Component.js的onIntent回调里手动拿参数sap.ui.define([sap/ui/core/UIComponent], function (UIComponent) { use strict; return UIComponent.extend(myapp.Component, { metadata: { manifest: json }, onIntent: function (oIntent) { var oParams oIntent oIntent.parameters ? oIntent.parameters : {}; if (oParams.SalesOrderID) { this.getModel().setProperty(/currentOrderId, oParams.SalesOrderID); } } }); });这里的onIntent是 SAP Fiori 框架提供的标准入口。需要注意它只有在应用以 Intent 方式被 Launchpad 唤起时才会触发如果你在本地调试直接打开 index.html这个回调往往不会走。还有一个重要细节入站参数的类型。URL 里面统统是字符串但应用内部可能希望拿到数字或者日期。这一点 Fiori Elements 做得比较好它会根据 manifest.json 里 target 配置的参数类型做自动转换。自开发应用就得自己处理比如parseInt或者用Date.parse。我见过一些应用因为没做类型校验参数直接参与计算后出现NaN排查半天才发现是字符串拼数字的问题。3. Cross-App 导航让应用之间“互相串门”Intent-Based Navigation 解决的是“人怎么从入口进入应用”Cross-App Navigation 解决的是“应用之间怎么带着业务上下文互相跳转”。这一层在企业级应用里极其常见因为没有一个业务是孤立存在的——销售订单旁边一定有客户主数据采购订单里一定关联供应商审批流程里往往要跳到多个业务对象去查看上下文。3.1 外部导航与应用间导航的边界刚开始做 Fiori 时我很容易把“从 Launchpad 外部的深链接跳进来”和“从应用 A 跳应用 B”搞混导致配置时不知道该在哪里下手。后来我给自己总结了一个口诀外部导航Deep Link从浏览器地址栏、邮件链接、其他系统直接进 Fiori 应用。这个场景下你要保证 Launchpad 能识别 Intent并且当前用户有权访问目标应用。应用间导航Cross-App Navigation正在运行中的应用 A 通过代码发起跳转带着业务参数进入应用 B。两个场景底层用的都是 Intent-Based Navigation 的能力但配置的责任方不同。深链接更多依赖 Launchpad 的 target mapping 配置而应用间导航需要应用 A 主动声明“我可以发哪个 Intent”同时也需要应用 B 声明“我可以接收哪个 Intent”。在 SAPUI5 中发起应用间导航的标准写法是这样sap.ushell.Container.getService(CrossApplicationNavigation).toExternal({ target: { semanticObject: Customer, action: display }, params: { CustomerID: C10086 } });这段代码看起来简单但它背后有一个很关键的约定应用 A 的代码里不会出现应用 B 的任何 URL 或者应用名。它只是说“我要看一个客户”至于谁能满足这个要求A 不知道也不需要知道。这是解耦思想的直接体现。但要注意这个toExternalAPI 依赖sap.ushell容器环境。如果你的应用在本地调试、没有跑在 Launchpad 容器里sap.ushell.Container.getService是拿不到的。针对这种情况我一般会在代码里做一次环境判断var oCrossAppNav null; try { oCrossAppNav sap.ushell.Container.getService(CrossApplicationNavigation); } catch (e) { // 本地非 FLP 环境直接忽略或走 fallback 逻辑 } if (oCrossAppNav) { oCrossAppNav.toExternal({...}); } else { // 本地调试时可以用 window.location.hash 模拟但只建议开发阶段用 }3.2 为什么应用 A 不需要知道应用 B 的存在有次在一个项目上做评审客户方的架构师问了我一个特别好的问题你们把导航做成这样A 不知道 B那 B 的权限控制、可见性怎么保证这正好说到跨应用导航的一个容易被忽略的点Cross-App Navigation 不只是“跳过去”还包含了对目标应用访问权限的检查。当用户从应用 A 发起意图“查看客户”时Launchpad 会检查这个用户有没有访问“客户显示”这个目标应用配置的权限。如果用户没有 Roles 或者没有分配对应的 Fiori Catalog导航会被拦下来哪怕他在应用 A 里能正常操作。这个权限检查是标准框架行为不需要额外开发。那就带来了第一个价值你不需要在应用 A 里写任何权限控制代码来判断用户能不能看客户主数据这个判断被推到了 Launchpad 层统一处理。后续如果改变了权限策略只调整 PFCG 角色或者 Fiori Catalog 即可应用代码一行不改。第二个价值是应对变更。SAP 世界里的系统替换是常态。以前你把一套自开发的客户查询应用放在那里新的客户主数据应用基于 SAP S/4HANA 2023 最新能力做了重构要切换过去。有了 intent 解耦你只需要在 Launchpad 后台把Customer-display这个 target mapping 从旧应用改成新应用所有调用它的应用全部自动指向新应用。3.3 跨应用导航配置的完整操作流程这部分说人话直接给步骤。假设我们的需求是从“销售订单审批”应用里点击一个按钮跳转到“客户显示”应用并自动带入该订单对应的客户号。第 1 步确认目标应用配置了正确的 inbound 参数。打开目标应用的manifest.json找到sap.ui5节点下的routing配置或者 Fiori Elements 应用的config区域确认它定义了Customer这个语义对象和display动作且支持CustomerID参数。这一步经常被省略很多人直接在 Launchpad 后台配 target mapping配了半天跳不过去最后发现是目标应用压根没有声明可接收的 intent。第 2 步在 Launchpad Designer 或者 Fiori 配置环境中新建一个 target mapping。语义对象填Customer动作填display参数映射里把CustomerID绑定到你想传的业务字段上。如果你是自开发应用这里的参数名一定要和步骤 1 里目标应用 manifest.json 定义的名称一致。第 3 步在源应用中写跳转逻辑。推荐用上面提到的CrossApplicationNavigationservice。如果源应用是 Fiori Elements 开发的你可以在自定义按钮的 press 事件里写这段逻辑。这里有一个实战中的小坑Fiori Elements 的按钮事件里如果直接调用sap.ushell.Container可能在测试环境正常、生产环境偶发报错因为容器实例化有先后。稳妥的做法是在onAfterRendering或者首次点击时才去获取 service并做异常捕获。第 4 步测试。测试时不要只验证“能跳过去”还要验证参数是否准确带入、目标应用是否识别参数、用户是否对目标应用有权限。我见过很多项目只测了跳转而漏了权限测试导致上线当天客户点按钮看到一片空白。下面这个表格可以当作配置核对清单用检查项源应用目标应用Launchpad 配置语义对象命名发起时使用Customerinbound 声明Customertarget mapping 的语义对象填Customer动作命名发起时使用displayinbound 声明displaytarget mapping 的动作填display参数名CustomerID入参定义CustomerID参数映射配置CustomerID权限无需特殊配置用户有目标应用授权目标应用在用户 Fiori Catalog 中可见4. Inner-App 导航应用内部的路由管理跨应用导航解决了应用之间的串联但用户一旦进入应用接下来每天打交道的是应用内部的页面切换。这块如果做得不好体验会很割裂应用间的跳转是业务化的、有语义的应用内却是乱七八糟的 hash 路由甚至有的团队直接把多个页面做成 hidden 的 fragment切换时手动控制显隐——这种方案做简单 demo 还行稍微复杂点就成了一团乱麻。4.1 内部路由和外部导航到底怎么分工我先说结论Inner-App 导航用 SAPUI5 自带的路由机制跟 Intent-Based Navigation 没有直接关系但两者在 URL 上是“前后段”的关系。写一个 SAPUI5 应用时manifest.json 里的sap.ui5.routing配置了路由表。比如经典的三页面结构列表页、详情页、编辑页。你的路由可能是这样routing: { config: { routerClass: sap.m.routing.Router, viewType: XML, controlId: app, controlAggregation: pages, transition: slide }, routes: [ { pattern: SalesOrderList, name: SalesOrderList, target: SalesOrderList }, { pattern: SalesOrderDetail/{SalesOrderID}, name: SalesOrderDetail, target: SalesOrderDetail } ], targets: { SalesOrderList: { viewName: SalesOrderList, viewLevel: 0 }, SalesOrderDetail: { viewName: SalesOrderDetail, viewLevel: 1 } } }当应用在 Launchpad 中启动时整个 URL 的结构类似https://host/.../FioriLaunchpad.html#SalesOrder-displaySalesOrderID1000123前段SalesOrder-display是 IntentLaunchpad 解析后启动应用应用内部再根据自身的 hash 路由去渲染页面。实际操作中SAP Fiori 框架会把 URL 中#后面的 Intent 部分去掉把宿主页面的 hash 交给应用路由。所以你会在应用内部看到类似#/SalesOrderDetail/1000123的 hash这个部分完全由应用路由接管。4.2 SAPUI5 路由的核心机制参数、嵌套与按需加载SAPUI5 路由这套东西初学觉得复杂真正用熟了以后反而会觉得它设计得很顺手。我自己使用频率最高的三个特性路由参数pattern里用大括号包住的就是参数比如SalesOrderDetail/{SalesOrderID}导航时oRouter.navTo(SalesOrderDetail, { SalesOrderID: 1000123 })路由就会自动把参数拼进 hash同时触发目标视图控制器里的onRouteMatched回调。嵌套路由复杂业务页面往往有 tab 结构比如详情页里有两个子 tab一个展示行项目一个展示附件。你可以为每个 tab 单独定义子路由父路由匹配后子路由再匹配自己的 pattern。按需加载路由 target 里如果不设置viewName对应的lazy属性默认是 false应用启动时会把所有视图全部加载大应用首次打开会明显卡顿。我通常在 manifest.json 里显式声明lazy: true让路由匹配到对应页面时才加载视图。这里有一个很容易被忽视的问题路由参数的数据类型。跟 Intent 参数一样hash 里的参数全是字符串但navTo的时候我们可以传 object 或者 number。SAPUI5 路由虽然不会崩溃但如果你在目标页面直接拿参数做数字计算经常会出现“看起来正常但算出来不对”。我的习惯是在onRouteMatched回调里统一做一次类型解析把从路由里拿到的所有参数都走一遍清洗逻辑。4.3 Fiori Elements 应用内部的导航设计逻辑基于 Fiori Elements 开发的应用内部导航大部分不用自己写代码。对象页面Object Page之间的关联、列表页到明细页的跳转只要数据结构里定义了关联Fiori Elements 会根据注释annotations自动生成导航。这也是 SAP 大力推广 Fiori Elements 的原因之一通过元数据驱动UI 层的导航逻辑跟业务模型保持一致。但自开发场景还是逃不出几个硬需求。最典型的是列表页的行项目上自定义一个按钮跳到一个内部的自定义页面带上当前行数据。这种场景不需要走 Cross-App只需要用Router的navTo就行。注意如果你是在 Fiori Elements 的应用里加自定义路由要把它挂在标准的sap.ui.routing.Router上不要另起炉灶再定义一个新 Router否则会导致返回键行为不一致页面堆栈错乱。另外一个实战细节Fiori Elements 应用里如果你不小心把内部路由的 pattern 定义成跟外部 Intent 一样的名称比如外部 intent 是SalesOrder-display内部路由 pattern 也写了SalesOrder-display某些场景下 Launchpad 会误判跳转目标出现“应用内点击后整个页面被刷新并重新启动应用”的诡异现象。避免办法很简单内部路由 pattern 统一加/前缀事实上 SAPUI5 官方也推荐这么做比如/SalesOrder-display这样内部路由和 Intent 就永远不会混在一起。5. 导航配置中的常见问题排查这一部分是我最想写给后来人的因为导航问题跟别的报错不一样它常常不是红屏报错而是“点了没反应”“跳过去是空白页”“参数带过去了但页面没有按参数加载数据”。这类问题很难靠搜报错信息解决得靠排查思路。5.1 Intent 匹配不上日志到底怎么读先说最经典的一条报错No handler found for intent: SalesOrder-display很多新手看到这条第一反应是“目标应用没部署”“Launchpad 配置错了”。其实这条报错信息已经足够明确Launchpad 后端收到了SalesOrder-display这个意图但在当前用户的配置里找不到任何一个 target mapping 能处理它。排查时我一般按这个顺序来打开 Chrome 开发者工具Network 页签里找到那个失败的请求看请求的 URL 里的sap-client和站点 ID 是不是当前系统、当前客户端。有次客户在客户端 100 配好了结果用户登录默认进了客户端 300自然是找不到映射。用 SAP GUI 或者直接查表检查 target mapping 是否存在。主要看 Fiori Catalog 和 Groups 的分配关系。用户看不到目标入口那就直接会话 404。确认用户是否有访问权限。没有对应 Fiori Catalog 的角色Launchpad 连 target 都不会加载。这类问题的通用排查表我给到下面现象可能原因排查动作点击 tile 后空白页目标应用部署失败或 BSP 服务未激活检查目标应用的 ICF 节点是否激活直接 URL 访问报 404target mapping 未配置或用户无权限检查 Fiori Catalog 与角色分配从应用 A 跳 B 没反应B 应用未声明对应 inbound intent检查 B 应用 manifest.json 的 routing/inbound从应用 A 跳 B 报无权限B 应用 index 未分配或 CORS 拦截后端日志配合前端 Network 查看具体报错参数带过去了但页面没数据参数名不一致或大小写不匹配对比源应用跳转代码和目标应用读取参数的变量名5.2 参数传递丢失与类型不匹配这类问题非常隐蔽尤其在跨应用跳转场景。最常见的情况是A 应用传给 B 应用一个CustomerIDB 应用能正常打开但页面就是查不到数据。打开 Network 仔细看请求其实是发出去了但后端返回 0 条记录。我见过太多同事卡在这个困境里其实 90% 的情况就是参数名对不上。A 应用以为参数叫CustomerIDB 应用读取的却是CustomerNumber或者 A 传的是customerId首字母小写B 读的是CustomerID。加上 Fiori 的 target mapping 里如果你没有显式做参数映射Launchpad 会做一层松散的匹配松到某些情况下参数直接就不传了。另一个典型是多值参数。比如一个业务对象可能关联多个物料号A 应用要把一串物料号传给 B 应用最简单的做法是逗号分隔MaterialID1001,2001,3001。但目标应用读取时如果直接用字符串去查询可能匹配不上。稳妥的处理方式是在发送方做 JSON.stringify接收方再用 JSON.parse或者约定好分隔符并在接收方拆分成数组。无论哪种方式建议在代码里做一层防御性校验参数为空时就地提示用户而不是一路带到后端查出个奇怪的结果。5.3 跨应用跳转失效的经典原因与处理建议跳不过去这个现象看着简单背后的原因有时候让人哭笑不得。我自己遇到最多的一类就是配置没问题、代码没问题但目标应用在用户的 Fiori Launchpad 里根本没有分配。比如销售订单审批应用需要跳到供应商详情但用户在这个系统里只有“销售订单-审批者”这个角色并不包含任何跟供应商相关的 Fiori Catalog。那么他的 Launchpad 里连供应商应用的 tile 都看不到更别提让 Launchpad 给他创建跳转会话了——框架直接拦截。处理方式有两种要么给这类用户额外分配供应商主数据的“查看”权限分析清楚业务上是否允许要么在 A 应用里增加一个提示“您没有查看供应商详情的权限请联系系统管理员。”后者虽然多一步开发但用户体验上反而不容易造成“点按钮没反应”的困惑。还有一类经典问题是CORS跨域资源共享。如果你的 B 应用部署在另一个 BTP 子账户或者另一个 ABAP 系统A 应用的前端代码跨域调用 B 应用的资源会被浏览器拦截。这种问题的典型表现是开发环境一切正常部署到测试环境后跨应用跳转的请求发出去了但浏览器 Console 里一堆 CORS 报错。处理方案不复杂在 B 应用所在系统的 ICF 服务或 BTP 目的地Destination里配置 CORS 允许源把 A 应用所在域加进去。6. 设计导航方案时的一些原则与经验技术细节写了很多最后我想说说方案层面的事情。很多项目导航乱不是技术能力不够而是从一开始就没定好规矩。以下几个原则是我的经验总结建议大家在做 Fiori 项目时当成基线要求。6.1 尽早统一语义对象与动作命名规范一个集团级项目里语义对象少则几十个多则上百个如果没有统一命名规范很快会出现同一个业务对象叫法不统一的情况。比如有些团队叫Customer有些叫CustomerMaster还有叫BPBusiness Partner 的缩写的。这些差异在各自应用内部没毛病但一旦要做跨应用跳转目标应用只认Customer-display你从别的应用发一个BP-display过去直接失败。我的建议是项目启动的第一周就拉上业务方、架构师、各应用开发负责人开一次命名对齐会产出一张语义对象与动作清单包括对象名、动作名、参数名、参数类型、适用场景。这张表作为设计文档正式评审之后所有应用开发、导航配置全部以此为准。变更要走评审流程不能开发人员私下加一个动作就完事。这个清单的价值在项目后期会越来越明显。6.2 导航配置尽量集中管理与自动化Fiori Launchpad 的配置分散在各个系统之间大企业可能有开发、测试、预生产、生产四套环境每套环境里都有 target mapping、Catalog、Group。手工在这些环境间同步很容易漏尤其是导航相关配置漏一个映射往往要到集成测试时才能发现。工程化的做法是把导航配置当作代码管理。SAP 提供了不少手段来做配置的传输与版本化管理比如 ABAP 环境里通过 Workbench 请求传输BTP 环境里通过 MTA 部署。就算没有这些基础设施也应该至少维护一份 markdown 或者 Excel 的配置清单每次变更都同步更新并做好版本记录方便回滚和审计。另外强烈推荐在开发环境里沉淀一套自动化的冒烟测试脚本。每次上线前脚本自动遍历核心业务链路的导航场景——从 launchpad 入口跳应用 A、从应用 A 跳应用 B、应用 B 内部翻页到下个页面——任何一环失败都能在发版前暴露。6.3 别忽略移动端与第三方系统的导航入口Fiori 不只是桌面浏览器里的 Launchpad还有 SAP Mobile Start 以及嵌在第三方门户里的 Fiori 组件。移动端的导航有一些特殊约束比如深链接在 iOS 和 Android 的 URL scheme 不一样Intent 参数在移动端网络环境下传输要注意序列化和压缩。第三方系统集成则更普遍。很多企业有自研 OA 或者门户系统不希望用户从 Fiori Launchpad 跳转而是从自己门户里直接链接到 Fiori 的某个业务页面。这种场景下你要对外提供的不只是#SalesOrder-displaySalesOrderID...这样的完整 URL还要考虑单点登录SSO的票据如何在第三方系统里生成。这块经常被忽略到了集成测试阶段才发现跳转链接在外部浏览器里打不开又回头去查 SAML 和票据逻辑。我个人还有一个体会导航测试一定要纳入性能回归范围。导航本身如果不涉及数据加载还好但很多跨应用跳转会触发目标应用初始化、用户首选项加载、后端会话创建这些叠加起来可能让一次导航耗时飙到十几秒。用户对一次点击跳转的等待阈值很低所以我通常在性能测试方案里专门列出几条核心导航链路的耗时指标比如 95 分位不超过 3 秒超了就回头查是后端慢还是前端初始化慢。6.4 最后分享一个排查小技巧如果你实在搞不清楚某个导航问题到底是 Launchpad 配置问题还是应用内部问题教你一个“剥洋葱”的办法先把目标应用的 URL 直接粘到浏览器里用不带 Intent 的方式访问参数手动跟在 URL 后面。如果这个方式能正常打开并加载数据那问题大概率在 Launchpad 的映射解析。如果这个方式也打不开或数据不对那问题就在应用自身对参数的解析和处理上。这个办法能迅速缩小排查范围省掉大量在配置界面和代码之间来回切换的时间。我做了这么多年 Fiori 项目深刻感觉导航体系就像城市的交通系统Intent-Based Navigation 是路网规划Cross-App 是公交线路的换乘枢纽Inner-App 是楼宇内部的电梯楼梯。三套系统分开设计又能无缝衔接整个城市跑起来才顺。希望这篇文章能帮你在自己的项目里把这三层理顺少踩几个我用头发换来的坑。
返回列表