# 应用角标功能开发指南
## 功能介绍
### 应用角标
**应用角标** 是应用（小程序/网页应用）的一种信息通知能力，类似“即时消息”的未读消息标识。通过这个能力，应用图标右上角会展示红色的数字角标，以此来提醒用户应用内有需要关注的信息或待处理的任务。
应用角标支持展示的数字范围是 **1~999**，因此：
- 当应用角标的待办数量小于等于 999 时，显示为红色数字
- 当应用角标的待办数量大于 999 时，显示为红点

### 应用角标的展示位置

接入了角标能力的应用被添加到工作台上，具体的角标展示位置因工作台的类型而异，具体见下表。
**注**： 如果应用被配置在客户端主导航上，角标会照常显示。

**工作台类型** | **如果企业使用的是**<br>[定制工作台](https://www.feishu.cn/hc/zh-CN/articles/507240292326) | **如果企业使用的是**[网页嵌入工作台](https://www.feishu.cn/hc/zh-CN/articles/854243992870) | **如果企业使用的是默认工作台**
---|---|---|---
**支持的版本** | **V5.15** | **V5.18** | **无版本要求**
**具体表现** | **展示在应用图标的右上角：**<br>- 当应用被添加至 **常用应用** 小组件：展示角标<br>- 当应用被添加至 **应用列表** 小组件：展示角标（**V5.27版本及以上**）<br>**注**：<br>- 如果应用列表选择了分组，当某个分组下有应用存在角标，分组标签上会展示红点。<br>- 如需要其他小组件展示角标，可自行实现，但自行实现的角标数据不计算进左侧工作台主导航栏。<br>**展示在主导航栏上工作台右上角**<br>工作台图标右上角的角标数字 =“**常用应用**”中所有角标数字之和 +“应用列表”中所有角标数字去重之和，即同一应用的待办信息仅会统计一次<br>![image.png](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/04ddc9b47dd53b914ee64ac8f9beeffe_bqimKJTrgl.png?height=512&lazyload=true&width=1280) | 仅主导航栏上工作台右上角展示角标，角标数字是网页内部应用角标去重之和<br>**注**：网页内部的角标由用户自行实现<br>![](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/d9febc55ca1a07a32eba54c88d966b80_lZfrrV324w.png?height=631&lazyload=true&width=846) | **展示在应用图标的右上角：**<br>- 当应用被添加至 **我的常用**：展示角标<br>- 当应用被添加至 **分组应用**：展示角标<br>- 当应用被添加至 **全部应用**：不展示角标<br>**展示在主导航栏上工作台右上角**<br>工作台图标右上角的角标数字 =“我的常用”中所有角标数字之和 +“分组应用”中所有角标数字去重之和，即同一应用的待办信息仅会统计一次<br>![](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/e718413c6884de9a026f30e7cc1d148d_3GhkeVQ51X.png?height=1066&lazyload=true&width=1872)<br>![](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/4f4e93b54ca5282751b093aceaa61afc_8tdsPFtVJj.png?height=1028&lazyload=true&width=1874)

### 在飞书客户端开启或关闭应用角标
当应用接入应用角标功能后，用户首次进入应用将查看到**开启角标的权限申请弹窗**，用户可决定是否开启角标功能。
后续如需自行操作角标的开关状态，可打开应用，在应用右上角点击 **···** 并进入 **关于** 页面，开启或关闭应用角标。
**注**：在桌面端或移动端任意一端开启/关闭应用角标，该设置会同步更新到所有客户端。

![](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/f57c129fd39f2a6a54b24ac771943de4_W2JU5xYv07.png?height=850&lazyload=true&width=1888) | ![](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/c786ee0bb14ce462a5edc33df83400b5_KtGSgo6N9R.png?height=622&lazyload=true&width=1168)
---|---

## 注意事项
应用角标是一种较强的提醒机制，能够让用户关注到重要的提醒，但如果使用不当也容易造成用户的反感，因此在使用时需要特别注意以下几点：
### 通过友好的方式征询授权
先在应用内告知用户应用角标功能的作用、让用户充分了解功能的价值和必要性，然后再申请授权，这样更有可能获得用户的授权许可。

**Step1：在应用页面中展示开启应用角标功能的提示**

![image.png](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/0164f7f89481cccca2476797e3749a7c_9sv7PeSNO8.png?height=1624&lazyload=true&maxWidth=300&width=750)

**Step2：用户点击开启应用角标功能后，调用接口[tt.authorize](https://open.feishu.cn/document/uYjL24iN/ugzMx4COzEjL4MTM)，向用户请求授权**

![image.png](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/b759613b509e7c81c3479386c16d2baa_QXtCLzVNum.png?height=1624&lazyload=true&maxWidth=300&width=750)

### 提供清晰明了的承接信息
确保用户进入应用后能够快速的在应用的界面内找到与应用角标数字对应的信息，了解数字的含义。
好的 case     | 坏的 case |
| -- | -- |
| 打开应用后，能够清晰的看到与应用角标对应的内容--有 3 个待审批的审批单   | 打开应用后，没有与应用角标数字承接的信息、不知道进行什么操作来消除角标   |
| ![](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/1076990a38414ba679c1d62b61982433_P8QOql6SUg.png?height=1796&lazyload=true&width=1854) | ![](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/c14a9b8a408fbef9f5a265fa769fe824_6E4LQRZQY4.png?height=1788&lazyload=true&width=1858)

### 提供明确的角标消除方式
确保用户进入应用后能够快速的了解如何消除应用角标，并且在用户完成消除应用角标的操作时，能及时更新角标数字。

例如，一个“审批”应用通过应用角标来提醒用户当前待审批的审批单数量，当用户完成审批操作后，应该即时更新应用角标数字。

### 合理使用应用角标
用户的注意力是有限的，在使用应用角标功能前，请评估你通过应用角标功能提醒的信息对用户来说是否是重要、必须关注和处理的信息。不重要的信息会分散用户的注意力，对用户造成打扰，甚至引发用户停用你的应用。

## 使用流程
### 使用前提
-   应用角标功能**自飞书3.42.0版本开始支持**，使用前请确认当前客户端版本高于该版本。
- 应用必须开启小程序或网页功能，才可以使用应用角标功能。因此，需要先按照 [创建企业自建应用](https://open.feishu.cn/document/home/introduction-to-custom-app-development/self-built-application-development-process) 或 [开发和上架应用商店应用](https://open.feishu.cn/document/uMzNwEjLzcDMx4yM3ATM/ugzNwEjL4cDMx4CO3ATM) 的流程创建并发布默认功能为小程序或网页功能的应用，流程如下：
	1. 创建应用
	2. 开启应用的小程序或网页功能
	3. 将默认的应用功能设置为小程序或网页功能
	4. 发布并在企业内启用应用

### 使用应用角标功能
#### 步骤一：应用鉴权
-   小程序：调用小程序接口前需要先进行登录，登录流程详见: [登录小程序](https://open.feishu.cn/document/uYjL24iN/uETO5QjLxkTO04SM5kDN)
- 网页：调用网页应用接口前，需要先完成鉴权，鉴权流程详见: [H5JSSDK - 鉴权接口](https://open.feishu.cn/document/uYjL24iN/uEzM4YjLxMDO24SMzgjN)
#### 步骤二：申请用户授权
-   应用角标是需要用户授权后才可以使用的功能，即当用户开启应用角标功能时，应用才可以在工作台展示角标。因此，应用如需使用角标功能，需要先征询用户的授权。
- 应用授权调用 [tt.authorize](https://open.feishu.cn/document/uYjL24iN/ugzMx4COzEjL4MTM)，用户未设置过权限（首次调用时），会弹窗咨询用户是否授予权限；如果用户设置过权限，会直接返回授权结果，不会展示授权弹窗。
- 调用[tt.authorize](https://open.feishu.cn/document/uYjL24iN/ugzMx4COzEjL4MTM) 时，传入 应用角标功能对应的 scope 为 `scope.appBadge`。

申请用户授权的方式如下：
#### 判断用户当前的授权状态
在应用内调用 [tt.getSetting](https://open.feishu.cn/document/uYjL24iN/uQzMx4CNzEjL0MTM) 获取用户已设置（包括授予和拒绝）的权限，如果返回的权限列表中没有`scope.appBadge`，则说明接下来是 首次申请授权；如果包含 `scope.appBadge`，且对应的值为false，则表示用户拒绝授权，同理为true表示用户同意授权。

#### 首次申请权限
在应用内 调用  [tt.authorize](https://open.feishu.cn/document/uYjL24iN/ugzMx4COzEjL4MTM) 调用接口后，平台会展示授权弹窗征询用户授权（弹窗表现如下图所示），并在用户操作后回调授权状态；

![20231201-201315.jpeg](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/825fe1be8caa093cf51756bdb660da8d_oKbjqgsbTN.jpeg?height=3060&lazyload=true&maxWidth=300&width=1398)

#### 用户拒绝后再次开启该权限（可选）
当首次申请授权弹窗，用户没有点击允许时，可以 通过 [tt.openSetting](https://open.feishu.cn/document/uYjL24iN/uUzMx4SNzEjL1MTM) 接口为用户打开应用设置页面，引导用户在该页面开启应用角标功能，在调用前 可以提前告知用户开启应用角标功能的作用、让用户充分了解功能的价值和必要性；

![image.png](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/ad345325ad043951a0eaf8940bc48fe5_Qf8Jqi7G2A.png?height=1119&lazyload=true&width=1280)

#### 示例代码如下

```javascript 
 // const SCOPE_BADGE = "scope.appBadge";
const that = this;
//第一步：获取用户当前授权状态
tt.getSetting({
  success: (res) => {
    console.log("get setting success setting=", res);
    if (!res || !res.authSetting || !res.authSetting.hasOwnProperty(SCOPE_BADGE)) {
    // 第二步，首次授权，则请求授权
      tt.authorize({
        scope: SCOPE_BADGE,
        success(res) {
          console.log("auth appBadge success res=", res);
          that.setData({
            badgeAuthed: true,
          });
        },
        fail(res) {
          console.error("auth badge fail res=", res);
          that.setData({
            badgeAuthed: false,
          });
        },
      });
      return;
    }
    that.setData({
      badgeAuthed: res.authSetting[SCOPE_BADGE]
    });

if(!res.authSetting[SCOPE_BADGE]) {
      // 第三步，用户拒绝授权后，调用openSetting打开权限列表，引导用户授权；
      tt.openSetting({
          success(res) {
            console.log("open setting success res=", res);
            if (!res || !res.authSetting) {
              return;
            }
            that.setData({
              badgeAuthed: res.authSetting[SCOPE_BADGE],
            });
          },
          fail(res) {
            console.error("open setting fail res=", res);
          },
});
    }
  },
  fail(res) {
    console.error("get setting fail res=", res);
  },
});
``` 

#### 步骤三： 设置应用角标数字
应用可以通过服务端接口和客户端接口设置应用角标数字，方法如下：

**服务端设置**
-   应用可以通过服务端调用设置应用角标接口来更新角标数字，详见服务端接口文档： [更新应用红点](https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/application-v6/app_badge/set)
- **服务端设置是基础，必须具备，不能跳过服务端设置而直接使用客户端设置**
- 服务端设置的基本原理如下图所示：

![image.png](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/0e054c8aa4fb836396d097f97d66816b_4LpAq7V4uY.png?height=701&lazyload=true&width=1001)

**客户端设置（可选）**
-   当用户在当前设备应用内进行了会造成角标发生变化的操作时（例如完成了一个待审批单据），应用可以通过客户端接口来快速设置当前设备的角标数，优化因网络延时带来的更新不及时。
- 客户端设置的基本原理如下图所示：

![image.png](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/fbb6f6b3d39686b5d9f30480d677e7bc_v247PVWqDV.png?height=701&lazyload=true&width=907)

- 客户端设置接口为[tt.updateBadge](https://open.feishu.cn/document/uYjL24iN/uQjMuQjMuQjM/appbadge/updagebadge)，接口调用方式如下：

```javascript 
 tt.request({
  url: URL_BADGE_SERVICE, // 业务服务端的地址
  data,
  dataType: "json",
  method: "POST",
  header: {
    "content-type": "application/json",
  },
  success(res) {
    /**
     * 模拟处理完和badge相关的事务后，如果该事务需要更改当前用户当前设备上的badge，
     * 可以快速先调用updateBadge api来更新当前设备上的badge数，例如：
     * 1.你当前有5条审批单，处理完一条之后，服务端会有推送到各个设备上
     * 2.但是推送到达是有极小概率失败的，并且会有一定的延时
     * 3.因此可以在本设备上调用updateBadge把badge数更新成4
     */
    console.log("update badge success res=", res);
    if (res.statusCode != 200) {
      return;
    }
    if (!res.data || res.data.length == 0) {
      return;
    }
    for (let i = 0; i < res.data.length; i++) {
      const badgeItem = res.data[i];
      if (badgeItem.openId == that.data.openId && 
        badgeItem.platform===CURRENT_TRUELY_PLATFORM && 
        badgeItem.appType===CURRENT_TRUELY_APP_TYPE) {
        that.setData({
          badgeNum: badgeItem.badgeNum,
        });
        // 调用updateBadge 来更新本地的红点数
        tt.updateBadge({
          badgeNum: badgeItem.badgeNum,
          success(res) {
            console.log("api update badge success res=", res);
          },
          fail(res) {
            console.error("api update badge fail res=", res);
          },
        });
      }
    }
  },
  fail(res) {
    console.error(`update badge failed res=`, res);
  },
});
``` 
客户端更新速度快、能够让用户在完成操作后即时看到应用角标的更新。**如果应用同时需要保持不同端的应用角标同步，需要同步调用服务端接口去更新其他端的应用角标数字。** warnning

**使用注意：**
1. 客户端设置的前提是当前设备已有Badge数据，即**至少先通过服务端设置过一次Badge**
2. 客户端设置只能操作当前设备的Badge数据，如果要**更新多端Badge数据，请使用服务端设置**
3. 客户端设置的Badge数据会被服务端设置的数据覆盖，因此**在使用客户端设置时需同步进行服务端设置**
## Q&A
### 调用[tt.updateBadge](https://open.feishu.cn/document/uYjL24iN/uQjMuQjMuQjM/appbadge/updagebadge) 没能成功更新角标
A：客户端设置角标的前提是当前设备已有Badge数据，即至少先通过服务端设置过一次Badge；详细可参考：**设置应用角标数字 -- 客户端设置（可选）**

### 固定在主导航栏的网页应用角标数字不对（7.10+）
A：网页应用桌面端配置为 **在飞书内新标签页打开** 时，不会对该应用在主导航栏上的角标进行更新（工作台内的不受影响）
![image.png](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/0b21567dd50b05540d76b692da263fc5_E2OE1xOM32.png?lazyload=true&width=1686&height=632)

### 网页应用调用接口失败
A: 需要确认在调用接口前是否先进行了鉴权，以及当前的JS-SDK版本是否满足要求；详细可参考：**使用应用角标功能 -- 步骤一：应用鉴权**

### 应用的角标没有在工作台展示
A：应用角标在工作台展示需要同时满足以下3个条件，请确认是否都满足：
1. 用户开启了应用角标的授权（可以通过“应用--关于”页面查看应用角标功能是否处于开启状态）
1. 通过服务端设置过应用角标数字且当前数字不为 0
1. 当前应用被用户添加到了工作台“我的（常用）应用”或“应用分组”内，如下图所示：

![image.png](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/e46b217bbfa97cd13604a506ee9b606b_KsYFPo0Nj5.png?height=666&lazyload=true&width=1280)

### 网页应用 调用[tt.getSetting](https://open.feishu.cn/document/uYjL24iN/uQzMx4CNzEjL0MTM) 获取不到 `scope.appBadge` 数据
-   **问题表现**：**网页应用**在window.h5sdk.ready中**立刻**调用 [tt.getSetting](https://open.feishu.cn/document/uYjL24iN/uQzMx4CNzEjL0MTM)、无法获取到 `scope.appBadge` 的数据，或者立刻调用[tt.authorize](https://open.feishu.cn/document/uYjL24iN/ugzMx4COzEjL4MTM) 申请 `scope.appBadge` 权限时、会弹出授权弹窗，即使此时用户已经授权过Badge权限。如下图所示：立刻调用时没有获取到 `scope.appBadge` 的数据，设置延时1000ms后调用可以获取到 `scope.appBadge` 的数据：

![](//sf3-cn.feishucdn.com/obj/open-platform-opendoc/7e06bdf2b9b6ae7e27faeb7becfb1d78_wyOb8Xar5k.png?height=1284&lazyload=true&maxWidth=400&width=1026)

- **问题原因**：JSSDK ready 和 [tt.getSetting](https://open.feishu.cn/document/uYjL24iN/uQzMx4CNzEjL0MTM) 存在时序问题, getSetting的数据可能还没获取到
- **处理方法**：应用在window.h5sdk.ready后**不要立刻**调用接口，可以设置1000 ms的延时，即在window.h5sdk.ready后间隔1000 ms再调用[tt.getSetting](https://open.feishu.cn/document/uYjL24iN/uQzMx4CNzEjL0MTM)、[tt.authorize](https://open.feishu.cn/document/uYjL24iN/ugzMx4COzEjL4MTM)接口

