封装的DynamicCRM平台中最实用的JS工具类
包含了一个遮罩层的使用对象和一个通用的CRM平台JS操作对象。
使用示例:
常用的比如去除页面查找字段guid的'{}':commonUtil.delBrackets(commonUtil.getLookupId("xxx_xxxx"))
遮罩层使用方式:overflowLayer.open("耗时中...", toDo) :toDo为当前使用遮罩层的js方法名
注意使用遮罩层的js方法都需要加一个回调参数,在执行完耗时方法后调用:overflowLayer.close() 关闭
function toDo(callback) { console.log('开始审批(BPM)') if (!callback) { Xrm.Utility.confirmDialog("您将做一个耗时操作,是否确认?", function () { overflowLayer.open("操作执行中,请勿进行其他操作...", toDoM); return; }) } else{ //执行操作 overflowLayer.close(); } }
通用commonUtil工具JS
1 var isFirstDefineOverflowLayer = false; 2 /** 3 * 遮罩层的使用 4 */ 5 var overflowLayer = overflowLayer || (function () { 6 if (window == window.top) { 7 return { 8 open: function (msg) { }, 9 close: function () { }, 10 appendShadowCls: function () { }, 11 appendShadowDiv: function () { } 12 }; 13 } 14 isFirstDefineOverflowLayer = true; 15 return { 16 layerId: 'layer_shadow_in_top_window', 17 /** 18 * 打开遮罩层 19 * @param {any} msg 遮罩层提示的信息 20 */ 21 open: function (msg, callback) { 22 $('#' + this.layerId + '_div', window.top.document).css('display', 'block'); 23 $('#' + this.layerId + '_msgDiv', window.top.document).css('display', 'block'); 24 $('#' + this.layerId + '_msg', window.top.document).text(msg); 25 if (typeof callback === 'function') { 26 setTimeout(function () { callback(true); }, 100);// 中断JS线程让界面及时渲染 27 } 28 }, 29 /** 30 * 关闭遮罩层 31 */ 32 close: function () { 33 $('#' + this.layerId + '_div', window.top.document).css('display', 'none'); 34 $('#' + this.layerId + '_msgDiv', window.top.document).css('display', 'none'); 35 }, 36 /** 37 * 添加遮罩层样式至顶层页面 38 */ 39 appendShadowCls: function () { 40 var doc = window.top.document; 41 var shadowCssId = this.layerId + '_css'; 42 var shadowCss = doc.getElementById(shadowCssId); 43 if (shadowCss) { 44 return; 45 } 46 var shadowDode = '.msgbox-shadow {position: fixed;left: 0;top: 0;right: 0;bottom: 0;background-color: #FFF;opacity: 0.8;z-index: 10000;}'; 47 var modalCode = '.msgbox-modal {position: fixed;top: 50%;left: 50%;opacity: 1;transform: translate(-50%, -50%);z-index: 10001;}'; 48 var style = doc.createElement('style'); 49 style.id = shadowCssId 50 style.type = 'text/css'; 51 style.rel = 'stylesheet'; 52 //for Chrome Firefox Opera Safari 53 style.appendChild(doc.createTextNode(shadowDode)); 54 style.appendChild(doc.createTextNode(modalCode)); 55 //for IE 56 if (this.isIE()) { 57 style.styleSheet.cssText = shadowDode; 58 style.styleSheet.cssText = modalCode; 59 } 60 var head = doc.getElementsByTagName('head')[0]; 61 head.appendChild(style); 62 }, 63 appendShadowDiv: function () { 64 var doc = window.top.document; 65 var shadowDivId = this.layerId + '_div'; 66 var shadowDiv = doc.getElementById(shadowDivId); 67 if (shadowDiv) { 68 return; 69 } 70 71 var body = doc.getElementsByTagName('body')[0]; 72 var layerDiv = doc.createElement('div'); 73 body.appendChild(layerDiv); 74 layerDiv.id = shadowDivId; 75 layerDiv.classList.add('msgbox-shadow'); 76 var msgDiv = doc.createElement('div'); 77 msgDiv.id = this.layerId + '_msgDiv'; 78 body.appendChild(msgDiv); 79 msgDiv.classList.add('msgbox-modal'); 80 81 msgDiv.style.textAlign = 'center'; 82 var img = doc.createElement('img'); 83 img.src = "/_imgs/processing_loader.gif"; 84 img.classList.add('ms-crm-inline-processing'); 85 msgDiv.appendChild(img); 86 msgDiv.appendChild(document.createElement('br')); 87 var msgText = doc.createElement('span'); 88 msgText.id = this.layerId + '_msg'; 89 msgText.style.fontSize = '20px'; 90 msgText.style.margin = '0px'; 91 msgText.style.padding = '0px'; 92 msgDiv.appendChild(msgText); 93 94 layerDiv.style.display = 'none'; 95 msgDiv.style.display = 'none'; 96 }, 97 isIE: function () { 98 var userAgent = navigator.userAgent; 99 var isOpera = userAgent.indexOf("Opera") > -1; //判断是否Opera浏览器 100 return userAgent.indexOf("compatible") > -1 101 && userAgent.indexOf("MSIE") > -1 && !isOpera; //判断是否IE浏览器 102 } 103 }; 104 })(); 105 106 if (isFirstDefineOverflowLayer) { 107 overflowLayer.appendShadowCls(); // 添加CSS样式到document 108 overflowLayer.appendShadowDiv(); // 添加遮罩层到顶层document 109 } 110 111 /** 112 * 封装常用CRM操作工具类 113 */ 114 var commonUtil = (function () { 115 const BASE_URL = Xrm.Page.context.getClientUrl() + "/api/data/v8.2"; 116 //是否本地 117 const IS_LOCAL = true; 118 /** 119 * 获取当前运行环境 120 */ 121 const getEnvironment = function () { 122 if (Xrm.Page.context.getClientUrl().indexOf("Testf") >= 0) 123 return "1";//测试环境 124 else if (Xrm.Page.context.getClientUrl().indexOf("hwdms") >= 0) 125 return "2";//正式环境 126 } 127 /** 128 * 打开弹窗 129 */ 130 const openDialog = function (page, params, cbfun, level, width, height, top) { 131 if (level == null || level == "") 132 level = 0; 133 if (width == null || width == "") 134 width = 1000; 135 if (height == null || height == "") 136 height = 550; 137 if (top == null || top == "") 138 top = -300; 139 var Clienturl = Xrm.Page.context.getClientUrl(); 140 var URL = Clienturl + "/WebResources/" + page; 141 var DialogOption = new Xrm.DialogOptions; 142 DialogOption.width = width; 143 DialogOption.height = height; 144 DialogOption.top = top; 145 switch (level) { 146 case 0://0级子页面,即当前页面打开弹窗 147 Xrm.Internal.openDialog(URL + "?Type=&data=" + params, DialogOption, null, null, cbfun); 148 break; 149 case 1://1级子页面打开弹窗 150 parent.Xrm.Internal.openDialog(URL + "?Type=&data=" + params, DialogOption, null, null, cbfun); 151 break; 152 } 153 } 154 /** 155 * 根据查询URL执行查询操作 156 * @param {any} queryUrl 查询URL 157 * @param {any} callback 结果回调方法 158 * @param {any} async 是否异步查询,默认为true 159 * @param {int} maxRows 获取记录的最大条数,默认为空 160 */ 161 const queryWithUrl = function (queryUrl, callback, async, maxRows) { 162 if (!queryUrl) { 163 callback && callback({ success: false, message: '参数queryUrl不可为空' }) 164 return 165 } 166 var req = new XMLHttpRequest(); 167 req.open("GET", BASE_URL + queryUrl, async !== false); 168 req.setRequestHeader("OData-MaxVersion", "4.0"); 169 req.setRequestHeader("OData-Version", "4.0"); 170 req.setRequestHeader("Accept", "application/json"); 171 req.setRequestHeader("Content-Type", "application/json; charset=utf-8"); 172 req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"" + (maxRows ? (",odata.maxpagesize=" + maxRows) : "")); 173 req.onreadystatechange = function () { 174 if (this.readyState === 4) { 175 req.onreadystatechange = null; 176 let result = { success: false, message: this.statusText } 177 if (this.status === 200) { 178 result.success = true 179 let data = JSON.parse(this.response) 180 result.data = data.value || data 181 } else { 182 console.error(this.response) 183 } 184 callback && callback(result) 185 } 186 }; 187 req.send(); 188 } 189 190 const createEntity = function (entitySetName, entityData, callback, async) { 191 if (!entitySetName) { 192 callback && callback({ success: false, message: '参数entitySetName不可为空' }) 193 return 194 } 195 var req = new XMLHttpRequest(); 196 req.open("POST", `${BASE_URL}/${entitySetName}`, async !== false); 197 req.setRequestHeader("OData-MaxVersion", "4.0"); 198 req.setRequestHeader("OData-Version", "4.0"); 199 req.setRequestHeader("Accept", "application/json"); 200 req.setRequestHeader("Content-Type", "application/json; charset=utf-8"); 201 req.setRequestHeader("Prefer", "odata.include-annotations=\"*\""); 202 req.onreadystatechange = function () { 203 let result = { success: false, message: this.responseText } 204 if (this.readyState === 4) { 205 req.onreadystatechange = null; 206 if (this.status === 204) { 207 var uri = this.getResponseHeader("OData-EntityId"); 208 var regExp = /\(([^)]+)\)/; 209 var matches = regExp.exec(uri); 210 result.success = true 211 result.data = { id: matches[1] } 212 } else { 213 console.error('----' + this.responseText) 214 } 215 } else { 216 console.error('==== ' + this.responseText) 217 } 218 callback && callback(result) 219 }; 220 req.send(JSON.stringify(entityData)); 221 } 222 223 const updateEntity = function (entitySetName, entityId, entityData, callback, async) { 224 if (!entitySetName) { 225 callback && callback({ success: false, message: '参数entitySetName不可为空' }) 226 return 227 } 228 var req = new XMLHttpRequest(); 229 req.open("PATCH", `${BASE_URL}/${entitySetName}(${entityId})`, async !== false); 230 req.setRequestHeader("OData-MaxVersion", "4.0"); 231 req.setRequestHeader("OData-Version", "4.0"); 232 req.setRequestHeader("Accept", "application/json"); 233 req.setRequestHeader("Content-Type", "application/json; charset=utf-8"); 234 req.onreadystatechange = function () { 235 let result = { success: false, message: this.statusText } 236 if (this.readyState === 4) { 237 req.onreadystatechange = null; 238 if (this.status === 204) { 239 result.success = true 240 result.data = { id: entityId } 241 } else { 242 console.error('----' + this.statusText) 243 } 244 } else { 245 console.error('==== ' + this.statusText) 246 } 247 callback && callback(result) 248 }; 249 req.send(JSON.stringify(entityData)); 250 } 251 252 /** 253 * 根据业务实体集合名称及业务实体ID删除指定的记录 254 * @param {any} entitySetName 【必须】业务实体集合名称 255 * @param {any} entityId 【必须】业务实体ID 256 * @param {any} callback 【可选】回调方法,参数为:{success:true/false,message:null/具体错误信息} 257 * @param {any} async 【可选】是否异步操作,默认为true,传入false时则同步执行,否则按异常执行 258 */ 259 const deleteEntity = function (entitySetName, entityId, callback, async) { 260 var req = new XMLHttpRequest(); 261 req.open("DELETE", `${BASE_URL}/${entitySetName}(${entityId})`, async !== false); 262 req.setRequestHeader("Accept", "application/json"); 263 req.setRequestHeader("Content-Type", "application/json; charset=utf-8"); 264 req.setRequestHeader("OData-MaxVersion", "4.0"); 265 req.setRequestHeader("OData-Version", "4.0"); 266 req.onreadystatechange = function () { 267 if (this.readyState === 4) { 268 req.onreadystatechange = null; 269 callback && callback({ 270 success: this.status === 204 || this.status === 1223, 271 message: this.statusText 272 }) 273 if (this.status !== 204 && this.status !== 1223) { 274 console.error(this.response) 275 } 276 } 277 }; 278 req.send(); 279 } 280 /** 281 * 通过实体id取得数据 282 */ 283 const getEntityData = function (entity, id) { 284 var resultData = null; 285 var queryUrl = "/" + entity + "(" + commonUtil.delBrackets(id) + ")"; 286 commonUtil.queryWithUrl(queryUrl, 287 (result) => { 288 console.log("getEntityData", result) 289 if (result != null && result.data != null) 290 resultData = result.data; 291 }, false, 1); 292 293 return resultData; 294 } 295 /** 296 * 通过查询url取得数据 297 */ 298 const getEntityDatas = function (queryUrl) { 299 var resultData = null; 300 commonUtil.queryWithUrl(queryUrl, (result) => { 301 if (result && result.data && result.data.length) { 302 resultData = result.data; 303 } 304 }, false); 305 306 return resultData; 307 } 308 /** 309 * 在URL中解析ID 310 */ 311 const getIdFromUrl = function () { 312 let objData = parseParams() 313 return objData['?_CreateFromId'] && decodeURIComponent(objData['?_CreateFromId']) 314 } 315 /** 316 * 解析URL传入的参数 317 */ 318 const parseParams = function () { 319 var objData = {}; 320 var vals = decodeURIComponent(getParameter("extraqs")).split("&"); 321 for (var i = 0; i < vals.length; i++) { 322 var pr = vals[i].replace(/\+/g, " ").split("="); 323 if (pr.length != 2) { 324 continue; 325 } 326 objData[pr[0]] = pr[1]; 327 } 328 return objData; 329 } 330 /** 331 * 获取参数信息 332 * @param {any} param url参数 333 */ 334 const getParameter = function (param) { 335 var query = window.top.location.search; 336 var iLen = param.length; 337 var iStart = query.indexOf(param); 338 if (iStart == -1) 339 return ""; 340 iStart += iLen + 1; 341 var iEnd = query.indexOf("&", iStart); 342 if (iEnd == -1) 343 return query.substring(iStart); 344 return query.substring(iStart, iEnd); 345 } 398 /** 399 * 判断页面元素是否字段控件类型 400 * @param {any} control 控件对象 401 */ 402 const controlIsAttribute = function (control) { 403 var controlType = control.getControlType(); 404 return controlType != "iframe" && controlType != "webresource" && controlType != "subgrid"; 405 } 406 407 return { 408 /** 409 * 根据查询URL执行查询操作 410 * @param {any} queryUrl 查询URL 411 * @param {any} callback 结果回调方法 412 * @param {any} async 是否异步查询,默认为true 413 * @param {int} maxRows 获取记录的最大条数,默认为空 414 */ 415 queryWithUrl: queryWithUrl, 416 /** 417 * 根据业务实体集合名称及业务实体ID删除指定的记录 418 * @param {any} entitySetName 【必须】业务实体集合名称 419 * @param {any} entityId 【必须】业务实体ID 420 * @param {any} callback 【可选】回调方法,参数为:{success:true/false,message:null/具体错误信息} 421 * @param {any} async 【可选】是否异步操作,默认为true,传入false时则同步执行,否则按异常执行 422 */ 423 deleteEntity: deleteEntity, 424 /** 425 * 根据业务实体集合名称及业务实体数据创建新的记录 426 * @param {any} entitySetName 【必须】业务实体集合名称 427 * @param {any} entityData 【必须】业务实体数据 428 * @param {any} callback 【可选】回调方法,参数为:{success:true/false,message:null/具体错误信息} 429 * @param {any} async 【可选】是否异步操作,默认为true,传入false时则同步执行,否则按异常执行 430 */ 431 createEntity: createEntity, 432 /** 433 * 根据业务实体集合名称及业务实体数据创建新的记录 434 * @param {any} entitySetName 【必须】业务实体集合名称 435 * @param {any} entityId 【必须】业务实体ID 436 * @param {any} entityData 【必须】业务实体数据 437 * @param {any} callback 【可选】回调方法,参数为:{success:true/false,message:null/具体错误信息} 438 * @param {any} async 【可选】是否异步操作,默认为true,传入false时则同步执行,否则按异常执行 439 */ 440 updateEntity: updateEntity, 441 /** 442 * 将传入的数值保留两位小数后返回 443 */ 444 keep2DecimalPlace: (decimalValue) => { 445 if (!decimalValue || isNaN(decimalValue)) { 446 return decimalValue 447 } 448 return Math.round(decimalValue * 100) / 100 449 }, 450 /** 451 * 读取服务器时间 452 */ 453 getServerTime: () => { 454 var xhr = null; 455 if (window.XMLHttpRequest) { 456 xhr = new window.XMLHttpRequest(); 457 } else { // ie 458 xhr = new ActiveObject("Microsoft") 459 } 460 xhr.open("GET", "/", false)//false不可变 461 xhr.send(null); 462 return new Date(xhr.getResponseHeader("Date")) 463 }, 464 /** 465 * 判断当前窗体是不是新建窗口 466 */ 467 isCreateForm: () => { return Xrm.Page.ui.getFormType() === 1 }, 468 /** 469 * 判断当前窗体是不是编辑窗口 470 */ 471 isUpdateForm: () => { return Xrm.Page.ui.getFormType() === 2 }, 472 /** 473 * 判断对象是否为字符串 474 */ 475 isString: (obj) => { return Object.prototype.toString.call(obj) === "[object String]" }, 476 /** 477 * 读取查询类型属性的id 478 */ 479 getLookupId: (fieldName) => { 480 let attribute = Xrm.Page.getAttribute(fieldName) 481 if (!attribute) { 482 Xrm.Utility.alertDialog(`不存在的属性【${fieldName}】,请传入正确的属性名`) 483 return; 484 } 485 let fieldType = attribute.getAttributeType() 486 if (fieldType !== 'lookup') { 487 Xrm.Utility.alertDialog(`属性【${fieldName}】不是查找类型的字段,不可使用getLookupId方法`) 488 return 489 } 490 let lookupValue = attribute.getValue() 491 return lookupValue ? lookupValue[0].id : null 492 }, 493 /** 494 * 读取查询类型属性的name 495 */ 496 getLookupName: (fieldName) => { 497 let attribute = Xrm.Page.getAttribute(fieldName) 498 if (!attribute) { 499 Xrm.Utility.alertDialog(`不存在的属性【${fieldName}】,请传入正确的属性名`) 500 return; 501 } 502 let fieldType = attribute.getAttributeType() 503 if (fieldType !== 'lookup') { 504 Xrm.Utility.alertDialog(`属性【${fieldName}】不是查找类型的字段,不可使用getLookupName方法`) 505 return 506 } 507 508 let lookupValue = attribute.getValue() 509 return lookupValue ? lookupValue[0].name : null 510 }, 511 /** 512 * 设置Lookup类型的值 513 * @param {any} LookupAttribute lookup控件字段名 514 * @param {any} Type 实体类型 515 * @param {any} Id 设置值的Guid 516 * @param {any} Name 值 显示名称 517 */ 518 setLookupValue: (LookupAttribute, Type, Id, Name) => { 519 var lookupReference = []; 520 lookupReference[0] = {}; 521 lookupReference[0].id = Id; 522 lookupReference[0].entityType = Type; 523 lookupReference[0].name = Name; 524 Xrm.Page.getAttribute(LookupAttribute).setValue(lookupReference); 525 }, 526 /** 527 * 取得登录角户角色 528 */ 529 GetRoleNames: () => { 530 let roleNames = []; 531 let userId = Xrm.Page.context.getUserId(); 532 let queryUrl = `/systemusers(${commonUtil.delBrackets(userId)})?$select=fullname&$expand=systemuserroles_association($select=name)` 533 commonUtil.queryWithUrl(queryUrl, (result) => { 534 if (result.success) { 535 result.data.systemuserroles_association.forEach(r => { 536 roleNames.push(r.name); 537 }) 538 } 539 }, false) 540 return roleNames; 541 }, 542 /** 543 * 设置表单所有控件不可编辑 544 */ 545 DisableALLControls: () => { 546 Xrm.Page.ui.controls.forEach(function (control, index) { 547 if (controlIsAttribute(control)) { 548 control.setDisabled(true); 549 } 550 }) 551 }, 552 /** 553 * 删除传入字符串首尾的{} 554 */ 555 delBrackets: (str) => { 556 if (!str) { 557 return str; 558 } 559 return str.replace(/^\{|\}$/g, "").toUpperCase(); 560 }, 561 distinctArr: (arr, distinctKey) => { 562 const result = [] 563 if (!arr || !arr.length) { 564 return result 565 } 566 const obj = {} // 标识是否存在相同的唯一标识 567 for (item of arr) { 568 if (!obj[distinctKey ? item[distinctKey] : item]) { 569 result.push(item) 570 obj[distinctKey ? item[distinctKey] : item] = true 571 } 572 } 573 574 return result 575 }, 576 /** 577 * 获取实体ObjectTypeCode 578 */ 579 getObjectTypeCode: ()=> { 580 var url = $("#crmContentPanel", window.top.document).attr("src"); 581 var index = url.indexOf("etc="); 582 var objectTypeCode = url.substring(index + 4, index + 9); 583 return objectTypeCode 584 }, 585 /** 586 * 获取数据Id 587 * @param {any} type 当前页面:0主页面 1子页面 2关联视图 588 */ 589 getId: (type) =>{ 590 var id = ""; 591 switch ((type == null || type == "") ? 0 : type) { 592 case 0://主页面获取 593 id = Xrm.Page.data.entity.getId(); 594 break; 595 case 1://从子页面获取 596 id = Xrm.Page.context.getQueryStringParameters()._CreateFromId; 597 break; 598 case 2://从关联视图页面获取 599 id = Xrm.Page.context.getQueryStringParameters().id; 600 break; 601 } 602 return commonUtil.delBrackets(id); 603 }, 604 /** 605 * 通过实体id获取实体数据 606 */ 607 getEntityData: getEntityData, 608 /** 609 * 通过查询url获取相关实体数据 610 */ 611 getEntityDatas: getEntityDatas, 612 /** 613 * 在URL中解析ID 614 */ 615 getIdFromUrl: getIdFromUrl, 616 /* 617 * 解析URL传入的参数 618 * (自定义页面可用) 619 */ 620 parseParams: parseParams, 621 /* 622 * 打开弹窗(自定义页面) 623 */ 624 openDialog: openDialog, 625 /* 626 * 获取当前环境 627 */ 628 getEnvironment: getEnvironment, 629 /** 630 * 激活按钮隐藏 631 */ 632 isDisplayActivate: () => { 633 return false; 634 }, 635 /** 636 * 停用按钮隐藏 637 */ 638 isDisplayDeactivate: () => { 639 return false; 640 }, 669 /** 670 * 获取用户Id 671 */ 672 GetUserId: () => { 673 var id = Xrm.Page.context.getUserId(); 674 id = id.toString().replace("{", "").replace("}", ""); 675 676 return id; 677 } 678 } 679 })()