提交 65c7e701 作者: 毛细亚

修改钉钉扫码

上级 72b75eb3
......@@ -49,3 +49,5 @@
- 懒加载实现
## UI 规范
因为当前页面是在企微的侧边栏中打开的 所以需要适配企微的侧边栏样式 企微侧边栏 最大的宽度是 320px 所有页面需要适配320px的宽度,必须要使用自适应的方法 来开发页面 不能写死超过 320px 的宽度 宽度的样式一切都是可伸缩的
\ No newline at end of file
......@@ -2,7 +2,6 @@
<div id="app">
<!-- <h1>客服id:{{userInfo.userid}}</h1>
<h1>客户id:{{userInfo.externalUserId}}</h1> -->
<DdLogin/>
<router-view />
</div>
</template>
......
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
import Cookies from 'js-cookie'
Vue.use(VueRouter)
const routes = [
{
path: '/login',
name: 'login',
component: () => import('../views/login.vue')
},
{
path: '/',
name: 'home',
component: HomeView
......@@ -24,4 +30,28 @@ const router = new VueRouter({
base: process.env.BASE_URL,
routes
})
// router/index.js
router.beforeEach((to, from, next) => {
// 需要登录态的页面
const needAuth = !['/login'].includes(to.path)
// 检查登录信息
const wecomUserId = Cookies.get('wecom_userid')
const dingUserId = Cookies.get('ding_userid')
const externalUserId = Cookies.get('wecom_external_userid')
if (needAuth) {
if (wecomUserId && dingUserId && externalUserId) {
// 登录信息齐全,允许进入
next()
} else {
// 缺少登录信息,跳转到登录页
next('/login')
}
} else {
// 登录页、回调页等不需要校验
next()
}
})
export default router
......@@ -52,9 +52,7 @@ export default {
if (res.status_code === 1) {
this.organizationList = res.data.data
this.initCurrentApp();
this.$nextTick(() => {
this.dingInit();
});
}
},
......
// UnifiedLogin.vue
<template>
<div>
<div>
<div>
当前组织:<span class="current-org">{{ currentOrg.name }}</span>
<el-button type="text" @click="showOrgDialog = true">切换组织</el-button>
</div>
<div id="dingTalkLoginContainer"></div>
<!-- 组织切换弹窗 -->
<el-dialog :visible.sync="showOrgDialog" width="300px" title="选择组织">
<ul style="list-style:none;padding:0;margin-top: -20px;">
<li v-for="org in orgList" :key="org.app_key"
@click="switchOrg(org)"
:style="{
padding: '8px 16px',
cursor: 'pointer',
background: org.app_key === currentOrg.app_key ? '#e6f7ff' : '',
color: org.app_key === currentOrg.app_key ? '#1890ff' : '',
fontWeight: org.app_key === currentOrg.app_key ? 'bold' : 'normal',
borderRadius: '4px',
marginBottom: '4px',
transition: 'background 0.2s'
}"
@mouseover="hoveredOrg = org.app_key"
@mouseleave="hoveredOrg = null"
>
{{ org.name }}
<span v-if="org.app_key === currentOrg.app_key" style="margin-left:8px;">(当前)</span>
</li>
</ul>
</el-dialog>
<div v-if="dingUserInfo">钉钉用户:{{ dingUserInfo.name }}</div>
<div v-if="externalUserId">企微外部联系人ID:{{ externalUserId }}</div>
</div>
</div>
</template>
<script>
import * as ww from '@wecom/jssdk'
import { getOrganization } from '@/api/user'
import Cookies from 'js-cookie'
export default {
data() {
return {
wecomUserInfo: null, // 企微用户信息
dingUserInfo: null, // 钉钉用户信息
externalUserId: null, // 企微外部联系人ID
signData: null, // 企微签名数据
orgList: [],
currentOrg: {},
showOrgDialog: false,
hoveredOrg: null,
}
},
mounted() {
this.$nextTick( ()=>{
// await this.startWeComSilentAuth();
this.initOrganization();
this.initDingTalkLogin();
})
},
/*
1.把钉钉的逻辑中所有用的 appid 换成已选中的组织的 appid 也就是 this.currentOrg.app_key
2.点击切换切换组织没反应 并且给切换组织加点样式优化一下
*/
methods: {
// 1. 企微静默授权
async startWeComSilentAuth() {
const urlParams = this.getQueryParams();
if (!urlParams.code) {
// 跳转企微静默授权
const redirectUri = encodeURIComponent(window.location.href);
const appid = '你的企微CorpID';
const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect`;
window.location.href = authUrl;
return;
}
// 用code换取用户信息和签名
const res = await this.$api.getWeComUserAndSignature({ code: urlParams.code, url: window.location.href });
if (res.status_code === 1) {
this.wecomUserInfo = res.data.userInfo;
this.signData = res.data.signData;
// 注册JS-SDK
this.registerWeComSDK();
// 初始化钉钉扫码
this.initDingTalkLogin();
} else {
// 错误处理
}
},
// 2. 注册企微JS-SDK
registerWeComSDK() {
ww.register({
corpId: this.signData.corp_id,
agentId: this.signData.agent_id,
jsApiList: ['getCurExternalContact'],
getConfigSignature: () => Promise.resolve({
nonceStr: this.signData.nonceStr,
timestamp: this.signData.timestamp,
signature: this.signData.corp_signature,
}),
getAgentConfigSignature: () => Promise.resolve({
nonceStr: this.signData.nonceStr,
timestamp: this.signData.timestamp,
signature: this.signData.agent_signature,
}),
onAgentConfigSuccess: () => {
// 注册成功后不立即获取外部联系人,等钉钉扫码后再获取
},
onAgentConfigFail: (err) => {
// 错误处理
}
});
},
// 3. 获取组织列表并选取默认组织
async initOrganization() {
const res = await getOrganization();
if (res.status_code === 1) {
this.orgList = res.data.data;
// 默认组织逻辑:可根据业务自定义
this.initCurrentApp();
}
},
initCurrentApp() {
const currentApp = this.orgList.find(
(item) => item.app_key === "dingjigp0ksn9nbljdli"
);
this.$set(this, "currentOrg", currentApp);
},
// 4. 初始化钉钉扫码
initDingTalkLogin() {
if (!this.currentOrg.app_key) return;
const appid = this.currentOrg.app_key;
const redirectUri = encodeURIComponent(window.location.origin + '/ding-callback');
// 清空二维码容器,防止切换组织后二维码不刷新
const container = document.getElementById('dingTalkLoginContainer');
if (container) container.innerHTML = '';
DDLogin({
id: 'dingTalkLoginContainer',
goto: encodeURIComponent(`https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=${appid}&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=${redirectUri}`),
style: 'border:none;background-color:#FFFFFF;margin:0',
width: '210',
height: '250'
});
window.addEventListener('message', this.handleDingTalkLogin, false);
},
// 5. 切换组织
switchOrg(org) {
if (org.app_key === this.currentOrg.app_key) return; // 已是当前组织不处理
this.currentOrg = org;
this.showOrgDialog = false;
this.initDingTalkLogin();
},
// 6. 钉钉扫码回调
async handleDingTalkLogin(event) {
if (event.origin !== 'https://login.dingtalk.com') return;
const loginTmpCode = event.data;
// 跳转到后端,后端用loginTmpCode换取钉钉用户信息
const redirectUri = encodeURIComponent(window.location.origin);
const appid = this.currentOrg.app_key;
const url = `https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=${appid}&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=${redirectUri}&loginTmpCode=${loginTmpCode}`;
window.location.href = url;
},
// 7. 钉钉扫码回调页面处理
async handleDingCallback() {
const { code } = this.getQueryParams();
if (!code) return;
// 用code换取钉钉用户信息
const res = await this.$api.getDingUser({ code });
if (res.status_code === 1) {
this.dingUserInfo = res.data;
// 再次校验企微签名(可选,若页面未刷新可省略)
// this.registerWeComSDK();
// 获取外部联系人
this.getCurExternalContact();
} else {
// 错误处理
}
},
// 8. 获取企微外部联系人
getCurExternalContact() {
ww.getCurExternalContact({
success: (res) => {
if (res.err_msg === "getCurExternalContact:ok") {
this.externalUserId = res.userId;
}
},
fail: (err) => {
// 错误处理
}
});
},
// 工具方法:解析URL参数
getQueryParams() {
const params = {};
window.location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (str, key, value) {
params[key] = value;
});
return params;
}
},
created() {
// 如果是钉钉扫码回调页面
if (window.location.pathname === '/ding-callback') {
this.handleDingCallback();
}
}
}
</script>
<style lang="scss" scoped>
.current-org {
font-weight: bold;
margin-right: 5px;
}
</style>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论