如何将钉钉微应用在浏览器打开

一、功能概述

"浏览器打开"是 XXX 系统的一个功能按钮,点击后会将当前页面从钉钉桌面客户端内 跳转到系统默认浏览器中打开。该功能解决了钉钉内置浏览器在某些场景下的兼容性问题,让用户可以使用完整功能的系统浏览器访问 XXX 系统。


二、核心执行流程

流程图

复制代码
用户点击"浏览器打开"
       │
       ▼
buildUrlWithAuthParams()
  └─ 为当前 URL 附加 corpid 和 token 参数
       │
       ▼
notInDD() 判断环境
       │
   ┌───┴───┐
   │       │
 在钉钉内  不在钉钉内(纯浏览器)
   │       │
   ▼       ▼
钉钉协议 URL  window.open(url)
   │
   ▼
dd.biz.util.openLink()
调用钉钉 JSAPI
   │
┌──┴──┐
成功   失败
│      │
▼      ▼
日志   window.open() 兜底

2.1 构建认证 URL

typescript 复制代码
const currentUrl = buildUrlWithAuthParams(window.location.href);

buildUrlWithAuthParams 函数作用是为 URL 附加认证参数:

typescript 复制代码
export const buildUrlWithAuthParams = (url: string) => {
  const urlObj = new URL(url, window.location.origin);

  // 附加企业ID(corpid)
  if (!urlObj.searchParams.has('corpid') && (window as any).__corpId) {
    urlObj.searchParams.set('corpid', (window as any).__corpId);
  }

  // 附加认证token
  if (!urlObj.searchParams.has('token') && (window as any).__token__) {
    urlObj.searchParams.set('token', (window as any).__token__);
  }

  return urlObj.toString();
}

为什么需要附加参数?

当页面在外部浏览器打开时,原有的钉钉环境注入的 corpidtoken 可能丢失。通过显式附加这些参数到 URL 中,确保外部浏览器打开后能正常通过认证,无需重新登录。

设计要点:

  • 使用 URL API 安全解析和操作 URL
  • 仅在参数不存在时才添加,避免重复拼接
  • corpid 全局变量通过钉钉 JSAPI 注入到 window.__corpId
  • token 全局变量通过钉钉 JSAPI 注入到 window.__token__

2.2 环境判断

typescript 复制代码
if (!notInDD()) {
  // 在钉钉客户端内 → 使用钉钉协议跳转
} else {
  // 在普通浏览器中 → 直接 window.open()
}

notInDD()

typescript 复制代码
export const notInDD = () => dd?.env?.platform === 'notInDingTalk';

判断逻辑:

  • notInDD() 返回 true → 当前在普通浏览器中(不在钉钉客户端内)
  • notInDD() 返回 false → 当前在钉钉桌面客户端

注意区分两个相似函数:

函数 逻辑 区别
notInDD() platform === 'notInDingTalk' 仅检测是否离开钉钉环境
isNotDD() platform === 'notInDingTalk' 域名不含 ddcrm / 系统域名 额外排除"浏览器打开的钉钉CRM"场景

2.3 钉钉协议跳转(核心)

当检测到在钉钉客户端内时,构造钉钉自定义协议 URL 并通过 JSAPI 调用:

typescript 复制代码
const finalUrl = `dingtalk://dingtalkclient/page/link?url=${encodeURIComponent(currentUrl)}&pc_slide=false`

dd.biz.util.openLink({
  url: finalUrl,
  onSuccess: () => {
    console.log('已成功在外部浏览器打开页面');
  },
  onFail: (err: any) => {
    console.error('打开浏览器失败:', err);
    window.open(finalUrl);  // 兜底方案
  },
});
钉钉自定义协议解析

dingtalk://dingtalkclient/page/link 是钉钉桌面客户端的 URL Scheme,用于内部路由:

组成部分 说明
dingtalk:// 钉钉自定义协议头(类似 http://https://
dingtalkclient/page/link 钉钉内页面链接路由路径
url={encodeURIComponent(currentUrl)} 目标网页 URL(需 URL 编码)
pc_slide=false PC 端控制参数,false = 在系统默认浏览器打开;true = 在钉钉窗口内以侧边栏打开

pc_slide 参数详解:

  • pc_slide=false:启动系统默认浏览器(Chrome、Edge 等),在浏览器中打开目标 URL
  • pc_slide=true:在钉钉窗口内部以侧边栏/新 Tab 形式打开目标 URL(不离开钉钉客户端)
dd.biz.util.openLink() JSAPI

这是钉钉官方提供的 JSAPI,用于在钉钉客户端内打开链接:

  • 参数: 接收一个包含 urlonSuccessonFail 的对象
  • 工作原理: 钉钉客户端会识别 URL 中的 dingtalk:// 协议头,触发系统级 URL Scheme 处理,从而打开系统默认浏览器
  • 成功回调: 钉钉确认已触发外部浏览器打开
  • 失败回调: 如果 JSAPI 调用失败(如权限不足、版本不兼容),回退到 window.open() 兜底

三、依赖关系

复制代码
handleOpenInBrowser
  ├── buildUrlWithAuthParams(url)  →  附加 corpid + token
  ├── notInDD()                    →  判断是否离开钉钉环境
  ├── dd.biz.util.openLink()       →  钉钉 JSAPI 打开链接
  ├── encodeURIComponent()         →  URL 编码
  └── window.open()                →  原生浏览器 API(兜底)

全局变量依赖

