Appearance
对接钉钉同步组织架构和成员
概述
在企业内部通常会使用钉钉
等即时通讯工具作为日常办公的沟通工具,这类工具通常提供了组织架构管理、用户管理、通知、待办等功能。 下面是对接飞书并同步组织架构和成员到织信的步骤。
实现步骤
- 同步钉钉组织架构前,需要先完成「第三方集成 >> 钉钉」的集成。
- 开通通讯录权限,在应用内-基础信息-权限管理,需要添加以下权限
- 通讯录个人信息读权限
- 成员信息读权限
- 通讯录部门信息读权限
- 邮箱等个人信息
- 企业员工手机号信息
- 个人手机号信息
实现代码
javascript
const defaultRole='normal';//授权给新用户的团队角色
const defaultPassword='123456';//新用户设置的密码,用户名为手机号
const syncMembers=true;//是否同步成员
let rootDeptId = null;
export function syncDept(){
var deptList = getDeptList();
console.log("deptList---------------->",JSON.stringify(deptList));
rootDeptId = (informat.dept.queryDeptList({
pageSize:1,
filter:{
conditionList:[
{"fieldId":"parentId","opt":"isnull"}
]
}
})[0] || {}).id;
console.log('rootDeptId', rootDeptId);
if(deptList!=null){
deptList.forEach(item=>{
var dept_id = `${item.dept_id}`;
var dept=informat.dept.getDept(dept_id);
console.log('dept_id', dept_id);
if(dept_id === '1') return;
if (dept==null) {
console.log('新增部门',item);
informat.dept.addDept({
'id': dept_id,
'name': item.name,
'remark': item.name,
'parentId': item.parent_id === 1 ? rootDeptId : `${item.parent_id}`
});
}else{
console.log('编辑部门',item);
informat.dept.updateDept({
'id': dept_id,
'name': item.name,
'parentId': item.parent_id === 1 ? rootDeptId : `${item.parent_id}`
});
}
});
}
//同步成员
if(syncMembers){
syncMemberList([{ dept_id: 1 }].concat(deptList));
}
}
function syncMemberList(deptList){
if(Array.isArray(deptList)) {
deptList.forEach(dept => {
const memberList = getMemberList(dept.dept_id);
memberList.forEach(member => {
var memberList=informat.company.queryCompanyMemberList({
pageIndex:1,
pageSize:1,
filter:{
conditionList:[{
"fieldId":"dingtalkUserId",
"opt":"eq",
"value":member.userid
}]
}
});
var departmentList=getDeptIdListWithDingtalkDeptIdList(member.dept_id_list);
if(memberList.length==0){//新增
var accountId=addAccount(member);
var roleList=defaultRole==null?[]:[defaultRole];
console.log('新增团队成员',member, departmentList);
informat.company.addCompanyMember(accountId, departmentList, roleList);
informat.company.updateCompanyMember({
id: accountId,
dingtalkUserId: member.userid,
});
}else{//编辑
console.log('编辑团队成员',member, departmentList);
var member=memberList[0];
informat.company.updateCompanyMember({
id: member.id,
departmentList: departmentList,
});
}
})
})
} else {
console.log("syncMemberList, deptList is not array. deptList: ", deptList);
}
}
function getDeptIdListWithDingtalkDeptIdList(idList) {
const rootIndex = idList.indexOf(1);
if(rootIndex > -1) {
idList.splice(rootIndex, 1, rootDeptId);
}
return idList.map(id => `${id}`)
}
function getMemberList(dept_id){
var dingtalkAccessToken=informat.app.dingtalkAccessToken();
var url = `https://oapi.dingtalk.com/topapi/user/listid?access_token=${dingtalkAccessToken}`;
var rs = httpPost(url,JSON.stringify({
"dept_id": dept_id
}));
const memberList = [];
if(rs.errcode === 0) {
rs.result.userid_list.forEach(id => {
memberList.push(getMemeberInfo(id));
});
}
return memberList;
}
function getMemeberInfo(user_id){
var dingtalkAccessToken=informat.app.dingtalkAccessToken();
var url = `https://oapi.dingtalk.com/topapi/v2/user/get?access_token=${dingtalkAccessToken}`;
var rs = httpPost(url,JSON.stringify({
"language":"zh_CN",
"userid": user_id
}));
return rs.result
}
function getDeptList(dept_id, result = []){
var dingtalkAccessToken=informat.app.dingtalkAccessToken();
var url = `https://oapi.dingtalk.com/topapi/v2/department/listsub?access_token=${dingtalkAccessToken}`;
//传入对应部门的id会识别该部门下的所有子部门id
const data = {
"language":"zh_CN"
}
if(dept_id) {
data.dept_id = dept_id
}
var rs = httpPost(url,JSON.stringify(data));
if(rs.errcode) return result;
const deptList = rs.result
deptList.forEach(item => {
// var detail = getDeptInfo(id);
result.push(item);
getDeptList(item.dept_id, result)
})
return result
}
function getDeptInfo(dept_id){
var dingtalkAccessToken=informat.app.dingtalkAccessToken();
var url = `https://oapi.dingtalk.com/topapi/v2/department/get?access_token=${dingtalkAccessToken}`;
var rs = httpPost(url,JSON.stringify({
"language":"zh_CN",
"dept_id": dept_id
}));
return rs.result;
}
function addAccount(item){
var mobile=item.mobile;
if(mobile==null){
throw new Error('员工手机号不能为空,请开放查看手机权限');
}
if(mobile.length==14){
mobile=mobile.substr(3);
}
var accountList=informat.system.queryAccountList({
pageIndex: 1,
pageSize: 1,
filter: {
conditionList: [
{
fieldId: 'mobileNo',
opt: 'eq',
value: mobile
}
]
}
});
var accountId=null;
if(accountList.length==0){//账号不存在
console.log('新增账号',item);
accountId=informat.system.addAccount({
oid: item.userid,
name: item.name,
avatar: 'pic15.png',
userName: mobile,
mobileNo: mobile,
email: item.email,
password: defaultPassword
});
}else{
var oldAccount=accountList[0];
accountId=oldAccount.id;
console.log('编辑账号',item, oldAccount);
informat.system.updateAccount({
id: oldAccount.id,
name: item.name,
userName: mobile,
mobileNo: mobile
});
}
return accountId;
}
function httpPost(url,body){
console.log("url----------------->",url);
console.log("body----------------->",body);
var resp=informat.http.request({
headers: {
"Content-Type": "application/json;chartset=utf-8"
},
method: "POST",
timeout: 30000,
url: url,
body:body,
});
if (200 != resp.statusCode()) {
console.log('url',url)
console.log('resp statusCode',resp.statusCode());
console.log('resp body',resp.body())
throw new Error('发起http请求失败,请联系开发人员');
}
console.log("url------->",url)
console.log("resp----------->",resp.body());
return JSON.parse(resp.body());
}