在 Teams 中生成仪表板
本分步指南可帮助你创建仪表板选项卡、向仪表板添加新小组件以及实现图形 API。 会看到以下输出:
先决条件
安装 | 使用 |
---|---|
Visual Studio Code | JavaScript、TypeScript 或 SharePoint 框架 (SPFx) 生成环境。 使用版本 1.55 或更高版本。 |
Teams 工具包 或 TeamsFx CLI | Microsoft Visual Studio Code 扩展,用于为应用创建项目基架。 使用 Teams 工具包 v5。 |
Microsoft 365 开发人员计划 | 具有安装应用的相应权限的 Teams 帐户。 |
Node.js | 后端 JavaScript 运行时环境。 有关详细信息,请参阅 项目类型的Node.js 版本兼容性表。 |
Microsoft Teams | Microsoft Teams,在一个位置通过聊天、会议和通话应用与你合作的每个人进行协作。 |
Microsoft Edge(推荐)或 Google Chrome | 包含开发人员工具的浏览器。 |
创建新仪表板
Teams 工具包支持创建仪表板和基架。
若要创建新仪表板,请执行以下操作:
选择 Visual Studio Code 活动栏中的 Teams 工具包图标。
选择“ 创建新应用”。
选择 “Tab” 以创建新的选项卡项目。
选择 “仪表板”。
选择“ TypeScript ”作为编程语言。
选择“ 默认文件夹 ”,将项目根文件夹存储在默认位置。
为应用输入合适的名称,然后选择 Enter。
Teams 选项卡应用在几秒钟内创建。
创建应用后,Teams 工具包会显示以下消息:
选择边栏中的“Teams 工具包”图标。
选择“ 登录到 Microsoft 365”。
选择“登录”。
选择 F5 以在调试模式下运行应用程序。
选择“添加”。
已在 Teams 中成功创建选项卡应用仪表板。
Teams 还支持不同的主题,包括深色和高对比度主题。
在 TeamsFx CLI 中,
如果首选交互模式,请执行
teamsfx new
命令,然后使用键盘执行与 Visual Studio Code 中的相同流程。如果更喜欢非交互模式,请在一个命令中输入所有必需的参数:
teamsfx new--interactive false--capabilities "dashboard-tab"--programming-language "TypeScript"--folder "./"--app-name dashboard-cli-001
浏览应用源代码
创建项目后,可以在 Visual Studio Code 的 资源管理器 中查看项目文件夹和文件。 仪表板的核心实现位于选项卡文件夹中。
Folder | 目录 |
---|---|
.vscode |
用于调试的 Visual Studio Code 文件。 |
appPackage |
Teams 应用程序清单的模板。 |
env |
环境文件。 |
infra |
用于预配 Azure 资源的模板。 |
src |
仪表板 Teams 应用程序的源代码。 |
以下文件提供仪表板选项卡的业务逻辑。可以更新文件以满足业务逻辑要求。 默认实现提供了一个起点来帮助你入门。
文件 | 目录 |
---|---|
src/models/chartModel.ts |
图表小组件的数据模型。 |
src/models/listModel.ts |
列表小组件的数据模型。 |
src/services/chartService.ts |
图表小组件的数据检索实现。 |
src/services/listService.ts |
列表小组件的数据检索实现。 |
src/dashboards/SampleDashboard.tsx |
仪表板布局实现示例。 |
src/styles/ChartWidget.css |
图表小组件样式文件。 |
src/styles/ListWidget.css |
列表小组件样式文件。 |
src/widgets/ChartWidget.tsx |
可显示图表的小组件实现。 |
src/widgets/ListWidget.tsx |
可显示列表的小组件实现。 |
src/App.css |
应用程序路由的样式。 |
src/App.tsx |
应用程序路由。 |
以下文件是与项目相关的文件。 通常,不需要自定义这些文件。
文件 | 目录 |
---|---|
src/index.css |
应用程序入口点的样式。 |
src/index.tsx |
应用程序入口点。 |
src/internal/addNewScopes.ts |
新范围的实现添加。 |
src/internal/context.ts |
TeamsFx 上下文。 |
src/internal/login.ts |
登录的实现。 |
src/internal/singletonContext.ts |
TeamsUserCredential 实例单一实例的实现。 |
向仪表板添加小组件
若要向仪表板添加新小组件,请执行以下步骤:
定义数据模型
在 Visual Studio Code 中,转到 “资源管理器>”src>模型。
创建 sampleModel.ts 文件。
在 sampleModel.ts 文件中添加以下代码:
export interface SampleModel { content: string; }
创建数据检索服务
注意
可以实现服务,以从后端服务或Microsoft图形 API 检索数据。
在 Visual Studio Code 中,转到 “资源管理器”>src>服务。
创建 sampleService.ts 文件。
在 sampleService.ts 文件中添加以下代码:
import { SampleModel } from "../models/sampleModel"; export const getSampleData = (): SampleModel => { return { content: "Hello world!" }; };
创建小组件文件
在 Visual Studio Code 中,转到 “资源管理器>”src>小组件。
创建 SampleWidget.tsx 文件。
在 SampleWidget.tsx 文件中添加以下代码:
import { Button, Text } from "@fluentui/react-components"; import { BaseWidget } from "@microsoft/teamsfx-react"; import { SampleModel } from "../models/sampleModel"; import { getSampleData } from "../services/sampleService"; interface SampleWidgetState { data?: SampleModel; } export class SampleWidget extends BaseWidget<any, SampleWidgetState> { override async getData(): Promise<SampleWidgetState> { return { data: getSampleData() }; } override header(): JSX.Element | undefined { return <Text>Sample Widget</Text>; } override body(): JSX.Element | undefined { return <div>{this.state.data?.content}</div>; } override footer(): JSX.Element | undefined { return <Button>View Details</Button>; } }
将小组件添加到仪表板
若要将小组件添加到仪表板,请执行以下步骤:
在 Visual Studio Code 中,转到 资源管理器>src>仪表板>SampleDashboard.tsx。
通过更新
override layout()
方法将小组件添加到仪表板:override layout(): JSX.Element | undefined { return (<> <ListWidget /> <ChartWidget /> <SampleWidget /> </> ); }
可选:请参阅以下代码以在列中添加小组件:
.one-column { display: grid; gap: 20 px; grid-template-rows: 1fr 1fr; }
override layout(): JSX.Element | undefined { return (<> <ListWidget /> <div className="one-column"> <ChartWidget /> <SampleWidget /> </div> </> ); }
添加用于创建小组件的所有相关详细信息后,保存相应的文件。
可以在仪表板上查看更改的布局和日历小组件。
添加 SSO 和图形 API 调用
你已了解如何创建仪表板选项卡并将新小组件添加到仪表板。 让我们将单一登录 (SSO) 和图形 API 调用添加到仪表板选项卡。
添加 SSO
若要添加 SSO,请执行以下步骤:
1. 创建Microsoft Entra 应用清单。
若要创建Microsoft Entra 应用清单,请执行以下步骤:
在 Visual Studio Code 中,转到 “资源管理器”。
创建 aad.manifest.json 文件。
在 aad.manifest.json 文件中添加以下代码:
{ "id": "${{AAD_APP_OBJECT_ID}}", "appId": "${{AAD_APP_CLIENT_ID}}", "name": "dashboardDemo", "accessTokenAcceptedVersion": 2, "signInAudience": "AzureADMyOrg", "optionalClaims": { "idToken": [], "accessToken": [ { "name": "idtyp", "source": null, "essential": false, "additionalProperties": [] } ], "saml2Token": [] }, "requiredResourceAccess": [ { "resourceAppId": "Microsoft Graph", "resourceAccess": [ { "id": "User.Read", "type": "Scope" } ] } ], "oauth2Permissions": [ { "adminConsentDescription": "Allows Teams to call the app's web APIs as the current user.", "adminConsentDisplayName": "Teams can access app's web APIs", "id": "${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}", "isEnabled": true, "type": "User", "userConsentDescription": "Enable Teams to call this app's web APIs with the same rights that you have", "userConsentDisplayName": "Teams can access app's web APIs and make requests on your behalf", "value": "access_as_user" } ], "preAuthorizedApplications": [ { "appId": "1fec8e78-bce4-4aaf-ab1b-5451cc387264", "permissionIds": ["${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"] }, { "appId": "5e3ce6c0-2b1f-4285-8d4b-75ee78787346", "permissionIds": ["${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"] }, { "appId": "d3590ed6-52b3-4102-aeff-aad2292ab01c", "permissionIds": ["${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"] }, { "appId": "00000002-0000-0ff1-ce00-000000000000", "permissionIds": ["${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"] }, { "appId": "bc59ab01-8403-45c6-8796-ac3ef710b3e3", "permissionIds": ["${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"] }, { "appId": "0ec893e0-5785-4de6-99da-4ed124e5296c", "permissionIds": ["${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"] }, { "appId": "4765445b-32c6-49b0-83e6-1d93765276ca", "permissionIds": ["${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"] }, { "appId": "4345a7b9-9a63-4910-a426-35363201d503", "permissionIds": ["${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"] } ], "identifierUris": ["api://${{TAB_DOMAIN}}/${{AAD_APP_CLIENT_ID}}"], "replyUrlsWithType": [ { "url": "${{TAB_ENDPOINT}}/auth-end.html", "type": "Web" }, { "url": "${{TAB_ENDPOINT}}/auth-end.html?clientId=${{AAD_APP_CLIENT_ID}}", "type": "Spa" }, { "url": "${{TAB_ENDPOINT}}/blank-auth-end.html", "type": "Spa" } ] }
2. 更新 Teams 应用清单。
若要更新 Teams 应用清单,请执行以下步骤:
在 Visual Studio Code 中,转到 “资源管理器”>appPackage>manifest.json。
在 manifest.json 文件中的有效域属性后面添加以下代码:
"webApplicationInfo": { "id": "${{AAD_APP_CLIENT_ID}}", "resource": "api://${{TAB_DOMAIN}}/${{AAD_APP_CLIENT_ID}}" }
3. 更新 Teams 工具包配置文件。
若要更新 teamsapp.yml 和 teamsapp.local.yml 文件中的 Teams 工具包配置代码,请执行以下步骤:
在 下
provision
添加代码。- uses: aadApp/create with: name: "YOUR_AAD_APP_NAME" generateClientSecret: true signInAudience: "AzureADMyOrg" writeToEnvironmentFile: clientId: AAD_APP_CLIENT_ID clientSecret: SECRET_AAD_APP_CLIENT_SECRET objectId: AAD_APP_OBJECT_ID tenantId: AAD_APP_TENANT_ID authority: AAD_APP_OAUTH_AUTHORITY authorityHost: AAD_APP_OAUTH_AUTHORITY_HOST - uses: aadApp/update with: manifestPath: "./aad.manifest.json" outputFilePath: ./build/aad.manifest.${{TEAMSFX_ENV}}.json
在 操作
cli/runNpmCommand
和build app
名称下添加以下代码:env: REACT_APP_CLIENT_ID: ${{AAD_APP_CLIENT_ID}} REACT_APP_START_LOGIN_PAGE_URL: ${{TAB_ENDPOINT}}/auth-start.html
4. 更新源代码。
在公用文件夹中创建 auth-start.html 和 auth-end.html 文件。
将代码添加到 auth-start.html 和 auth-end.html 文件中。
在 auth-start.html中添加以下代码:
<!--The Teams authentication flow process uses this file to assist with retrieval of the access token.--> <!--If you're not familiar with this process, don't alter or remove this file from your project.--> <html> <head> <title>Sign-in Start Page</title> <meta charset="utf-8" /> </head> <body> <script src="https://res.cdn.office.net/teams-js/2.7.1/js/MicrosoftTeams.min.js" integrity="sha384-4Gy2G+qxzDVdrdemcVqKVQvaSK1Ghg3x6xcsaMLPc/pw7KPtiogHGM97LTWF2PWg" crossorigin="anonymous"></script> <script type="text/javascript" src="https://alcdn.msauth.net/browser/2.21.0/js/msal-browser.min.js" integrity="sha384-s/NxjjAgw1QgpDhOlVjTceLl4axrp5nqpUbCPOEQy1PqbFit9On6uw2XmEF1eq0s" crossorigin="anonymous"> </script> <script type="text/javascript"> microsoftTeams.app.initialize().then(() => { microsoftTeams.app.getContext().then(async (context) => { // Generate random state string and store it, so we can verify it in the callback var currentURL = new URL(window.location); var clientId = currentURL.searchParams.get("clientId"); var scope = currentURL.searchParams.get("scope"); var loginHint = currentURL.searchParams.get("loginHint"); const msalConfig = { auth: { clientId: clientId, authority: `https://login.microsoftonline.com/${context.user.tenant.id}`, navigateToLoginRequestUrl: false }, cache: { cacheLocation: "sessionStorage", }, } const msalInstance = new msal.PublicClientApplication(msalConfig); const scopesArray = scope.split(" "); const scopesRequest = { scopes: scopesArray, redirectUri: window.location.origin + `/auth-end.html?clientId=${clientId}`, loginHint: loginHint }; await msalInstance.loginRedirect(scopesRequest); }); }); </script> </body> </html>
你已将 SSO 文件添加到项目,接下来需要调用 Graph API。
添加图形 API 调用
若要添加图形 API,请执行以下步骤:
TeamsFx SDK 实现图形 API 调用。
在 Visual Studio Code 中,转到 “资源管理器>”src>服务>listService.ts。
更新 listService.ts中的以下代码:
/** * Retrieve sample data * @returns data for list widget */ import {TeamsUserCredentialContext} from "../internal/singletonContext"; import { createMicrosoftGraphClientWithCredential, TeamsUserCredential, } from "@microsoft/teamsfx"; import { ListModel } from "../models/listModel"; import { loginAction } from "../internal/login"; export const getListData = async (): Promise<ListModel[]> => { await loginAction(["User.Read"]); let credential = TeamsUserCredentialContext.getInstance().getCredential(); const graphClient = createMicrosoftGraphClientWithCredential(credential, ["User.Read", ]); const me = await graphClient.api("/me").get(); return [ { id: me.id, title: me.displayName, content: me.mail, }, ]; // { // id: "id1", // title: "Sample title", // content: "Sample description", // }, // { // id: "id2", // title: "Sample title", // content: "Sample description", // }, // { // id: "id3", // title: "Sample title", // content: "Sample description", // }, }
转到 EXPLORER>src>小组件>ListWidget.tsx。
更新 以
export default class ListWidget()
添加用户配置文件小组件。export default class ListWidget extends BaseWidget<any, IListWidgetState> { async getData(): Promise<IListWidgetState> { return { data: await getListData() };
SSO 和 Graph API 在列表小组件中显示已登录的用户配置文件。
完成挑战
你想出了这样的东西吗?
祝贺你!
你已完成本教程!
你有关于此部分的问题? 如果有,请向我们提供反馈,以便我们对此部分作出改进。