变量 来源 说明
window.__corpId 钉钉 JSAPI 注入 当前企业 ID
window.__token__ 钉钉 JSAPI 注入 当前用户的认证 token
window.location.href 浏览器标准 API 当前页面完整 URL
dd.env.platform 钉钉 JSAPI SDK 当前运行平台标识
dd.biz.util.openLink 钉钉 JSAPI SDK 打开链接能力

四、异常处理

代码包含多层容错机制:

层级 场景 处理方式
1 不在钉钉内 直接 window.open(),跳过钉钉协议
2 钉钉 JSAPI 调用失败 onFail 回调中 window.open() 兜底
3 dd 对象不存在 使用可选链 dd?.env?.platform 避免崩溃

五、相关函数速查

ddOpenInBrowser()

typescript 复制代码
export const ddOpenInBrowser = () =>
  dd?.env?.platform === 'notInDingTalk' &&
  (location.hostname.includes('ddcrm') ||
    location.hostname.includes('系统域名'));

用于判断用户是否已经在使用浏览器访问钉钉 CRM(而非在钉钉客户端内)。如果是,则"浏览器打开"按钮无需显示。

openNewWindow()

typescript 复制代码
export const openNewWindow = (url, ...arg) => {
  if (!url) return;
  const isNeedAuthParams = ddOpenInBrowser();
  const finalUrl = isNeedAuthParams ? buildUrlWithAuthParams(url) : url;
  window.open(finalUrl, ...arg);
};

通用的"在新窗口打开"方法,在浏览器打开钉钉 CRM 场景下会自动附加认证参数。handleOpenInBrowser 中直接使用了 window.open() 而非此函数,因为 URL 已在前面通过 buildUrlWithAuthParams 构建完毕。

newtab()

通用的"新 Tab 打开"方法,根据环境选择钉钉 JSAPI 或 window.open()

typescript 复制代码
export function newtab(url = '') {
  // ...URL 处理(相对路径转换、添加 ddtab=true 参数)
  if (!notInDD()) {
    dd.biz.util.openLink({ url: finalUrl, ... });
  } else {
    openNewWindow(finalUrl);
  }
}

六、完整时序图

复制代码
用户                   RightTopNavBtns             浏览器/钉钉             系统浏览器
 │                          │                         │                      │
 │  点击"浏览器打开"         │                         │                      │
 │─────────────────────────►│                         │                      │
 │                          │                         │                      │
 │                   buildUrlWithAuthParams()          │                      │
 │                   window.location.href              │                      │
 │                   + corpid + token                  │                      │
 │                          │                         │                      │
 │                   notInDD() 判断                    │                      │
 │                          │                         │                      │
 │         ┌────────────────┤                         │                      │
 │         │ 在钉钉内       │                         │                      │
 │         ▼                │                         │                      │
 │  构造 dingtalk:// 协议URL │                         │                      │
 │  dd.biz.util.openLink()──┼────────────────────────►│                      │
 │                          │                         │ 识别 dingtalk://     │
 │                          │                         │ 协议, 触发系统浏览器    │
 │                          │                         │─────────────────────►│
 │                          │                         │                      │ 打开目标 URL
 │                          │                         │                      │ (带 corpid+token)
 │                          │                         │◄─────────────────────│
 │                          │◄────────────────────────│                      │
 │                          │ onSuccess 回调           │                      │
 │                          │                         │                      │
 │         ┌────────────────┤                         │                      │
 │         │ 不在钉钉内     │                         │                      │
 │         ▼                │                         │                      │
 │  window.open(url) ───────┼─────────────────────────┼──────────────────────►│
 │                          │                         │                      │ 打开目标 URL
 │                          │                         │                      │
 │  页面在外部浏览器中打开    │                         │                      │
 │◄─────────────────────────────────────────────────────────────────────────│
 │                          │                         │                      │

七、注意事项

  1. 钉钉版本兼容性: dingtalk://dingtalkclient/page/link 协议需要钉钉桌面客户端 6.0+ 版本支持
  2. Mac 与 Windows 差异: pc_slide 参数在两个平台上行为一致,均会调用系统默认浏览器
  3. URL 编码: 目标 URL 必须经过 encodeURIComponent() 编码,否则包含特殊字符(如 &#)时会截断参数
  4. 认证参数时效: token 有过期时间,如果用户在外部浏览器中长时间停留后刷新,可能需要重新认证
  5. 安全策略: 部分企业浏览器的安全策略可能拦截 dingtalk:// 协议唤起,此时会触发 onFail 兜底
相关推荐
小雨下雨的雨1 小时前
鸿蒙PC用Electron框架——Canvas蜡笔抖动效果实现技术深度解析
前端·javascript·华为·electron·鸿蒙系统
ZC跨境爬虫1 小时前
跟着 MDN 学CSS day_49:定位实例练习从入门到精通
前端·css·学习
前端小万1 小时前
用AI两小时开发上架的小程序,单日新增用户173
前端·微信小程序
道友可好2 小时前
Spec Kit:GitHub 官方出品,规范即代码
前端·人工智能·后端
木斯佳2 小时前
前端八股文面经大全:磐松私募-27届前端实习一面(2026-05-27)·面经深度解析
前端
薛先生_0992 小时前
声明式导航(route-link)(跳转传参)
前端
郑州光合科技余经理2 小时前
海外版外卖系统:如何快速搭建国际化外卖平台
java·开发语言·前端·人工智能·小程序·系统架构·php
小雨下雨的雨2 小时前
蜡笔小画家鸿蒙PC用Electron框架 - 儿童学画蜡笔画技术实现详解
前端·javascript·华为·electron·前端框架·交互·鸿蒙系统
天蓝色的鱼鱼2 小时前
别只拿 Playwright 写测试,这三个野路子用法才是真香
前端