先展示最终效果(就是在vue页面中,内嵌了一块ifream页面):

2.进入开放平台后,选择--创建企业自建应用--创建网页应用,然后在主页面记住该应用的appId和appSecret参数,后面要用
3.然后注意一点的是,因为后面的授权等逻辑我们一般用我们自己的文档做测试,但是自己的文档也属于企业,所以需要将平台应用正式上线,这个需要企业管理员审核,提前说明一下,还需要开通部分接口和数据权限,也是需要审核的.建议最好弄个管理员账号过来开一下
4.在开放平台--开发者后台这里,点击左侧菜单栏的[添加应用能力]页签,然后在右侧菜单选择网页组件

然后在弹出框中点击[如何开发]进入到官方文档中

进入文档页面后,切换左侧的菜单到网页组件中,使用这个组件:

5. 使用该组件,最开始的一件事就是要完成一圈授权流程,在这里将会用到的授权的参数记录如下:
- private static final String APP_ID = "";
-
- private static final String APP_SECRET = "";
-
- /** 用appId和appSecret获取tenant_access_token(租户授权,目前用不到,暂时留存) */
- private static final String TENANT_ACCESS_TOKEN_URI = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal";
-
- /** 获取ticket参数的api */
- private static final String JSAPI_TICKET_URI = "https://open.feishu.cn/open-apis/jssdk/ticket/get";
-
- /** 加签sha1的一个随机参数 */
- private static final String NONCE_STR = "abc123def456";
-
- /** 用appId和appSecret获取app_access_token(应用级别的授权(只允许查看,不允许编辑,分享等功能权限)) */
- private static final String APP_ACCESS_TOKEN_URI = "https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal";
-
- /** 用户访问令牌(用户级别授权,和用户权限挂钩,唯有这种授权在用户拥有权限的情况下,可以实现在线编辑文档,目前暂不做) */
- private static final String USER_ACCESS_TOKEN_URI = "https://open.feishu.cn/open-apis/authen/v1/access_token";
-
- /** 用户信息接口路径 */
- private static final String USER_INFO_URI = "https://open.feishu.cn/open-apis/authen/v1/user_info";
-
- private static final String DOCUMENT_URL = "https://xxxxxxx.feishu.cn/docx/xxxxxxxxxxxxxx";
需要注意的两个点是:
(1). 如果你使用app_access_token去进行后续的验证,那么默认无法获得在线文档编辑的操作,只允许操作,只有当使用user_access_token权限认证,才可以根据用户的权限进行后续的编辑等操作
(2). 请注意DOCUMENT_URL这个参数,这个组件貌似目前只能用/docs下的文档进行渲染,而不可以用我们知识库下的wiki组件,也就是说,你打开的文档如果是wiki的,那么需要将他另存到共享空间中,就会自动变成docs.才可以用
6.授权参数明确后,还有一件事,就是需要开通对应权限,开通对应的权限后还需要上架最新的应用
(1):TENANT_ACCESS_TOKEN_URI不需要开通权限
(2):APP_ACCESS_TOKEN_URI: 不需要开通权限
(3):USER_ACCESS_TOKEN_URI:需要权限如下

