UNPKG

mtl-js-sdk

Version:

ynf-fw-mtl-api

641 lines (597 loc) 22.8 kB
/* * @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 };