钉钉二次开发-企业内部系统集成官方OA审批流程(三)

书接上回,本文主要分享 企业内部系统集成钉钉官方OA审批流程的步骤 的第二部分。

前端代码集成钉钉免登JSAPI:

前端通过corpid 获得钉钉临时访问码code,再通过临时访问码code调用此接口返回当前用户的姓名、userid、 钉钉用户id、 系统工号、 钉钉部门id列表、 业务系统访问token 等信息,然后将 token 存储到 localStorage。

前端框架使用 react

操作 localStorage 的基础代码

TypeScript 复制代码
export function getToken(){
    return localStorage.getItem("token") as string
}

export function setToken(token:string){
    localStorage.setItem("token",token)
}

export function removeToken(){
    localStorage.removeItem("token")
}

判断字段是否包含指定的字符串

TypeScript 复制代码
export function containsStr(str:string, target:string): boolean{
    str = str === null ? 'str' : str;
    target = target === null ? 'target' : target;
    if(str.indexOf(target) !== -1){
        // 字段str包含指定的字符串
        return true;
    } else {
        // 字段str不包含指定的字符串
        return false;
    }
}

钉钉免登录插件

TypeScript 复制代码
export class checkLoginPlugin extends Middleware {
  async handler(ctx: MiddlewareContext<{}>, next: () => Promise<any>): Promise<void> {
    // 判断是否获取到了token
    var token = getToken()
    const base_url = import.meta.env.BASE_URL;
    localStorage.setItem("base_url", base_url);
    if (token) {
	  // token有值
      axios({
        method: 'get',
        baseURL: '/sale',
        url: '/api/checkToken?token=' + token,
        headers: {
          'Content-Type': 'application/json',
        },
      }).then((res: AxiosResponse) => {
        if (res.data.code == 200) {
		  // token有效,打开应用
          localStorage.setItem("dingUserId", res.data.dingUserId);
          localStorage.setItem("dingDeptIds", res.data.dingDeptId);
          // 检查当前登录人的角色中是否包含 MANAGER 可以辅助实现数据权限校验
          var role_no = localStorage.getItem("role_no") as string;
          if (containsStr(role_no, "MANAGER")) {
            localStorage.setItem("manager", "true");
          } else {
            localStorage.setItem("manager", "false");
          }
          next()
        } else {               
		  // token无效,钉钉重新获取token,不是钉钉,直接提示未登录
          if (dd.env.platform !== "notInDingTalk") {
			// 钉钉打开应用,重新获取code及token
            const corpid = import.meta.env.CORPID
            dd.ready(() => {
              dd.runtime.permission.requestAuthCode({
                corpId: corpid,
              }).then(
                (result) => {
                  const { code } = result;
                  axios({
                    method: 'get',
                    baseURL: '/sale',
                    url: '/dd/login?code=' + code,
                    headers: {
                      'Content-Type': 'application/json'
                    },
                  }).then((res: AxiosResponse) => {
                    localStorage.setItem("token", res.data.data.token);
                    localStorage.setItem("dingUserId", res.data.data.dingUserId);
                    localStorage.setItem("dingDeptIds", res.data.data.dingDeptIds);
                    localStorage.setItem("user_info", res.data.data.user_info);
                    localStorage.setItem("userno", res.data.data.user_no);
                    localStorage.setItem("user_id", res.data.data.user_id);
                    // 检查当前登录人的角列表是否包含 MANAGER 可以辅助实现数据权限校验
                    var role_no = localStorage.getItem("role_no") as string;
                    if (containsStr(role_no, "MANAGER")) {
                      localStorage.setItem("manager", "true");
                    } else {
                      localStorage.setItem("manager", "false");
                    }
                    token = res.data.data.token;
					// 可以继续访问应用资源
                    next()
                    return res.data.data
                  }).catch(err => {
                    router.navigate("/check")  //登录页
                    return Promise.reject(err)
                  })
                },
              ).catch(err => {
				// 出现异常,跳转到登录页
                router.navigate("/checkLogin")
              });
            });
          } else {
		    // 从钉钉外打开应用,跳转到登录页
            router.navigate("/checkLogin")
          }
        }
      }).catch(err => {
		// 出现异常,跳转到登录页
        router.navigate("/checkLogin")
        return Promise.reject(err)
      })
    } else {
	  // token没有值
      if (dd.env.platform !== "notInDingTalk") {
		// 钉钉打开应用,重新获取钉钉临时code及token
        const corpid = import.meta.env.CORPID
        dd.ready(() => {
          dd.runtime.permission.requestAuthCode({
            corpId: corpid,
          }).then(
            (result) => {
              const { code } = result;
              axios({
                method: 'get',
                baseURL: '/sale',
                url: '/dd/login?code=' + code,
                headers: {
                  'Content-Type': 'application/json'
                },
              }).then((res: AxiosResponse) => {
                localStorage.setItem("usertoken", res.data.data.token);
                localStorage.setItem("dingtalkUserId", res.data.data.dingtalkUserId);
                localStorage.setItem("dingtalkDeptIds", res.data.data.dingtalkDeptIds);
                localStorage.setItem("user_info", res.data.data.user_info);
                localStorage.setItem("userno", res.data.data.user_no);
                localStorage.setItem("user_id", res.data.data.user_id);
                // 检查当前登录人的角色中是否包含 MANAGER 可以辅助实现数据权限校验
                var role_no = localStorage.getItem("role_no") as string;
                if (containsStr(role_no, "MANAGER")) {
                  localStorage.setItem("manager", "true");
                } else {
                  localStorage.setItem("manager", "false");
                }
                token = res.data.data.token;
                next()
                return res.data.data
              }).catch(err => {
				// 出现异常,跳转到登录页
                router.navigate("/checkLogin")
                return Promise.reject(err)
              })
            },
          ).catch(err => {
            // 出现异常,跳转到登录页
			router.navigate("/checkLogin")
          });
        });
      } else {    
		// 从钉钉外打开应用,跳转到登录页
        router.navigate("/checkLogin")
      }
    }

  }

}
相关推荐
better_liang4 小时前
每日Java面试场景题知识点之-消息队列MQ核心场景与实战
java·面试·kafka·消息队列·rabbitmq·rocketmq·mq
小江的记录本4 小时前
【JVM虚拟机】垃圾回收GC:四种引用类型:强引用、软引用、弱引用、虚引用(附《思维导图》+《面试高频考点清单》)
java·jvm·spring boot·后端·python·spring·面试
小马爱打代码4 小时前
Spring源码 第四篇:Spring 5 源码深度拆解:AOP 全流程核心原理
java·后端·spring
better_liang4 小时前
每日Java面试场景题知识点之-SpringBoot启动流程
java·面试·springboot·源码解析·启动流程
RyFit5 小时前
Java + AI 实战:Spring AI 从入门到企业级落地
java·人工智能·spring
ZhengEnCi6 小时前
01-如何监听接口调用情况?
java·spring boot·后端
JAVA面经实录9177 小时前
MyBatis学习体系
java·mybatis
java1234_小锋7 小时前
在 Spring AI 中如何实现函数调用(Function Calling)?请说明其基本原理和应用场景。
java·人工智能·spring
苏渡苇7 小时前
Spring Cloud Alibaba:将 Sentinel 熔断限流规则持久化到 Nacos 配置中心
数据库·spring boot·mysql·spring cloud·nacos·sentinel·持久化
小马爱打代码8 小时前
Spring源码 第九篇:Spring 5 源码深度拆解 - Spring 事件驱动模型
java·后端·spring