7.授权相关后台代码(用了Hutool的Http请求封装,自己引入或者改一下):
- package com.ruoyi.biz.controller;
-
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
-
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- import com.alibaba.fastjson.JSONObject;
- import com.ruoyi.biz.vo.FeishuWebComponentAuthVo;
- import com.ruoyi.common.core.controller.BaseController;
- import com.ruoyi.common.core.domain.AjaxResult;
- import cn.hutool.http.HttpRequest;
- import cn.hutool.http.HttpUtil;
- import lombok.extern.slf4j.Slf4j;
-
- /**
- * @author zhaoyuyang
- */
- @RestController
- @RequestMapping("/biz/help")
- @Slf4j
- public class HelpController extends BaseController
- {
- private static final String APP_ID = "";
-
- private static final String APP_SECRET = "";
-
- /** 用appId和appSecret获取tenant_access_token(租户授权,目前用不到,暂时留存) */
- private static final String TENANT_ACCESS_TOKEN_URI = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal";
-
- /** 获取ticket参数的api */
- private static final String JSAPI_TICKET_URI = "https://open.feishu.cn/open-apis/jssdk/ticket/get";
-
- /** 加签sha1的一个随机参数 */
- private static final String NONCE_STR = "abc123def456";
-
- /** 用appId和appSecret获取app_access_token(应用级别的授权(只允许查看,不允许编辑,分享等功能权限)) */
- private static final String APP_ACCESS_TOKEN_URI = "https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal";
-
- /** 用户访问令牌(用户级别授权,和用户权限挂钩,唯有这种授权在用户拥有权限的情况下,可以实现在线编辑文档,目前暂不做) */
- private static final String USER_ACCESS_TOKEN_URI = "https://open.feishu.cn/open-apis/authen/v1/access_token";
-
- /** 用户信息接口路径 */
- private static final String USER_INFO_URI = "https://open.feishu.cn/open-apis/authen/v1/user_info";
-
- private static final String DOCUMENT_URL = "替换你自己的文档全路径";
-
- /**
- * 获取签名数据
- */
- @GetMapping("/getSignData")
- public AjaxResult getSignData()
- {
- // 1. 通过app_id和app_secret获取app_access_token
- Map
paramMap = new HashMap<>(); - paramMap.put("app_id", HelpController.APP_ID);
- paramMap.put("app_secret", HelpController.APP_SECRET);
- String returnStr = HttpUtil.post(HelpController.APP_ACCESS_TOKEN_URI,
- paramMap);
- JSONObject jsonObject = JSONObject.parseObject(returnStr);
- String appAccessToken = jsonObject.getString("app_access_token");
- // 2.通过tenantAccessToken获取ticket
- String ticketResponseStr = HttpRequest
- .post(HelpController.JSAPI_TICKET_URI)
- .header("Authorization", "Bearer " + appAccessToken).execute()
- .body();
- String ticket = JSONObject.parseObject(ticketResponseStr)
- .getJSONObject("data").getString("ticket");
- // 3.按照要求拼接Signature,然后使用sha1进行加密
- StringBuilder signatureBuilder = new StringBuilder();
- Long timeStamp = System.currentTimeMillis();
- signatureBuilder.append("jsapi_ticket=").append(ticket)
- .append("&noncestr=").append(HelpController.NONCE_STR)
- .append("×tamp=").append(timeStamp).append("&url=")
- .append(HelpController.DOCUMENT_URL);
- String signature = cn.hutool.crypto.SecureUtil
- .sha1(signatureBuilder.toString());
- // 4.返回数据,组装数据
- FeishuWebComponentAuthVo returnVo = new FeishuWebComponentAuthVo();
- List
list = new ArrayList<>(); - list.add("DocsComponent");
- // 如果为app_access_token模式进行授权,则不输入openId参数
- returnVo.setOpenId("").setSignature(signature)
- .setAppId(HelpController.APP_ID)
- .setTimestamp(timeStamp.toString())
- .setNonceStr(HelpController.NONCE_STR)
- .setUrl(HelpController.DOCUMENT_URL).setJsApiList(list)
- .setLocale("zh-CN");
- return AjaxResult.success(returnVo);
- }
- }
8.前端代码:
- <template>
- <div class="app-container">
- <div id="feishu-page">div>
- div>
- template>
- <script>
- import { getSignData } from '@/api/biz/help'
- export default {
- data() {
- return {}
- },
- created() {
- this.$modal.loading('正在加载文档')
- },
- mounted() {
- const script = document.createElement('script')
- script.src =
- 'https://lf1-cdn-tos.bytegoofy.com/goofy/locl/lark/external_js_sdk/h5-js-sdk-1.1.3.js'
- script.async = true
- script.onload = () => {
- // 执行一些操作,例如初始化该库或者调用一些方法
- this.authPage()
- }
- document.head.appendChild(script)
- },
- methods: {
- authPage() {
- getSignData().then((response) => {
- let openId = response.data.openId
- let signature = response.data.signature
- let appId = response.data.appId
- let timestamp = response.data.timestamp
- let nonceStr = response.data.nonceStr
- let url = response.data.url
- let jsApiList = response.data.jsApiList
- let locale = response.data.locale
- let that = this
- window.webComponent
- .config({
- openId, // 当前登录用户的open id,要确保与生成 signature 使用的 user_access_token 相对应,使用 app_access_token 时此项不填。注意:仅云文档组件可使用app_access_token
- signature, // 签名
- appId, // 应用 appId
- timestamp, // 时间戳(毫秒)
- nonceStr, // 随机字符串
- url, // 第3步参与加密计算的url,同时也是最终需要访问的url
- jsApiList, // 指定要使用的组件列表,请根据对应组件的开发文档填写。如云文档组件,填写['DocsComponent']
- locale, // 指定组件的国际化语言:en-US-英文、zh-CN-中文、ja-JP-日文
- })
- .then((res) => {
- // 动态渲染,返回组件实例。
- let myComponent = window.webComponent.render(
- 'DocsComponent',
- {
- //组件参数
- src: url,
- minHeight: '500px',
- height: '1100px', //该参数控制了页面的最大展开高度,不允许为Auto,也不能不写,会导致锚点定位,文本搜索失效
- width: '100%',
- },
- document.querySelector('#feishu-page'), // 将组件挂在到哪个元素上
- )
- // 通过setFeatureConfig方法修改组件的配置属性
- myComponent.config.setFeatureConfig({
- //文档头部菜单栏
- HEADER: {
- enable: true, // 隐藏头部
- },
- //点赞
- LIKE: {
- enable: true, // 隐藏点赞
- },
- //图片
- IMAGE: {
- maxWidth: 500, // 图片最大宽度
- },
- //分享
- SHARE: {
- enable: false, // 是否显示分享按钮
- visibleConfig: {
- // 区域的显隐配置
- invite: false, //邀请区域
- shareLink: false, //分享链接区域
- shareMethod: false, //分享方式区域
- },
- },
- //模态窗
- MODAL: {
- innerMask: true, // 有模态窗时, 组件内是否有遮罩
- outerMask: {
- enable: true, // 有模态窗时, 组件外是否有遮罩
- zIndex: 1000, // 遮罩层的z-index
- },
- offset: {
- // 模态窗的偏移量
- x: 0,
- y: 0,
- },
- },
- //文档内容
- CONTENT: {
- readonly: false, // 是否只读
- padding: [0, 0, 0, 0], // 文档内边距,例:[10, 0, 10, 0] 为上下增加 10 px 边距
- maxWidth: 0, //内部最大宽度
- titleVisible: true, //标题是否可见
- unscrollable: false, //云文档组件是都允许滚动
- },
- //评论
- COMMENT: {
- partial: {
- //局部评论
- enable: false, //是否启用局部评论
- open: false, //是否展开局部评论侧栏
- },
- global: {
- //全局评论
- enable: false, //是否启用全局评论
- },
- },
- //侧边栏
- SIDEBAR: {
- borderSide: [false, false, false, false], //侧边栏边框显隐,例:[true, true, false, false] 上、右侧有边框
- },
- //目录
- DIRECTORY: {
- enable: true, //是否显示目录
- pin: true, //是否固定目录
- },
- //文档头部右侧更多菜单
- MORE_MENU: {
- enable: true, //是否显示更多菜单
- items: {
- //菜单子项
- findAndReplaceEnable: true, //是否显示查找替换
- makeCopyEnable: false, //是否显示创建副本
- applyEditPermissionEnable: false, //是否显示申请编辑权限入口
- exportEnable: false, //是否显示导出
- documentInfoEnable: false, //是否显示文档详情
- editHistoryEnable: false, //是否显示编辑历史'
- commentHistoryEnable: false, //是否显示评论历史
- translateEnable: false, //是否显示翻译
- printEnable: false, //是否显示打印
- deleteEnable: false, //是否显示删除
- },
- },
- //右下角全屏按钮
- FULLSCREEN: {
- enable: true, //是否显示按钮
- },
- //文档头部右侧协作者列表
- COLLABORATOR: {
- enable: false, //是否显示协作者列表
- },
- })
- myComponent.event.onMountSuccess(function () {
- that.$modal.closeLoading()
- })
- })
- })
- },
- },
- }
- script>