mtl-js-sdk
Version:
ynf-fw-mtl-api
641 lines (597 loc) • 22.8 kB
JavaScript
/*
* @Author: wangyingliang@yonyou.com
* @Date: 2024-10-31 09:34:14
* @LastEditors: wangyingliang wangyingliang@yonyou.com
* @LastEditTime: 2025-10-20 16:46:43
* @FilePath: /mtl-api-project/src/platforms/all-platform/contacts/index.js
* @Description: 选人组件
* Copyright (c) 2024 by Yonyou, All Rights Reserved.
*/
import xaxios from 'axios'
const axios = xaxios?.default || xaxios
const FILE_PATH = '/selectcontacts/mobile.contacts.min.js'
function getSocializedServicesDomain(domain) {
let domainUrl = domain || window.location.origin
// https://bip-daily-dedicated.yonyoucloud.com
if (domain.includes('bip-daily-dedicated') || domain.includes('mretail-bip-daily')) {
if (domain.includes('diwork')) {
domainUrl = 'https://bip-daily.diwork.com'
} else {
domainUrl = 'https://bip-daily.yonyoucloud.com'
}
} else if (
domain.includes('c1.') ||
domain.includes('c3.') ||
domain.includes('c4.') ||
domain.includes('c5.') ||
domain.includes('c6.') ||
domain.includes('dbox.')) {
// 如果不是测试环境, 线上统一使用 c2 环境.
domainUrl = ''
if (domain.includes('diwork')) {
domainUrl = 'https://c2.diwork.com'
} else {
domainUrl = 'https://c2.yonyoucloud.com'
}
} else if (
domain.includes('core1.') ||
domain.includes('core3.')) {
// 如果不是测试环境, 线上统一使用 c2 环境.
domainUrl = ''
if (domain.includes('diwork')) {
domainUrl = 'https://c2.diwork.com'
} else {
domainUrl = 'https://c2.yonyoucloud.com'
}
}
return domainUrl
}
/**
* 根据当前环境获取服务域名
* @param {function} success 成功的回调
* @param {function} fail 失败的回调
*/
function getDomain(object) {
mtl.execUpesnBridge({
method: 'getMultiDataCenterConfig',
success: function (res) {
console.log("getMultiDataCenterConfig: ");
console.log(res);
window.mtl.contacts.tenantId = object?.tenantId || res.currentTenantID
let domainUrl = res.multidata.multidataUrl[object?.tenantId || res.currentTenantID] // 默认是多数据中心地址
if (object?.serviceCode) {
// 如果 serviceCode 存在需要查询是否在多数据中心环境
let multidataCodeList = res.multidata?.multidataCode // 多数据中心域名
let domainCodeList = res.domain?.domainCode // 社会化服务域名
console.log(1);
if (multidataCodeList[object?.serviceCode]) {
console.log(2);
domainUrl = res.multidata.multidataUrl[object?.tenantId || res.currentTenantID]
} else if (domainCodeList[object?.serviceCode]) {
domainUrl = res.domain.domainUrl // 社会化域名
} else {
console.log(3);
domainUrl = window.location.origin // 当前环境域名
}
}
object?.success(resultStructure("200", "Successfully obtained", {
domain: domainUrl
}))
},
fail: (err) => {
// 不是在友空间
console.log("err: ", err);
if (mtl.platform === "APIIos" || mtl.platform === "APIAndroid") {
// 友空间私有版 需要额外处理
mtl.getStorage({
key: 'key_base_url',
success: (res) => {
console.log("res = ", res)
object?.success(resultStructure("200", "YYZone API scenes", {
domain: res?.data || ''
}))
},
fail: (err) => {
object?.success(resultStructure("201", "YYZone API scenes", {
domain: object?.baseUrl || window.location.origin
}))
},
})
} else {
object?.success(resultStructure("201", "Successfully obtained non YYZone scenes", {
domain: object?.baseUrl || window.location.origin
}))
}
}
});
}
/**
* 判断指定的CSS文件是否已经被加载过
* @param {string} url 资源地址
* @returns true 加载过, false 未加载
*/
function isLoadedCss(url) {
// 老选人组件退出会移除对象, 必须要重复加载.
if (url.indexOf('mobile.contacts.min') != -1) {
return false
}
for (var i = 0; i < document.styleSheets.length; i++) {
if (document.styleSheets[i].href == url) {
return true; // CSS文件已经加载过
}
}
return false; // CSS文件还没有加载过
}
/**
* 判断指定的CSS文件是否已经被加载过
* @param {string} url 资源地址
* @returns true 加载过, false 未加载
*/
function isLoadedJsScript(url) {
if (url.indexOf('mobile.contacts.min') != -1) {
return false
}
for (var i = 0; i < document.scripts.length; i++) {
if (document.scripts[i].src == url) {
return true;
}
}
return false;
}
/**
* 动态加载多个cdn脚本.
* @param {array} urls cdn 地址
* @param {number} index 当前的
* @param {function} success 成功的回调
* @param {function} fail 失败的回调
*/
function loadCDNScript(object) {
let index = object?.index || 0
let url = object?.urls && object?.urls[index]
let isCSS = url.includes('.css')
let element = isCSS ? "link" : "script"
let type = isCSS ? "text/css" : "text/javascript"
var script = document.createElement(element);
script.type = type;
if (isCSS) {
script.rel = "stylesheet";
script.href = url;
} else {
script.src = url;
}
script.onload = () => {
console.log('init success ============== ', index)
index += 1
if (index == object.urls.length) {
object?.success && object?.success(resultStructure("200", "success"))
return
}
object.index = index
loadCDNScript(object)
}
script.onerror = (err) => {
console.log(' init fail ============== ', index)
index += 1
if (index == object.urls.length) {
object?.success && object?.success(resultStructure("200", "success"))
return
}
object.index = index
loadCDNScript(object)
}
console.log('url = ' + url);
// 判断当前页面是否已经存在相同的脚本
if (isCSS && !isLoadedCss(url)) {
window.document.head.appendChild(script)
} else if (!isCSS && !isLoadedJsScript(url)) {
window.document.body.appendChild(script);
} else {
object?.success && object?.success(resultStructure("200", "The resource has already been loaded and cannot be loaded again"))
return // 跳出递归逻辑, 不能删除!
}
}
// 上传
async function getHeaders(form) {
return new Promise((resolve, reject) => {
form.getLength((err, length) => {
if (err) reject(err)
const headers = Object.assign({ "Content-Length": length }, form.getHeaders())
resolve(headers)
})
})
}
/**
* 判断当前环境是否协同OA盘
*/
function getOAStatus(object) {
var baseUrl = object?.baseUrl || window.location.origin
baseUrl = baseUrl.endsWith('/') ? baseUrl : baseUrl + '/'
var url = baseUrl + "iuap-yonbuilder-" + "mobile/rest/v1/mobile/addressBook/containsOA"
var xaxios = axios?.default || axios
xaxios.get(url, {
params: {
tenantId: object?.tenantId,
A00: object?.a00,
A01: object?.a01,
},
headers: {
'Content-Type': 'application/json'
},
timeout: 5000,
withCredentials: true,
responseType: 'json'
}).then(function (res) {
console.log("res = ", res.data)
object?.success && object?.success(res.data.data)
}).catch(function (err) {
console.log("err = ", err)
object?.fail && object?.fail({ isOA: false })
});
}
/**
* mobile.contacts.min.js 选人组件初始化函数
* @param {string} url 资源地址
* @param {string} urls 资源地址数组, 推荐使用
* @param {string} renew 强制加载资源, 仅支持mobile.contacts组件
* @param {string} tenantId 租户Id, 必填
* @param {string} serviceCode 服务编码, 非必填
* @param {bool} isExclusivity 是否是专属化, 默认 false
* @param {bool} debug 是否开启debug模式, 默认false
* @param {function} success 成功的回调
* @param {function} fail 失败的回调
*/
function init(option) {
// 2024年08月12日, 讨论后结论为,
// - 公有云所有场景只使用协同云选人组件.
// - 私有云场景, 增加判断当前环境是否有协同OA盘, 如果有依然使用协同云选人组件, 没有则使用平台选人组件.
window.mtl.contacts.tenantId = option?.tenantId
// 获取 iuap-yonbuilder-mobile 服务 domain.
getDomain({
tenantId: option?.tenantId,
serviceCode: "iuap-yonbuilder-mobile",
success: (res) => {
var baseUrl = res.data.domain
if (res.code === '201') {
// 查不到情况下使用当前环境
baseUrl = option?.baseUrl || window.location.origin
}
option.baseUrl = baseUrl
var obj = {
tenantId: option?.tenantId,
baseUrl: baseUrl,
a00: option?.a00 || option?.A00,
a01: option?.a01 || option?.A01,
success: (res) => {
option.oaStatus = res?.isOA
_init(option)
},
fail: (res) => {
option.oaStatus = res?.isOA || false
_init(option)
},
}
// 判断当前环境是否有协同OA盘, 存储状态, 跨租户场景兼容
getOAStatus(obj)
}
})
}
function _init(option) {
let url = option?.url // mobile.contacts.min.js 选人组件. 注意: 如果url有值一定用mobile.contacts.min.js选人
let baseUrl = option?.baseUrl // 当前环境
let isExclusivity = option?.isExclusivity || false // true 专属化, false 公有云;
window.mtl.contacts.isExclusivity = isExclusivity // 存储到全局对象
if (!option.oaStatus) {
// 如果传了url或者私有化标识, 使用 mobile.contacts.min.js 选人组件, 否则使用友空间选人组件.
if (url || isExclusivity) {
if (!baseUrl) {
// mobile.contacts.min.js 选人组件为多核心服务
getDomain({
tenantId: option?.tenantId,
serviceCode: option?.serviceCode,
success: (res) => {
option.baseUrl = res.data.domain
initMobileContacts(option)
}
})
return
}
initMobileContacts(option)
}
return
}
if (baseUrl) {
// domain 需要特殊处理
option.baseUrl = getSocializedServicesDomain(baseUrl)
initYYZoneSelectMember(option)
return
}
getDomain({
tenantId: option?.tenantId,
serviceCode: "yonbip-ec-base",
success: (res) => {
option.baseUrl = res.data.domain
if (res.code === '201') {
// 非友空间情况下 处理接口
option.baseUrl = getSocializedServicesDomain(res.data.domain)
}
initYYZoneSelectMember(option)
}
})
}
/**
* mobile.contacts.min.js 选人组件初始化函数
* @param {string} url 资源地址
* @param {string} renew 强制加载资源
* @param {bool} debug 是否开启debug模式, 默认false
* @param {function} success 成功的回调
* @param {function} fail 失败的回调
*/
function initMobileContacts(object) {
let url = object?.url
let renew = object?.renew
// https://c1.yonyoucloud.com/iuap-yonbuilder-designer/ucf-wh/mobile-builder/selectcontacts/mobile.contacts.min.js
if (!url) {
if (object?.debug) {
url = 'https://bip-daily.yonyoucloud.com' + '/iuap-yonbuilder-designer/ucf-wh/mobile-builder' + FILE_PATH
} else {
let baseUrl = object?.baseUrl // 当前环境
if (baseUrl) {
let doamin = baseUrl.endsWith('/') ? baseUrl : baseUrl + '/'
url = `${doamin}iuap-yonbuilder-designer/ucf-wh/mobile-builder${FILE_PATH}`
} else {
url = `${window.location.origin}/iuap-yonbuilder-designer/ucf-wh/mobile-builder${FILE_PATH}`
}
}
}
if (window.selectContacts && !renew) {
console.log('selectContacts version is: ', window.selectContacts.version)
object?.success && object?.success(resultStructure("200", "The resource has already been loaded and cannot be loaded again"))
return
}
console.log("----------url----------" + url);
window.mtl.contacts.domain = object?.baseUrl || new URL(url).origin || window.location.origin;
loadCDNScript({
urls: [
url
],
success: (res) => {
if (!window.selectContacts) {
object?.fail && object?.fail(resultStructure('-1', "mobile.contacts init error"))
return
}
console.log('mobile.contacts init success, version is : ', window.selectContacts.version)
object?.success && object?.success(resultStructure("200", "success"))
},
fail: (err) => {
object?.fail && object?.fail(resultStructure('-1', "mobile.contacts init error"))
}
})
}
/**
* YYZoneSelectMember 友空间选人组件初始化函数
* @param {string} urls 资源地址
* @param {bool} debug 是否开启debug模式, 默认false
* @param {function} success 成功的回调
* @param {function} fail 失败的回调
*/
function initYYZoneSelectMember(object) {
let urls = object?.urls
if (!urls) {
if (object?.debug) {
urls = [
'https://bip-daily.yonyoucloud.com' + '/yonbip-ec-base/ucf-wh/promotion/mobileSelectMember/js/index.js',
'https://bip-daily.yonyoucloud.com' + '/yonbip-ec-base/ucf-wh/promotion/mobileSelectMember/css/selectMember.css',
]
} else {
let baseUrl = object?.baseUrl // 当前环境
if (!baseUrl) {
baseUrl = window.location.origin + '/'
}
baseUrl = baseUrl.endsWith('/') ? baseUrl : baseUrl + "/"
urls = [
`${baseUrl}yonbip-ec-base/ucf-wh/promotion/mobileSelectMember/js/index.js`,
`${baseUrl}yonbip-ec-base/ucf-wh/promotion/mobileSelectMember/css/selectMember.css`,
]
}
}
window.mtl.contacts.domain = object?.baseUrl || new URL(url).origin || window.location.origin;
loadCDNScript({
urls: urls,
success: (res) => {
if (!window.YouZoneMobileSelectMember) {
object?.fail && object?.fail(resultStructure('-1', "YouZoneMobileSelectMember init error"))
return
}
console.log('YouZoneMobileSelectMember init finish')
object?.success && object?.success(resultStructure("200", "success"))
},
fail: (err) => {
object?.fail && object?.fail(resultStructure('-1', "YouZoneMobileSelectMember init error"))
}
})
}
function selectContacts(option) {
selectPersonnel({ ...option, userFlag: true })
}
function selectPersonnel(option) {
//window.selectContacts 支持全平台的调用,
//需要Android、IOS时候可以
//needYhtUserId number 1:需要友户通ID 0:不需要友户通ID
const { filterList = [], filterCondition, isNative = true, lang = "zhcn", selectUserList = [], needDeptMember = false } = option;
let userIds = [] // yhtUserId 数组, 给老选人用
let filterMembers = {} // 新结构给协同选人
filterList.forEach(element => {
if (typeof element == "string") {
userIds.push(element)
return
}
const yhtUserId = element?.yhtUserId || element?.id
if (yhtUserId) {
userIds.push(yhtUserId)
filterMembers[yhtUserId] = element
}
});
let tenantId = option?.tenantId || window.mtl.contacts.tenantId
// window.selectContacts 对象不存且非专属化场景
// if (!window?.selectContacts && !window.mtl?.contacts.isExclusivity) {
if (!window?.selectContacts && !window.mtl.oaStatus) {
let baseUrl = option?.baseUrl || window.mtl.contacts.domain || window.location.origin
console.log("YouZoneMobileSelectMember domain = ", baseUrl);
// 使用友空间h5选人组件
let { tabKeys = ['deptMember', 'groupMember'], maxCount = 1500, customTabs = [] } = option
let members = {}
selectUserList.forEach(element => {
const yhtUserId = element?.yhtUserId || element?.id
if (yhtUserId) {
members[yhtUserId] = element
}
})
let isZH = lang.indexOf('zh') != -1 || lang.indexOf('ZH') != -1
if (filterList.length > 0) {
tabKeys = ['userMember']
if (needDeptMember) {
tabKeys.push('deptMember')
}
customTabs.push({
title: option?.tabTitle || (isZH ? '范围选人' : "Range selection"),
key: 'userMember',
type: 'list',
dataType: 'member',
data: filterMembers,
tenantId,
onSearch: option?.onSearch ? option?.onSearch : function (keyword, callback) {
const searchMembers = {}
let failedList = filterList.filter((item) => {
// 处理成字符串, 并转成小写
let title = item?.userName || item?.title
title = title + ''
title = title.toLowerCase()
// 搜索词同样处理
let hotKey = keyword + ''
hotKey = hotKey.toLowerCase()
return title.includes(hotKey)
});
failedList.forEach(element => {
const yhtUserId = element?.yhtUserId || element?.id
if (yhtUserId) {
searchMembers[yhtUserId] = element
}
});
if (!keyword) {
searchMembers = filterMembers
}
callback(searchMembers)
}
})
}
window.YouZoneMobileSelectMember({
tenantId,
...option,
lang: lang,
domainUrl: baseUrl,
limit: maxCount,
tabKeys,
haveSelected: { member: { ...members } },
customTabs,
onConfirm: function (res) {
const { member = {} } = res
const array = Object.values(member)
option?.success && option?.success({
code: 200,
message: 'YouZoneMobileSelectMember success',
data: { ...res, selectUserList: array }
})
},
onCancle: function (res) {
option?.cancel && option?.cancel({
...res,
code: 200,
message: 'cancel event success',
actionType: 'cancle'
});
}
})
return
}
// 判断是否是在友空间
if (checkNativate(option) && isNative) {
console.log("------ chooseContacts ------");
// 在友空间内, 并需要使用原生调用
let fCondition = filterCondition;
if (!!!filterCondition) {
let lists = [];
filterList.forEach(element => {
lists.push({ refpk: element })
});
if (lists && lists.length > 0) {
fCondition = JSON.stringify({ specUsers: lists, isSpecRange: true, isPartData: true });
} else {
fCondition = '';
}
}
let chooseContacts = mtl.chooseContacts || mtl.upesn.chooseContacts || {}
chooseContacts({
tenantId,
...option,
needYhtUserId: 1,
selectedList: selectUserList,
filterCondition: fCondition,
success: (res) => {
console.log("chooseContacts,", res)
option.success && option.success(
{
code: 200,
message: 'chooseContacts success',
data: { selectUserList: res }
})
}
})
return
}
console.log("------ selectContacts.showBox ------");
if (!window.selectContacts) {
option?.fail && option?.fail(resultStructure("-1", "Please executing init function first!"))
return
}
if (filterList.length > 0) {
option.filterList = userIds
}
window.selectContacts.showBox({
tenantId,
...option,
baseUrl: `${option?.baseUrl || window.location.origin}/iuap-yonbuilder-mobile`,
onClose: (res) => {
option?.success && option?.success(res)
}
})
}
function error(option, msg) {
option.fail && option.fail({ message: msg })
}
function checkNativate(option) {
const platform = option.platform || mtl.platform;
console.log('platform is ', platform)
//暂时先屏蔽了这段逻辑,友空间选人有问题
return (platform === "upesn")
}
/**
* 处理回调返回结构
* @param {string} code 响应code
* @param {string} msg code 对应的说明
* @param {object} data 返回值
*/
function resultStructure(code, msg, data) {
const response = {
code: code,
message: msg
}
if (data) {
response.data = data
}
return response
}
export default {
init,
selectContacts,
selectPersonnel
};