ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

SAP Fiori Element实战:从注解开发到部署上线的采购申请App构建指南

SAP Fiori Element实战:从注解开发到部署上线的采购申请App构建指南 1. 项目概述为什么Fiori Element是SAP开发者的效率利器如果你是一名SAP开发者或者正在向这个方向转型那么“如何开发一个Fiori App”这个问题大概率是你职业生涯中绕不开的一个坎。几年前当我们面对一个业务需求时往往需要从零开始设计UI5视图、编写控制器逻辑、绑定OData模型、处理路由和导航……一套流程下来一个简单的列表展示页面可能就要耗费好几天。代码量不小后期维护更是头疼每个开发者都有自己的编码风格项目一复杂团队协作就成了大问题。而SAP Fiori Element的出现几乎就是为了解决这些痛点而生的。它不是一个新的UI控件库而是一种声明式的开发框架。简单来说你不再需要手写大量的视图View和控制器Controller的JavaScript代码而是通过预定义的模板Template和注解Annotation来“描述”你想要的应用长什么样、有什么功能。框架会根据你的描述自动生成标准化的、符合Fiori设计规范的运行时界面。这听起来有点像“低代码”但它比低代码更贴近开发者。你依然需要理解OData服务、理解业务实体和它们之间的关系并通过注解来精确地控制UI行为。它的核心价值在于将开发者从重复的、样板式的UI编码工作中解放出来让他们能更专注于业务逻辑本身。无论是创建一个展示采购申请就像热词里提到的sap mrp生成的采购申请没有行号这种具体问题的列表报表还是构建一个复杂的对象页面Fiori Element都提供了成熟的解决方案。所以这篇内容不是一篇泛泛而谈的概念介绍而是我基于多个实际项目从零开始使用Fiori Element开发一个完整App的实战记录。我会带你走过从环境准备、服务搭建、注解开发到部署上线的全流程并分享那些官方文档里不会写的“踩坑”经验和性能调优技巧。无论你是想快速上手还是希望深入理解其工作机制这里都有你需要的干货。2. 开发环境与工具链搭建工欲善其事必先利其器。Fiori Element开发虽然简化了UI编码但对底层工具链和环境的规范性要求反而更高。一个稳定、高效的开发环境是成功的第一步。2.1 核心工具选型SAP Business Application Studio vs. VS Code目前主流的Fiori开发IDE有两个选择SAP官方的Business Application StudioBAS和社区更偏爱的Visual Studio CodeVS Code配合SAP扩展包。SAP Business Application Studio (BAS)这是一个基于浏览器的云端开发环境由SAP直接提供和维护。它的最大优势是开箱即用和深度集成。优势预装了所有必需的开发工具如Fiori生成器、部署工具、与SAP BTP业务技术平台账号无缝连接、内置的预览和调试功能非常强大。你几乎不需要在本地配置任何东西打开浏览器就能开始编码。对于企业级开发特别是需要与SAP BTP上的服务如SAP S/4HANA Cloud集成的场景BAS是首选。如何开始你需要一个SAP BTP的试用或正式账号在BTP Cockpit中订阅Business Application Studio服务即可创建自己的Dev Space开发空间。选择“SAP Fiori”类型的Dev Space它会预装所有Fiori开发相关的扩展。Visual Studio Code (VS Code)这是一个轻量级、高度可扩展的本地代码编辑器通过安装SAP提供的扩展包来获得Fiori开发能力。优势完全本地化运行速度快不受网络环境影响可以自由搭配其他强大的扩展如GitLens、Thunder Client等对电脑资源占用相对较少。适合喜欢高度自定义环境、或需要在离线/内网环境下开发的开发者。必备扩展你需要从VS Code市场安装“SAP Fiori tools - Extension Pack”。这个扩展包包含了Fiori项目生成器、XML视图和注解的智能感知IntelliSense、OData服务连接器、本地预览服务器等核心功能。我的选择与建议对于新手和希望快速上手的团队我强烈推荐从BAS开始。它能帮你屏蔽掉大量环境配置的麻烦让你直接聚焦于Fiori Element开发本身减少在“配环境”这个环节的挫败感。当你对整套流程非常熟悉后可以根据团队偏好切换到VS Code。我个人在早期探索和演示项目中使用BAS而在大型、长期的本地化项目中使用VS Code。2.2 项目脚手架Fiori Generator的妙用无论是BAS还是VS Code其核心能力都来自于SAP Fiori Generator。这是一个基于Yeoman的命令行工具集它能通过交互式问答帮你快速生成一个结构完整、配置正确的Fiori项目。创建一个Fiori Element应用的基本流程如下在IDE中打开终端。运行命令yo sap/fiori在BAS中可能已集成在UI中。生成器会引导你做出系列选择应用类型这里选择“SAP Fiori elements application”。UI版本选择“SAPUI5 1.108或更高版本”推荐最新稳定版。数据源选择“Connect to an OData Service”。你需要提供OData服务的URL例如连接到你本地的SAP Gateway系统或一个API Hub上的服务。模板类型这是关键一步。Fiori Element提供了几种预定义的页面模板List Report Object Page: 最常用的模板包含一个列表报告页面和一个对象详情页面。适合管理主数据如物料、供应商或业务单据如销售订单、采购申请。Worklist: 简单的列表页面适合快速查看和搜索。Overview Page: 仪表盘式页面用于展示KPI和导航卡片。Analytical List Page: 专注于数据分析的列表带有强大的图表和筛选功能。实体集选择生成器会读取你提供的OData服务的元数据Metadata让你选择用哪个实体集EntitySet作为应用的主数据模型。完成选择后生成器会自动创建项目文件夹包含webapp/目录你的应用代码、ui5.yaml项目配置、package.json依赖管理等核心文件。这个自动生成的过程确保了你的项目结构符合SAP最佳实践避免了手动创建可能带来的配置错误。生成的项目已经是一个可以运行的最小化应用。2.3 本地运行与调试配置项目生成后你需要在本地运行它以验证环境是否正常。安装依赖在项目根目录运行npm install。这会安装所有必要的SAPUI5库和构建工具。启动预览服务器运行npm start。这个命令会启动一个本地Web服务器默认端口8080并自动打开浏览器。理解webapp/目录结构Component.js: 应用的入口组件定义了应用的根视图、模型、路由等。manifest.json:这是Fiori应用的核心配置文件被称为“描述符”Descriptor。它定义了应用的所有元数据使用的数据模型、路由配置、以及最重要的——Fiori Element的注解文件路径。所有对页面模板的定制几乎都通过修改或扩展manifest.json来实现。annotations/目录存放你的注解文件.xml格式。注解是Fiori Element的灵魂我们会在下一章详细讲解。localService/目录通常用于存放本地模拟的OData服务元数据metadata.xml和模拟数据mockdata/*.json。这在开发初期后端服务还未就绪时极其有用。实操心得善用Mock Server。在开发初期后端OData服务可能不稳定或尚未开发完成。务必在manifest.json的sap.app-dataSources部分将uri指向本地模拟服务如/localService/metadata.xml并设置settings中的localUri。这样npm start时会自动启动一个Mock服务器使用你准备的JSON数据来模拟API响应实现前后端并行开发大幅提升效率。3. 核心原理注解驱动的UI生成机制理解了环境我们深入到Fiori Element的核心——注解Annotations。这是它与传统SAPUI5自由式开发最根本的区别。3.1 什么是注解它如何工作你可以把注解理解为一份给SAPUI5运行时的“设计说明书”。这份说明书用XML格式写成遵循OData注解词汇表如UI,Common,Analytics等。它不描述“如何画一个按钮”而是描述“这个页面需要展示哪些字段”、“这个字段应该是什么标签”、“哪些操作应该出现在表格工具栏上”。工作流程简化版应用启动加载manifest.json。manifest.json告诉应用使用哪个页面模板如List Report和哪个注解文件。运行时SAPUI5库中的Fiori Elements框架读取注解文件。框架根据“模板”“注解”的指令动态生成最终的UI控件树、绑定数据模型、并配置所有交互逻辑。用户看到的是一个完整的、可交互的Fiori应用。例如你想在列表页的表格里显示“采购申请号”和“创建日期”两列并在工具栏加一个“创建”按钮。在传统开发中你需要在视图里定义sap.m.Table和sap.m.Column在控制器里写按钮点击事件。在Fiori Element中你只需要在注解文件里写Annotations TargetMyService.PurchaseRequest Annotation TermUI.LineItem Collection Record TypeUI.DataField PropertyValue PropertyValue PathPurchaseReqNo/ /Record Record TypeUI.DataField PropertyValue PropertyValue PathCreationDate/ /Record /Collection /Annotation Annotation TermUI.Identification Collection.../Collection /Annotation /Annotations以及为实体集添加UI.FieldGroup和UI.Facets来定义对象页的布局。框架会为你生成这一切。3.2 关键注解词汇解析对于初学者掌握以下几个核心注解术语至关重要UI.LineItem: 定义列表报告List Report表格中要显示哪些字段及其顺序、类型如带链接跳转。UI.SelectionFields: 定义列表报告顶部的智能筛选器Smart Filter Bar中显示哪些筛选字段。UI.FieldGroup: 定义对象页Object Page上字段如何分组。例如将“基本数据”放在一个组“公司代码数据”放在另一个组。UI.Facets和UI.Chart: 用于在对象页上定义更复杂的区块比如一个图表Facet或一个表格Facet。UI.HeaderInfo: 定义对象页的标题区域显示什么内容如标题、描述性文字。Common.ValueList: 定义字段的值帮助Value Help即F4搜索帮助关联到另一个实体集。Capabilities.*: 控制UI元素的可见性和可用性例如Capabilities.InsertRestrictions可以控制是否允许创建新条目。3.3 注解文件的组织与管理一个应用通常有多个注解文件。常见的组织方式是annotations/目录下创建一个以服务命名的文件如PurchaseOrder.annotations.xml。在manifest.json的sap.app-models-数据源名称-settings-annotations属性中以数组形式引用这些注解文件。随着应用变复杂注解文件会变得很大。好的实践是按功能或页面进行拆分。例如将列表页的LineItem和SelectionFields放在一个文件将对象页的FieldGroup和Facets放在另一个文件然后在manifest.json中按需引用。这提高了代码的可维护性。注意事项注解的加载顺序与合并。如果多个注解文件对同一个目标Target进行了注解它们会进行合并。但如果有冲突例如对同一个属性定义了不同的值后加载的会覆盖先加载的。理解这一点对调试复杂的注解问题很有帮助。务必在manifest.json中明确注解文件的加载顺序。4. 从零构建一个采购申请管理App现在我们结合热词中提到的“采购申请”场景实战构建一个简单的Fiori Element应用。假设我们的OData服务叫PRService其中有一个PurchaseRequests实体集。4.1 定义列表报告页面列表报告是用户进入应用首先看到的页面核心是表格和筛选。生成项目使用Fiori Generator选择“List Report Object Page”模板数据源连接到PRService主实体集选择PurchaseRequests。定制LineItem(表格列)打开生成的注解文件找到目标为PRService.PurchaseRequests的UI.LineItem注解。修改它来定义我们想要的列Annotations TargetPRService.PurchaseRequests Annotation TermUI.LineItem Collection !-- 第一列通常设为带链接的点击可导航到对象页 -- Record TypeUI.DataFieldForAnnotation PropertyValue PropertyTarget AnnotationPathUI.Identification/ /Record !-- 显示采购申请号 -- Record TypeUI.DataField PropertyValue PropertyValue PathPurchaseReqNo/ PropertyValue PropertyLabel String申请号/ /Record !-- 显示物料号 -- Record TypeUI.DataField PropertyValue PropertyValue PathMaterial/MaterialId/ !-- 假设有关联 -- PropertyValue PropertyLabel String物料/ /Record !-- 显示数量 -- Record TypeUI.DataField PropertyValue PropertyValue PathQuantity/ PropertyValue PropertyLabel String数量/ /Record !-- 显示状态可以用TextArrangement让文本和状态图标一起显示 -- Record TypeUI.DataField PropertyValue PropertyValue PathOverallStatus/ PropertyValue PropertyLabel String状态/ /Record /Collection /Annotation /Annotations定制SelectionFields(筛选字段)在同一个Target下添加或修改UI.SelectionFields定义顶部筛选栏。Annotation TermUI.SelectionFields Collection PropertyPathPurchaseReqNo/PropertyPath PropertyPathMaterial/MaterialId/PropertyPath PropertyPathCreatedBy/PropertyPath PropertyPathCreationDate/PropertyPath /Collection /Annotation添加UI.Identification这是为对象页的标题区域做准备也用于列表页第一列的链接显示。Annotation TermUI.Identification Collection Record TypeUI.DataField PropertyValue PropertyValue PathPurchaseReqNo/ /Record Record TypeUI.DataField PropertyValue PropertyValue PathMaterial/MaterialId/ /Record /Collection /Annotation完成以上步骤后运行应用你应该能看到一个包含指定列和筛选器的采购申请列表。4.2 构建对象页详情对象页用于显示一条采购申请的详细信息。定义UI.HeaderInfo这决定了对象页头部大标题显示什么。Annotation TermUI.HeaderInfo Record TypeUI.HeaderInfoType PropertyValue PropertyTypeName String采购申请/ PropertyValue PropertyTypeNamePlural String采购申请/ PropertyValue PropertyTitle PropertyPathPurchaseReqNo/ PropertyValue PropertyDescription PropertyPathMaterial/MaterialText/ !-- 假设有物料描述 -- /Record /Annotation组织字段到UI.FieldGroup这是对象页的核心将字段逻辑分组。Annotation TermUI.FieldGroup Record TypeUI.FieldGroupType PropertyValue PropertyData Collection !-- 第一个字段组基本信息 -- Record TypeUI.DataField PropertyValue PropertyLabel String申请号/ PropertyValue PropertyValue PathPurchaseReqNo/ /Record Record TypeUI.DataField PropertyValue PropertyLabel String物料/ PropertyValue PropertyValue PathMaterial/MaterialId/ /Record Record TypeUI.DataField PropertyValue PropertyLabel String数量/ PropertyValue PropertyValue PathQuantity/ /Record Record TypeUI.DataField PropertyValue PropertyLabel String单位/ PropertyValue PropertyValue PathUnit/ /Record !-- 第二个字段组日期与人员 -- Record TypeUI.DataField PropertyValue PropertyLabel String创建日期/ PropertyValue PropertyValue PathCreationDate/ /Record Record TypeUI.DataField PropertyValue PropertyLabel String创建人/ PropertyValue PropertyValue PathCreatedBy/ /Record /Collection /PropertyValue /Record /Annotation将FieldGroup关联到页面布局通过UI.Facets将字段组放置到页面上。List Report模板的对象页通常有一个“General Information” Facet。Annotation TermUI.Facets Collection Record TypeUI.ReferenceFacet PropertyValue PropertyLabel String常规信息/ PropertyValue PropertyTarget AnnotationPathUI.FieldGroup#你的FieldGroup的Qualifier/ /Record /Collection /Annotation注意你需要为UI.FieldGroup注解定义一个Qualifier属性如#GeneralInfo然后在Target中引用它。现在从列表页点击一条采购申请就能跳转到布局清晰的对象详情页了。4.3 实现创建与编辑功能Fiori Element模板默认集成了创建Create和编辑Edit功能但需要后端OData服务支持相应的POST和PUT/PATCH操作。确保OData服务支持你的PurchaseRequests实体集必须在元数据中声明EntityType的Create、Update和Delete能力。同时服务实现必须处理这些HTTP请求。前端启用在manifest.json中找到对应数据模型的设置。对于创建功能框架会自动在列表报告页的工具栏生成“创建”按钮。编辑功能则在对象页的工具栏上。定制创建对话框默认的创建表单会显示实体类型的所有字段。你可以通过UI.FieldGroup注解带特定的Qualifier如#Create来精确控制创建对话框中字段的顺序、分组和类型。在manifest.json中你需要为PurchaseRequests实体集配置createWith属性指向这个特定的FieldGroup。字段校验与值帮助利用Common.ValueList注解为字段如物料号关联值帮助。利用Validation相关的注解或OData模型本身的约束如Nullable”false”来实现基础校验。踩坑记录编辑后刷新问题。一个常见的问题是在对象页编辑并保存一条数据后页面数据没有自动刷新看到的还是旧值。这是因为框架默认可能不会立即重新读取数据。解决方案通常是在manifest.json中对应视图的settings里配置editFlow为“SaveAndNavigate”或类似选项并确保后端UPDATE操作成功后返回了更新后的完整实体数据。有时也需要在Component.js中监听editFlow的事件手动刷新绑定上下文。5. 高级定制与扩展当标准模板的功能无法满足需求时Fiori Element提供了强大的扩展机制允许你注入自定义的代码片段。5.1 使用扩展点Extension Points扩展点是框架在运行时预留的、允许开发者插入自定义UI控件或逻辑的“插槽”。这是最常用的定制方式。常见扩展点示例ListReport|表格工具栏: 在列表页表格的工具栏上添加自定义按钮。ListReport|表格行项目: 在表格的每一行添加自定义列或操作。ObjectPage|头部: 在对象页标题区域添加自定义内容。ObjectPage|章节: 在对象页的某个Facet节前后添加自定义内容。如何实现在manifest.json的sap.ui5-routing-targets部分找到对应的目标视图如ObjectPage在其options-settings中定义extensionPoints。extensionPoints: { MyCustomHeaderExtension: { className: my.app.extensions.CustomHeaderExtension } }在webapp/下创建对应的扩展类文件例如ext/CustomHeaderExtension.js。这个类必须继承sap/ui/core/mvc/ControllerExtension。在扩展类的onInit或onExit生命周期方法中编写你的自定义逻辑例如创建按钮并添加到指定位置。sap.ui.define([ sap/ui/core/mvc/ControllerExtension ], function (ControllerExtension) { use strict; return ControllerExtension.extend(my.app.extensions.CustomHeaderExtension, { override: { onInit: function() { // 获取扩展点所在的控件 var oView this.base.getView(); var oHeader oView.byId(headerArea); // 假设的ID实际需查阅模板API // 创建自定义按钮 var oButton new sap.m.Button({ text: 我的操作, press: this._onCustomAction.bind(this) }); oHeader.addContent(oButton); } }, _onCustomAction: function() { // 自定义按钮的处理逻辑 sap.m.MessageBox.information(自定义操作被触发); } }); });5.2 自定义列与片段Fragments对于更复杂的定制比如在表格中渲染一个包含进度条和按钮的组合控件你可以使用自定义列。定义自定义列注解在UI.LineItem中使用UI.DataFieldForIntentBasedNavigation或直接定义一个自定义数据类型并在路径中指向一个扩展点。创建XML片段Fragment在webapp/下创建一个.fragment.xml文件定义你想要的复杂控件结构。编写扩展控制器创建一个控制器扩展在onBeforeRendering等钩子函数中将片段实例化并绑定到自定义列对应的单元格上。这种方式提供了极大的灵活性但复杂度也显著增加需要你对SAPUI5控件生命周期和数据绑定有更深的理解。5.3 集成自定义的OData操作有时业务逻辑不仅仅是CRUD增删改查。例如针对采购申请可能有一个“批量审批”或“转采购订单”的自定义OData操作Function Import。在注解中暴露操作使用UI.DataFieldForAction注解将自定义操作显示为表格行项目上的按钮或对象页工具栏上的按钮。Record TypeUI.DataFieldForAction PropertyValue PropertyLabel String批量审批/ PropertyValue PropertyAction StringPRService.batchApprove/ PropertyValue PropertyInvocationGrouping EnumMemberUI.OperationGroupingType/Isolated/ /Record在扩展控制器中处理调用当用户点击这个按钮时框架会触发一个事件。你需要在对应的扩展控制器中监听这个事件例如onListReportActionPressed然后使用OData模型的callFunction方法去调用后端的Function Import并处理返回结果。6. 调试、测试与部署上线开发完成后确保应用稳定可靠是最后的关键步骤。6.1 调试技巧Fiori Element应用的调试有其特殊性因为大部分UI是运行时生成的。浏览器开发者工具这是最基础的。使用Elements面板查看最终生成的DOM结构使用Console查看日志和错误使用Network面板监控OData请求和响应。SAPUI5诊断工具在浏览器地址栏的应用URL后加上?sap-ui-xx-debugtrue可以激活SAPUI5的诊断工具。特别是“控件树”Control Tree视图它能以层级结构展示所有SAPUI5控件对于查找扩展点对应的控件ID或理解页面结构至关重要。注解文件调试确保注解文件语法正确且Target路径指向正确的实体集或属性。一个常见的错误是路径拼写错误。利用IDE的XML验证和智能感知功能可以减少这类问题。Mock数据调试在localService/mockdata/下的JSON文件必须严格遵循OData JSON格式。使用npm start启动Mock服务器后在浏览器中直接访问OData服务的元数据URL如http://localhost:8080/localService/metadata.xml和实体集URL如http://localhost:8080/localService/PurchaseRequests来验证Mock数据是否被正确加载和返回。6.2 测试策略单元测试可选但推荐对于你编写的自定义扩展控制器Controller Extension中的复杂逻辑可以编写QUnit单元测试。集成测试/OPA5测试这是测试Fiori Element应用更有效的方式。OPA5是SAPUI5的集成测试框架可以模拟用户操作点击、输入、导航并验证页面状态。Fiori Element提供了特定的测试API如ListReport和ObjectPage的测试库让你能更方便地定位和操作运行时生成的控件。例如你可以编写测试用例“用户筛选状态为‘待审批’的采购申请列表应只显示对应条目”。端到端E2E测试对于关键业务流程可以使用如Selenium、Cypress等工具进行E2E测试但这通常由专门的测试团队负责。6.3 部署到SAP BTP开发完成并通过测试后就需要将应用部署到生产或测试环境。SAP BTP是首选的托管平台。构建项目运行npm run build命令。这会执行代码压缩、资源优化等操作在dist/目录下生成一个适合部署的版本。准备部署描述符项目根目录下的mta.yaml文件如果使用BAS的Cloud MTA Build Tool或manifest.yml文件如果直接部署到Cloud Foundry环境是部署配置的核心。你需要在此文件中配置应用名称、内存、磁盘配额、以及需要绑到的服务实例如Destination服务、XSUAA身份认证服务。配置Destination在SAP BTP Cockpit中你需要创建一个Destination目的地指向你的后端OData服务如SAP S/4HANA系统。这个Destination包含了服务URL、认证方式如BasicAuth或OAuth2等信息。你的Fiori应用在BTP上运行时会通过这个Destination来调用后端API。执行部署使用MTA在项目根目录运行mbt build生成.mtar归档文件然后使用cf deploy .mtar命令部署。使用CF CLI在项目根目录运行cf push命令将应用直接推送到Cloud Foundry环境。发布到Fiori Launchpad部署成功后应用会有一个独立的URL。如果你希望用户通过企业统一的Fiori Launchpad访问它你需要在BTP的HTML5应用仓库中启用该应用然后在SAP Build Work Zone或传统的Fiori Launchpad设计器中将该应用作为一个Tile磁贴添加到相应的Catalogs目录和Groups组中并分配相应的角色和权限。整个流程从环境搭建到部署上线虽然步骤不少但每一步都有成熟的工具和规范可循。Fiori Element通过其声明式的开发模式极大地提升了标准业务应用开发的效率与一致性。掌握它意味着你能用更少的代码交付更专业、更符合SAP设计语言的现代化应用。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表