UNPKG

infly-libs

Version:

工具组件库

1,693 lines (1,653 loc) 229 kB
// import { createHashHistory } from "history"; // import EventApi from "@module/EventApi"; // import Filter from "./Filter.js"; // import CacheRequest from "@root/Tools/cacheTool/CacheRequest.js"; // import MigrateTools from "@root/Tools/MigrateTools/MigrateTools.js"; // import StateApi from "./StateApi"; // const _history = createHashHistory(); // console.log(_history); let _getItem = Storage.prototype.getItem; // import Uts from "./Uts"; let $state = { name: "", params: {}, search: "", preName: "", preParams: {}, preState: {}, state: {}, setPreName: function(value) { this.preName = value; }, getPreName: function() { return this.preName; }, setPreParams: function(value) { this.preParams = value; }, getPreParams: function() { return this.preParams; }, setStateName: function(value) { this.setPreName(this.name); this.name = value; }, setParams: function(value) { this.setPreParams(this.params); this.params = value; }, getStateName: function() { return this.name; }, getParams: function() { return this.params; }, setState: function(value) { this.State = value; }, getState: function() { return this.State; }, setSearch: function(value) { this.search = value; }, go: function(options) { global.Uts.$stateGo(options); }, to: function(path) { global.Uts.$stateTo(path); } }; global.$state = $state; /** * @noIndex 通用工具方法 Uts */ let Uts = { migrateRequestUrlConfig: {}, testDomain: "https://www.test.rj-info.com", publishDomain: "https://www.rjmart.cn", /** * console.log one error 控制台打印错误信息 * @module message * @todo Uts.ce * @param text text to console output * @return {type} * @example * Uts.ce('请检查配置'); */ ce(text) { global.console.error && global.console.error(text); }, /** * set class 动态设置类名 * @module condition * @todo Uts.sc * @param {array} options the expression to set class * @return {string} the className result * @example Uts.sc([ formData.$$status.test1 ? "a" : "b", "hello world" ]) */ sc(arr) { if (this.notEmptyArray(arr)) { return arr.join(" "); } }, /** * throw one error ,显示JS默认错误源追溯 * @module errorCatch * @todo Uts.te * @param {string} text * @return {type} * @example * Uts.te('error info') * */ te(text) { throw new Error(text); }, /** * 判断是否为真 * @module checkType * @todo Uts.isTrue * @param {value} value 要检测的值 * @return {Boolean} * @example * Uts.isTrue('a') true */ isTrue(value) { return Boolean(value); }, cleanStateScope() { let innerState = global.$state; if (innerState) { innerState.autoState = {}; // delete innerState.autoState; } }, /** * 当前页面自动状态维护(页面切换后会自动清空,当前页面通用,跨越所有的组件层级通讯) * @module stateStore * @todo Uts.setAutoState * @param {string} name 路由状态的名字 * @param {object} value 路由状态的值 * @example * Uts.setAutoState('pageConfig',{a:1}) //Uts.getAutoState('pageConfig') 会获取到{a:1} */ setAutoState(name, value) { let innerState = global.$state; if (innerState) { innerState.autoState[name] = value; // delete innerState.autoState; } }, /** * 获取当前页面自动状态(页面切换后会自动清空,当前页面通用) * @module stateStore * @todo Uts.getAutoState * @param {string} name 路由状态的名字 * @example * Uts.getAutoState('pageConfig') //获取到Uts.setAutoState('pageConfig',xxx)的值 */ getAutoState(name) { let innerState = global.$state; if (innerState) { return innerState.autoState[name]; // delete innerState.autoState; } }, /** * 切换语言 * @module runEnv * @todo Uts.changeLanguage * @param {string} type 语言类型,正常为:cn/en * @param {string} site 站点 如:bio/lab * @example * Uts.changeLanguage('cn','bio'); */ changeLanguage(type, site) { //type: cn en let languageConfig = { bio: { typeName: "BIOLANGUAGE", cookieName: "bioLanguage", functionName: "bioLanguageChange" }, lab: { typeName: "LABLANGUAGE", cookieName: "labLanguage", functionName: "labLanguageChange" } }; Uts[languageConfig[site].typeName] = type; Uts.setCookie(languageConfig[site].cookieName, type, { expires: 365 }); //因为token过期会导致翻译有问题,所以默认设置有效期为一年 // EventApi.emit(languageConfig[site].functionName, type); /*Uts.BIOLANGUAGE = type; Uts.setCookie("bioLanguage", type); EventApi.emit("bioLanguageChange", type);*/ }, /** * 获取www域名下的静态文件地址 * @module runEnv * @todo Uts.getWwwFile * @param {string} fileUrl 文件的相对目录 * @return {string} 文件的绝对地址 * @example * Uts.getWwwFile('imgs/index_origine5575.png'); 'https://www.rjmart.cn/imgs/index_origine5575.png' * */ getWwwFile(fileUrl, isOldPurchaserSite) { let startStr = "/"; let currentOrigin = Uts.getOrigin(); let currentEnv; if (Uts.startWith(fileUrl, "/")) { startStr = ""; } if (Uts.isDevMode()) { let localDirectory = Uts.TR(!isOldPurchaserSite, "/RJReact/OLD_WEB", "/fe-old-purchaser"); return currentOrigin + localDirectory + startStr + fileUrl; } else { if (isOldPurchaserSite) { startStr = "/purchaser" + startStr; } let wwwSiteOrigin = currentOrigin; let regWithThirdLevelDomain = /www\.[^\.]+\.rjmart/; // 如果非门户域名,转换为对应环境门户域名 if (!/\/www\./.test(currentOrigin)) { wwwSiteOrigin = currentOrigin.replace(/\/[^\.]+\./, "//www."); } if (/renlab\.cn/.test(wwwSiteOrigin)) { if (Uts.getEnv().env == "test") { wwwSiteOrigin = Uts.testDomain; } else { wwwSiteOrigin = Uts.publishDomain; } } // 如果是rj-info.com 但没有test,加上test if (Uts.contain(wwwSiteOrigin, "rj-info\\.com") && !Uts.contain(wwwSiteOrigin, "test\\.")) { wwwSiteOrigin = wwwSiteOrigin.replace("www.", "www.test."); currentEnv = "test"; } else if (Uts.contain(wwwSiteOrigin, "rjmart\\.cn") && regWithThirdLevelDomain.test(wwwSiteOrigin)) { wwwSiteOrigin = wwwSiteOrigin.replace(regWithThirdLevelDomain, "www.rjmart"); currentEnv = "publish"; } // 如果域名大于4个.,需要去掉多余 let splitSymbol = "."; let originArr = wwwSiteOrigin.split(splitSymbol); let originArrLength = originArr.length; let validCount = Uts.TR(currentEnv == "publish", 3, 4); if (originArrLength > validCount) { let startCount = Uts.TR(currentEnv == "publish", 1, 2); originArr.splice(startCount, originArrLength - validCount); wwwSiteOrigin = originArr.join(splitSymbol); } /* https://www.test.rj-info.com/purchaser/ZenIconImg/GreyFile.png 外网时转到 http://xyeyy.rjmart.net/purchaser/ZenIconImg/GreyFile.png */ if (Uts.getEnv().env == "external") { wwwSiteOrigin = currentOrigin; } else { // 强制转https,防止非http域名加载不出图片 if (!Uts.startWith(wwwSiteOrigin, "https")) { wwwSiteOrigin = wwwSiteOrigin.replace(/^http:/, "https:"); } } return wwwSiteOrigin + startStr + fileUrl; } }, hookBeforeStateChange(loc, action) {}, /** * navigage to new path * @param {string} path the path to navigage * @return {string} * @example const path = `/repos/${userName}/${repo}`; $stateGo(path); */ $stateTo(path) { //<Redirect to="/somewhere/else" /> /* <Redirect to={{ pathname: "/login", search: "?utm=your+face", state: { referrer: currentLocation } }} /> */ // $state; // const path = `/repos/${userName}/${repo}` // browserHistory.push(path); //return <Redirect to={path} />; if (Uts.checkShouldRemoveHash()) { Uts.routeByCacheHash(path); } else { // _history.push(path); Uts.autoPreFixedParams(); } }, /** * navigage to new path,应用内跳转,跨应用跳转用Uts.routeToDomain * @module route * @todo $state.go * @param {object} options 跳转配置对象 包含name及params,注意,name的值以/开始时,为绝对路由跳转,不以/开始,表示为相对路由跳转 * @example * $state.go({name:"/detail",params:{id:982388}}) //此时会跳转到#detail?id=982388 */ $stateGo(options) { let routerObject = { pathname: options.stateName || options.name, //"/login", search: Uts.paramsToSearch(options.params), //"?utm=your+face", state: options.state // basename: Uts.cachePathname }; //<Redirect to="/somewhere/else" /> /* <Redirect to={{ pathname: "/login", search: "?utm=your+face", state: { referrer: currentLocation } }} /> */ // const path = `/repos/${userName}/${repo}` if (options.reload) { routerObject = routerObject.pathname + routerObject.search; } if (options.target == "_blank") { let hostAndPath = Uts.getPartStringBySymbolIndex(location.href, "#", 0, 1); if (Uts.checkShouldRemoveHash()) { hostAndPath = Uts.cacheUrlBeforeHash; } let url = hostAndPath + "#" + routerObject.pathname; Uts.href(url + routerObject.search, options.target); } else { if (Uts.checkShouldRemoveHash()) { let subfix = ""; if (routerObject.search) { subfix = routerObject.search; if (!Uts.startWith(routerObject.search, "\\?")) { subfix = "?" + subfix; } } Uts.routeByCacheHash(routerObject.pathname + subfix); } else { // _history.push(routerObject); Uts.autoPreFixedParams(); } } }, /** * loop for array,遍历对象数组或字符串数组 * @module loop * @todo Uts.each * @param {type} arr 要遍历的数组 * @param {Function} cb 每个遍历执行的回调,参数依次为数组内的单个item及index、run对象(如需终止循环,执行run.stop即可) * @return {type} *@example Uts.each(array,function(item,index){}); */ each(arr, cb) { let runTimeConfig = {}; if (this.isArray(arr) && cb) { for (var i = 0; i < arr.length; i++) { if (this.pauseEach || runTimeConfig.stop) { break; } cb && cb(arr[i], i, runTimeConfig); } delete this.pauseEach; } }, /** * loop for object 对象遍历 * @module loop * @todo Uts.objEach * @param {object} object 要遍历的对象 * @param {Function} cb 每个遍历执行的回调,参数一次为当前value及key * @return {type} *@example Uts.objEach(object,function(item,index){}); */ objEach(obj, cb) { if (Uts.isFunction(cb)) { // for (let key in obj) { let keys = Uts.getObjectKeys(obj); Uts.each(keys, function(key, index, run) { let shouldStop = cb(obj[key], key, run); if (shouldStop) { Uts.pauseEach = true; } }); // } } else { return Uts.isPureObject(obj) && Uts.getObjectKeys(obj); } }, /** * 单纯遍历数组 * @noIndex loop * @todo Uts.loop * @param {array} similarArr * @param {Function} cb * @param {Object} currentLoop * @return {null} */ loop(similarArr, cb, currentLoop = {}) { if (Uts.isFunction(cb)) { for (var i = 0; i < similarArr.length; i++) { if (currentLoop.break) { break; } if (currentLoop.continue) { continue; } cb && cb(similarArr[i], i); } } }, /** * daysInMonth 获取当前月份有多少天 * @module date * @todo Uts.daysInMonth * @param {dateStr} String || Date 支持日期字符串及日期对象 * @param {symbol} String 日期格式的分隔符,默认为- * return Number 天数 * @example * Uts.daysInMonth('2022-07-22') */ daysInMonth(dateStr, symbol = "-") { if (Uts.isDate(dateStr)) { dateStr = dateStr.ZenFormat("Y-m-d"); } let dayConArr = dateStr.split(symbol); let year = Number(dayConArr[0]); let month = Number(dayConArr[1]); let days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; if (year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) { days[1] = 29; } return days[month - 1]; }, /** * getWeek 获取某个日期的星期值 * @module date * @todo Uts.getWeek * @param {dateStr} String || Date 日期,支持日期字符串及日期对象 * return Number 星期几 * @example * Uts.getWeek('2022-07-22') */ getWeek(dateStr) { let dateObj; let week; if (dateStr) { if (Uts.isDate(dateStr)) { dateObj = dateStr; } else { dateObj = new Date(dateStr.replace(/-|_|——/g, "/")); } week = dateObj.getDay(); if (week == 0) { week = 7; } } return week; }, /** * getDayStamp 获取日期的当天的开始或者结束时间戳 * @module date * @todo Uts.getDayStamp * @param {dateStr} String || Date 日期 * @param {type} Number 时间戳类型 0 开始时间,1结束时间 * @return {number} 时间戳 * @example //获取开始时间 00:00:00: getDayStamp('2021-01-20') //获取结束时间 23:59:59: getDayStamp('2021-01-27',1) */ // 为什么写这么个这么麻烦的方法呢,因为 Uts.formatDate(new Date("2021-06-16"),'Y-m-d H:i:s') -- "2021-06-16 08:00:00" // new Date("2021-06-16") 初始化的时间会自动加上8小时。这时候getTime()所得的时间戳就有问题了 getDayStamp: (dateStr, type = 0) => { let dateObj; let endFlag = type == 1; if (dateStr) { if (Uts.isDate(dateStr)) { dateObj = dateStr; } else { dateObj = new Date(dateStr.replace(/-|_|——/g, "/")); } } dateObj.setHours(endFlag ? 23 : 0); //设置小时 dateObj.setMinutes(endFlag ? 59 : 0); //设置分钟 dateObj.setSeconds(endFlag ? 59 : 0); //设置秒 dateObj.setMilliseconds(endFlag ? 999 : 0); //设置毫妙 let timestamp = dateObj.getTime(); //获取毫秒时间戳 return timestamp; }, /** * getNumDayBefore 获取多少天前的日期时间戳,默认当前日期为基准。默认获取30天前的日期 * @module date * @todo Uts.getNumDayBefore * @param {num} Number 天数 * @param {dateStr} String || Date 日期,支持日期字符串及日期对象 * @example * Uts.getNumDayBefore(30,'2022-07-21') 1655740800000 Filter.formatDate(1655740800000,'Y-m-d') '2022-06-21' */ getNumDayBefore: (num = 30, dateStr) => { let now = Uts.getDayStamp(new Date()); // 这里获取0点的当前日期时间戳 let numDayTimeStamp = num * 24 * 60 * 60 * 1000; if (dateStr) { if (Uts.isDate(dateStr)) { now = Uts.getDayStamp(dateStr); } else { now = Uts.getDayStamp(new Date(dateStr.replace(/-|_|——/g, "/"))); } } return now - numDayTimeStamp; }, /** * 把数组转为字符串,注意与Array.join的区别为默认.号,非默认;号,默认返回空字符串 * @module processArray * @todo Uts.join * @param {array} arr 需要转换的数组 * @param {string} symbol 符号 * @return {string} 返回字符串结果,默认空字符串 * @example * Uts.join(['someList',2,"name"]) 'someList.2.name' Uts.join() '' */ join(arr = [], symbol = ".") { if (Uts.notEmptyArray(arr)) { return arr.join(symbol); } else { return ""; } }, /** * 根据传入的length,生成对应长度的数组,默认为空值数组,可传入第二个参数生成索引值数组 * @module processArray * @todo Uts.generateArray * @param {num} Number 数组长度 * @param {boolean} 数组单个值是否为空 * @example * Uts.generateArray(5) //[empty × 5] Uts.generateArray(5,true) [0, 1, 2, 3, 4] */ generateArray: (length, notEmpty) => { let arr = new Array(length); if (!notEmpty) { return arr; } else { let newArr = []; Uts.each(arr, function(item, index) { newArr.push(index); }); return newArr; } }, /** * 把对象转换为url式查询 * @module processObject * @todo Uts.paramsToSearch * @param {custom} param 要转换的对象 * @param {custom} key 单个额外的key * @param {custom} encode * @param {custom} ifDeepMode * @param {custom} firstTime * @return {custom} * @example * Uts.paramsToSearch({name:"zhangsan",id:29,department:"生物研究"}) '?name=zhangsan&id=29&department=生物研究' */ paramsToSearch(param, key, encode, ifDeepMode, firstTime) { if (param == null) return ""; var paramStr = ""; var t = typeof param; if (ifDeepMode) { var encodeStr = this.copyObj(param); if (Uts.isObject(encodeStr)) { encodeStr = Uts.toStr(encodeStr); } if (!this.ifHadEncode(encodeStr)) { encodeStr = encodeURIComponent(encodeStr); } var flagSymbol = firstTime ? "?" : "&"; paramStr += flagSymbol + key + "=" + (encode == null || encode ? encodeStr : param); } else { var firstTime = true; for (var i in param) { var k = key == null ? i : key + (param instanceof Array ? "[" + i + "]" : "." + i); paramStr += Uts.paramsToSearch(param[i], k, encode, true, firstTime); firstTime = false; } } return paramStr; }, /** * 判断非空字符串 * @module checkType * @todo Uts.notEmptyString * @param {string} string * @return {boolean} true或空字符串 * @example * Uts.notEmptyString('e') true Uts.notEmptyString('') '' */ notEmptyString(string) { return string && this.isString(string); }, /** * 判断非空数组 * @module checkType * @todo Uts.notEmptyArray * @param {array} array 要检查的数组 * @return {boolean} 检查结果 布尔值 * @example * Uts.notEmptyArray([123]) true Uts.notEmptyArray([]) false */ notEmptyArray(arr) { return arr && arr.length > 0 && this.isArray(arr); }, /** * 合并数组(改变原数组,默认合并的数组在前面) * @module processArray * @todo Uts.pushArray * @param {array} rawArr 原数组 * @param {array} pushArr 要把值合并进来的数组 * @param {number} position 合并起始位置,默认为0 * @return {array} 值发生改变后的原数组 * @example * Uts.pushArray([1,2,3],[59]) [59, 1, 2, 3] Uts.pushArray([1,2,3],[59],3) [1, 2, 3, 59] */ pushArray(rawArr, pushArr, ps = 0) { if (Uts.isArray(rawArr) && Uts.isArray(pushArr)) { rawArr.splice(ps, 0, ...pushArr); return rawArr; } }, /** * 合并数组(改变原数组,默认合并的数组在后面) * @module processArray * @todo Uts.mergeArray * @param {array} rawArr 原数组 * @param {array} valueArray 要把值合并进来的数组 * @example * var arr1=[1,2,3]; Uts.mergeArray(arr1,[8,9]); console.log(arr1) [1, 2, 3, 8, 9] */ mergeArray(rawArr, valueArray) { if (this.isArray(rawArr) & this.notEmptyArray(valueArray)) { Array.prototype.push.apply(rawArr, valueArray); } }, /** * 数组随机排序(生成新数组,不改变原数组) * @module processArray * @todo Uts.randomOrder * @param {array} valueArray 数组 * @example * var arr1=[1,2,3,4,5,6,7,8,9]; Uts.randomOrder(arr1); [8, 5, 4, 7, 2, 6, 9, 1, 3] */ randomOrder(valueArray) { let loopTime = valueArray.length - 1; let startCount = loopTime; let newArray = []; while (startCount >= 0) { let newestLength = valueArray.length - 1; if (startCount > 0) { let randomValue = Uts.random(0, newestLength); newArray.push(valueArray[randomValue]); valueArray.splice(randomValue, 1); } else { newArray.push(valueArray[startCount]); } startCount--; } return newArray; }, /** * 合并数组(返回新数组,不改变原数组,与Array.prototype.concat一致) * @module processArray * @todo Uts.concat * @param {array} rawArr 原数组 * @param {array} valueArray 要把值合并进来的数组 * @return {array} newArray 返回新数组 * @example * var arr1=[1,2,3]; var newArr=Uts.concat(arr1,[8,9]); //返回的新数组 console.log(newArr) [1, 2, 3, 8, 9] //原数组不变 console.log(arr1) [1, 2, 3] */ concat(rawArr, valueArray) { if (Uts.notEmptyArray(rawArr)) { return rawArr.concat(valueArray); } else { return valueArray; } }, /** * 自动去重合并数组(返回新数组) * @module processArray * @todo Uts.mergeArrayWithoutDuplicate * @param {array} rawArr 原数组 * @param {array} valueArray 要把值合并进来的数组 * @return {object} object 配置对象 * @example * //合并对象数据 Uts.mergeArrayWithoutDuplicate([{id:9,name:"test9"},{id:11}],[{id:9,name:"test9"},{id:10,name:"test10"}]); [ { "id": 9, "name": "test9" }, { "id": 11 }, { "id": 10, "name": "test10" } ] //合并字符串或数字数组 Uts.mergeArrayWithoutDuplicate([1,2,3,4,5,6],[9,3,3,2,1]) [1, 2, 3, 4, 5, 6, 9] */ mergeArrayWithoutDuplicate(rawArr, valueArray, config = {}) { const { key = "id" } = config; let notDuplicateObj = {}; let concatArray = Uts.concat(rawArr, valueArray); let resultArray = []; Uts.each(concatArray, function(item, index) { let notDuplicateKey = item; if (Uts.isPureObject(item)) { notDuplicateKey = item[key]; } if (!notDuplicateObj[notDuplicateKey]) { resultArray.push(item); notDuplicateObj[notDuplicateKey] = true; } }); return resultArray; }, /** * 数组前置插入数组(改变原数组,默认合并的数组在最前面) * @module processArray * @todo Uts.unshiftArray * @param {array} rawArr 原数组 * @param {array} valueArray 要把值合并进来的数组 * @example * var arr1=[1,2,3]; Uts.unshiftArray(arr1,[8,9]); console.log(arr1); [8, 9, 1, 2, 3] */ unshiftArray(rawArr, valueArray) { if (this.isArray(rawArr) & this.notEmptyArray(valueArray)) { Array.prototype.unshift.apply(rawArr, valueArray); } }, overrideCookieName: function(cookieName, isSet) { return cookieName; let currentProject = Uts.getCurrentProject(); let exceptProject = { omsLoginToken: true, SPAccrosToken: true, examLoginToken: true }; if (Uts.tokenNameConfigFetch[cookieName] && !exceptProject[cookieName]) { // 如果为临时用户,且在采购门户,不允许访问全局token // Uts.currentSecondDomain === '' 本地开发 if ( !isSet && Uts.getCookie("userToken") && Uts.contain(["www", "school"], currentProject) && (Uts.contain(["www", "school"], Uts.currentSecondDomain) || Uts.currentSecondDomain === "") ) { return "tokenNotExistForTempUser"; } return Uts.tokenNameConfig.www; } else { return cookieName; } }, /** * get cookie by name,根据名字获取对应cookie值 * @module cookieStorage * @todo Uts.getCookie * @param {string} cookie name * @return {string} cookie value * @example * Uts.getCookie('labLanguage') 'cn' */ getCookie(cookieName) { cookieName = Uts.overrideCookieName(cookieName); /*var name = cookieName + "="; var ca = document.cookie.split(";"); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == " ") { c = c.substring(1); } if (c.indexOf(name) == 0) { return Uts.decode(c.substring(name.length, c.length)); } }*/ let matchResult = new RegExp("(^| )" + cookieName + "=([^;]+)").exec(document.cookie); if (Uts.notEmptyArray(matchResult)) { return Uts.decode(matchResult[2]); } else { return ""; } // return || ""; // return ""; }, /** * setCookie by name and value 设置cookie值 * @module cookieStorage * @todo Uts.setCookie * @param {string} cname 要设置的cookie名字 * @param {string} cvalue 要设置的cookie值 * @param {object} 配置对象 * @example * setCookie('labLanguage', 'en', { expires: 3650 }); */ setCookie(cname, cvalue, options = {}) { if (Uts.isUndefined(cvalue)) { return false; } let isHttps = location.protocol.indexOf("https:") > -1; cname = Uts.overrideCookieName(cname, true); var d = new Date(); options.path = "/"; var hostname = location.hostname; if (!options.domain) { if (Uts.isDevMode() || Uts.startWith(hostname, "[1-9]")) { options.domain = hostname; } else { options.domain = hostname.substring(hostname.indexOf("."), hostname.length); } } options.expires = options.expires || 0.32; if (typeof options.expires === "number") { var days = options.expires, t = (options.expires = new Date()); t.setTime(+t + days * 864e5); } let newFeature = ""; if (isHttps) { // newFeature = "; SameSite=None"; } // d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); // var expires = "expires="+d.toUTCString(); document.cookie = cname + "=" + Uts.encode(cvalue) + ";path=" + options.path + (options.domain ? "; domain=" + options.domain : "") + (options.expires ? "; expires=" + options.expires.toUTCString() : "") + newFeature + (isHttps ? "; secure" : ""); }, /** * 移除某个cookie值 * @module cookieStorage * @todo Uts.removeCookie * @param {string} cname 要移除的cookie名 * @param {Object} options 配置对象 如path/domain等 * @example * Uts.removeCookie('labLanguage') */ removeCookie(cname, options = {}) { let cvalue = ""; if (!Uts.isPureObject(options)) { options = {}; } if (options.isCurrentDomain) { options.domain = location.hostname; } options.expires = -1; Uts.setCookie(cname, cvalue, options); }, isUI6Page: function(stateName) { let currentProject = Uts.getCurrentProject(); let hadUpdateUI6Project = ["pm", "srm", "ui"]; if (Uts.contain(hadUpdateUI6Project, currentProject)) { return true; } else { if (Uts.notEmptyArray(Uts.UI6PageLists)) { if (Uts.notEmptyString(stateName) && !Uts.startWith("/Login", "/")) { stateName = "/" + stateName; } stateName = stateName || $state.name; return Uts.contain(Uts.UI6PageLists, stateName); } } return false; }, copyCleanFormData: function(formData, options = {}) { const { filterMark = true } = options; let cleanFormData = {}; let markPropList = ["$$valid", "$$status"]; Uts.objEach(formData, function(value, key) { if (filterMark && Uts.contain(markPropList, Uts.safeRegString(key))) { return; } if (!/\./.test(key)) { // console.log("deleting ", key); cleanFormData[key] = value; } }); return cleanFormData; }, callLogout: function(callback) { callback = callback || function() {}; let ignoreProjectList = [ /*"oms", "sp"*/ ]; let currentProject = Uts.getCurrentProject(); if (!Uts.contain(ignoreProjectList, currentProject)) { let currentToken = Uts.getTokenForProject(); if (currentToken) { window.REST.global.login.action.baseLogout && window.REST.global.login.action.baseLogout({ accessToken: Uts.getTokenForProject() }, "dis").ok(callback); } } }, /** * 针对退出时,统一配置清除缓存及cookie(会根据配置默认保留部分cookie及缓存),通常在退出登录时调用一次 * @module cookieStorage * @param {custom} 不需要参数 * @todo Uts.clearCacheForLogout * @example * Uts.clearCacheForLogout() */ clearCacheForLogout() { let shouldKeepStandloneSite = ["exam", "srs", "bio", "lab"]; //需要独立登录的在这加 let shouldKeepStandloneSiteCookie = ["examLoginToken", "srsLoginToken", "bioLoginToken", "labLoginToken"]; //需要独立登录的在这加 let keepCookieConfig = { keyCookie: ["omsLoginToken"] }; //非shouldKeepStandloneSite的站点退出的,应该保持shouldKeepStandloneSite的站点登录状态;还需要在Uts.js的ignoreToken方法添加 if (!($state.params.type == "logout" && Uts.contain(shouldKeepStandloneSite, $state.params.loginSite))) { keepCookieConfig.keyCookie = keepCookieConfig.keyCookie.concat(shouldKeepStandloneSiteCookie); } // 考試系統登錄時,保留門戶 if (Uts.contain(shouldKeepStandloneSite, $state.params.loginSite)) { keepCookieConfig.keyCookie.push("accrosToken"); } // Uts.callLogout(); Uts.clearAllCookiesAndStorage(keepCookieConfig); }, /** * 清除所有未配置保留的cookie及缓存(可配置不被清除的缓存及cookie), * 如果不知道如何配置保留项,不要轻易使用,请改使用Uts.clearCacheForLogout() * @module cookieStorage * @todo Uts.clearAllCookiesAndStorage * @param {Object} options * @return {null} * @example * Uts.clearAllCookiesAndStorage({ keyCookie: ["omsLoginToken", "labLanguage"] }); */ clearAllCookiesAndStorage(options = {}) { Uts.callLogout(); let formerToken = ""; let targetProject = Uts.getCurrentProject(); if (options && options.keepToken) { formerToken = Uts.getCookie("accrosToken") || Uts.getCookie("SPAccrosToken") || Uts.getCookie("omsLoginToken") || ""; } var cookieDomain = window.location.protocol.indexOf("https:") > -1 ? { path: "/", secure: true } : { path: "/" }; var h = location.hostname; cookieDomain.domain = h.indexOf("localhost") < 0 && !/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test( h ) ? h.substring(h.indexOf("."), h.length) : location.hostname; cookieDomain.expires = -1; let cookiesMap = Uts.cookiesMap(); let _self = this; let secondDomain = Uts.copyObj(cookieDomain); secondDomain.domain = location.host; Object.keys(cookiesMap).forEach(key => { if (!Uts.contain(Uts.keeyCookieWhenLogOut, key) && !Uts.contain(options.keyCookie, key)) { _self.setCookie(key, "", cookieDomain); _self.setCookie(key, "", secondDomain); _self.setCookie(key, "", { secure: true, expires: -1 }); } }); let keepStore = Uts.ifKeepStoreList(); localStorage.clear(); sessionStorage.clear(); delete cookieDomain.expires; if (keepStore) { Uts.rebackStoreList(); if (Uts.isObject(keepStore)) { Uts.objEach(keepStore, function(item, index) { sessionStorage.setItem(index, keepStore[index]); }); } } if (formerToken && options && options.keepToken) { Uts.setCookie("FORMERTOKEN", formerToken); } }, EVERYDAYCACHE: "EveryDayArr", /** * 根据缓存名获取有效期为当天的缓存值,默认第二天会失效自动删除 * @module cookieStorage * @todo Uts.getTodayCache * @param {string} storageKey 要读取的缓存名 * @return {value} 返回已设置的缓存值 * @example * Uts.setTodayCache('userInfo',{name:'zhangsan'}) Uts.getTodayCache('userInfo') {name: 'zhangsan'} */ getTodayCache: function(storageKey) { let cacheValue = storage.get(Uts.EVERYDAYCACHE); if (cacheValue) { return cacheValue[storageKey]; } }, /** * 根据缓存名设置有效期为当天的缓存值,默认第二天会失效自动删除 * @module cookieStorage * @todo Uts.setTodayCache * @param {string} storageKey 要设置的缓存名 * @param {value} valueToSet 要设置缓存值 * @example * Uts.setTodayCache('userInfo',{name:'zhangsan'}) */ setTodayCache: function(storageKey, valueToSet = true) { let limitTime = new Date().addDay(1).ZenFormat("Y-m-d") + " 00:00:00"; let cacheValue = storage.get(Uts.EVERYDAYCACHE) || {}; cacheValue[storageKey] = valueToSet; storage.set(Uts.EVERYDAYCACHE, cacheValue, limitTime); }, //判断是否自动登录 isAutoLogin(loginCb, _loginSite) { let loginSite = _loginSite || $state.params.loginSite || "www"; let autoLoginInfo = Uts.storage.get("autoLoginInfo") || { www: {}, oms: {}, hms: {} }; if (autoLoginInfo[loginSite] && autoLoginInfo[loginSite].autoLogin) { if (!(autoLoginInfo[loginSite].created > Uts.now("2020/12/23 18:35:00"))) { Uts.storage.set("autoLoginInfo", ""); } else { if (Uts.now() - autoLoginInfo[loginSite].lastAutoLoginTime < 60 * 1000) { //1分钟内不允许反复自动登录 Uts.storage.set("autoLoginInfo", ""); return false; } autoLoginInfo[loginSite].lastAutoLoginTime = Uts.now(); loginCb(autoLoginInfo[loginSite]); } } }, //返回能否自动登录 getAutoLoginInfo: function(_loginSite) { let loginSite = _loginSite || $state.params.loginSite || "www"; let autoLoginInfo = Uts.storage.get("autoLoginInfo") || { www: {}, oms: {}, hms: {} }; if (Uts.getCookie("autoLoginInfo") && JSON.parse(Uts.getCookie("autoLoginInfo"))) { autoLoginInfo = JSON.parse(Uts.getCookie("autoLoginInfo")); } let autoInfo = {}; loginSite = Uts.getAutoLoginProject(loginSite); if (autoLoginInfo[loginSite] && autoLoginInfo[loginSite].autoLogin) { autoInfo = autoLoginInfo[loginSite]; } return autoInfo; }, ifKeepStoreList() { let result = false; if (Uts.keepStoreListWhenLogOut && Uts.keepStoreListWhenLogOut.length > 0) { let list = Uts.keepStoreListWhenLogOut; Uts.saveTempStoreList(list); result = true; } if (Uts.autoKeepSessionWhenLogOut && Uts.autoKeepSessionWhenLogOut.length > 0) { let resultObj = {}; Uts.each(Uts.autoKeepSessionWhenLogOut, function(item, index) { resultObj[item] = sessionStorage.getItem(item); }); result = resultObj; } return result; }, saveTempStoreList(list) { let tempMaps = {}; list && list.map(item => { // let val = Uts.storage.get(item); let val = localStorage[item]; try { val = Uts.toJSON(val); } catch (err) {} tempMaps[item] = val; }); Uts.tempMaps = tempMaps; }, rebackStoreList() { let tempMaps = Uts.tempMaps; let keys = Object.keys(tempMaps); keys && keys.map(key => { let value = tempMaps[key]; let expires = 0; if (Uts.isPureObject(value)) { if (value.expires) { expires = Uts.formatDate(value.expires, "Y-m-d H:i:s"); } value = value.value; } Uts.storage.set(key, value, expires); }); }, /** * 匹配高亮文本(支持html)中的多个关键词,支持嵌套 * @module processString * @todo Uts.highlightKeyWord * @param {String} str 要处理的html * @param {Array} keywordList 关键词数组 * @param {Object} config 配置对象,tag用于配置标签,默认为span,className配置类名,默认zen_red * @return {string} 高亮后的完整html * @example * Uts.highlightKeyWord("<span class='test'>广州锐竞信息科技有限责任公司</span>",['广州','锐竞', '广州锐竞']); "<span class='zen_red'><span class='zen_red'><span class='test'>广州<span class='zen_red'></span>锐竞</span></span>信息科技有限责任公司</span>" */ highlightKeyWord: function(str = "", keywordList = [], config = {}) { const { tag = "span", className = "zen_red", onMatch } = config; // let startWord = "#####"; let startWord = "<" + tag + " class='" + className + "'>"; let startWordReg = "< ?[^>]+>"; // let endWord = "$$$$$"; let endWord = "</" + tag + ">"; let endWordReg = "</ ?w+>"; // let startWordReg = new RegExp(startWord, "g"); // let endWordReg = new RegExp(endWord.replace(/(.)/g, "\\$1"), "g"); // let endWordReg = new RegExp(endWord, "g"); let computeStr = str; if (Uts.isString(keywordList)) { keywordList = [keywordList]; } if (Uts.isArray(keywordList)) { Uts.each(keywordList, function(keyword, index) { if (Uts.notEmptyString(keyword)) { // let regStr = keyword.replace(/(.)/g, "([#$]{5,6}){0,}$1([#$]{5,6}){0,}"); let regStr = keyword.replace(/(.)/g, "(" + startWordReg + "){0,}$1(" + endWordReg + "){0,}"); let reg = new RegExp(regStr, "g"); computeStr = computeStr.replace(reg, function(partMatch, fullMatch) { if (Uts.isFunction(onMatch)) { return onMatch(partMatch, startWord, endWord); } else { return startWord + partMatch + endWord; } }); } }); // computeStr = computeStr.replace(endWordReg, "</" + tag + ">"); // computeStr = computeStr.replace(startWordReg, "<" + tag + " class='" + className + "'>"); } return computeStr; }, /** * 与Filter.formatDate同,格式化日期显示 * @module date * @todo Uts.formatDate * @param {date} date * @param {string} format * @return {string} * @example * Uts.formatDate(new Date(),'Y-m-d H:i:s') '2022-07-19 11:34:15' */ formatDate: function(date, format) { if (!date) { return false; } if (!Uts.isDate(date) && Uts.isString(date)) { date = new Date(date.replace(/-|_|——/g, "/")); } else if (Uts.isNumber(date)) { date = new Date(date); } return date.ZenFormat(format); }, /** * 安全url解码,代替decodeURIComponent方法 * @module changeCode * @todo Uts.decode * @param {string} str 要解码的字符串 * @return {string} 解码后的字符串 * @example * Uts.decode('%E6%B5%8B%E8%AF%95%E7%9A%84%E6%96%87%E6%9C%AC') '测试的文本' */ decode(s) { return decodeURIComponent(s); }, /** * 安全编码,代替的encodeURIComponent * @module changeCode * @todo Uts.encode * @param {string} str 要编码的字符串 * @return {string} 编码后的字符串 * @example * Uts.encode('测试的文本') '%E6%B5%8B%E8%AF%95%E7%9A%84%E6%96%87%E6%9C%AC' */ encode(s) { return encodeURIComponent(s); }, cookiesMap: function() { var cookies = document.cookie ? document.cookie.split("; ") : []; var result = {}; for (var i = 0, l = cookies.length; i < l; i++) { var parts = cookies[i].split("="); var name = Uts.decode(parts.shift()); var cookie = parts.join("="); result[name] = cookie; } return result; }, /** * 批量设置cookie值 * @module cookieStorage * @todo Uts.setCookieMt * @param {object} 配置 如:{useName:"abc",useId:123,useDeparment:"采购"} * @example setCookieMt({useName:"abc",useId:123,useDeparment:"采购"}); */ setCookieMt(options) { for (var pop in options) { Uts.setCookie(pop, options[pop]); } }, /** * getEnv 获取当前所在的环境(现网/测试/开发)及根域名(不带二级域名) * @module runEnv * @todo Uts.getEnv * @param {string} url 要判断的域名链接,默认为当前域名 * @return {object} * @example * //现网执行时: *Uts.getEnv() {rootDomain: 'rjmart.cn', env: 'publish'} //测试环境执行时 Uts.getEnv() {rootDomain: 'rj-info.com', env: 'test'} //开发环境执行时 Uts.getEnv() {rootDomain: 'localhost', env: 'localhost'} */ getEnv(string) { let config = {}; let host = string || location.host; config.rootDomain = (host.match(Uts.FINDDOMAINEXP) && host.match(Uts.FINDDOMAINEXP)[0]) || null; config.env = ""; switch (true) { case Uts.contain(host, "localhost:"): config.env = "localhost"; config.rootDomain = "localhost"; break; case Uts.contain(host, "192.168.4"): config.env = "localhost"; config.rootDomain = "localhost"; break; //"www.gray.rjmart.cn" case Uts.contain(host, "gray"): config.env = "gray"; break; //www.rjmart.rj-info.com case Uts.contain(host, "rjmart.rj-info"): config.env = "uat"; break; //test4.rj-info.com case Uts.contain(host, "test4"): config.env = "test4"; break; case Uts.contain(host, "\\.test\\."): config.env = "test"; break; case Uts.contain(host, "cloud.rj-info.com"): config.env = "test"; break; //www.demo.rjmart.cn case Uts.contain(host, "demo"): config.env = "demo"; break; //www.rjmart.cn case Uts.contain(host, ".rjmart.cn|.renlab.cn"): config.env = "publish"; break; case Uts.contain(host, "114.132.55.214"): config.env = "infly-test"; default: } if (!config.env) { config.env = "external"; } return config; }, /** * 获取两值中的最小值 * @module mathCompute * @todo Uts.min * @param {number} number1 * @param {number} number2 * @return {number} 两者中的最小值 * @example * Uts.min(10,38) 10 */ min(x, y) { return Math.min(x, y); }, transferReg(value) { if (value) { return value.replace(/([\$\(\)\*\+\.\[\]\?\\\^\{\}\|])/g, "\\$1"); } return value; }, /** * 生成正则表达式,用于正则判断不包含 * @module processString * @todo Uts.notContainReg * @param {string} value 要判断的字符串或正则 * @param {string} mode 正则模式,如'g,i' * @return {boolean} 正则表达式 * @example * Uts.notContainReg('<div>') /^((?!<div>).)+$/ */ notContainReg(value, mode = "") { if (Uts.notEmptyString(value)) { return new RegExp("^((?!" + value + ").)+$", mode); } }, /** * 在对象数组内根据条件查找符合条件的值 * @module processArray * @todo Uts.findObjByCondition * @param {array} arrayToFind 要查找的数组 * @param {object} cond 查找配置 * @param {Boolean} isStrict 是否严格模式,即完成匹配,默认否 * @return {array} 返回匹配的对象列表 * @example *var arr1=[{a:1},{a:1,b:2,c:3},{a:1,c:3}]; //非严格模式返回的数组包含第2和第3条数据 Uts.findObjByCondition(arr1,{a:1,c:3}); //严格模式返回的数组只会包含第3条数据 Uts.findObjByCondition(arr1,{a:1,c:3},true); //条件不匹配时返回空数组 Uts.findObjByCondition(arr1,{a:1,f:3}); [] */ findObjByCondition(arr, cond, isStrictMode, returnIndex, returnBoth) { if (this.notEmptyArray(arr)) { let _self = this; let result = []; let keys = Object.getOwnPropertyNames(cond); _self.each(arr, function(item, index) { let isMatch = true; let matchIndex; if (!isStrictMode || (isStrictMode && Object.getOwnPropertyNames(item).length == keys.length)) { _self.each(keys, function(keysItem, keysIndex) { if (!Uts.isPureObject(item) || item[keysItem] != cond[keysItem]) { isMatch = false; } }); if (isMatch) { if (returnBoth) { result.push({ index, item }); } else { result.push(returnIndex ? index : item); } if (isStrictMode) { _self.pauseEach = true; } } } }); return result; } }, /** * 在对象数组内根据条件查找符合条件的值,侧重于数据渲染时过滤,效果与Uts.findObjByCondition同 * @module processArray * @todo Uts.filterObjByCondition * @param {array} arrayToFind 要查找的数组 * @param {object} cond 查找配置 * @param {Boolean} isStrict 是否严格模式,即完成匹配,默认否 * @return {array} 返回匹配的对象列表 * @example *var arr1=[{a:1},{a:1,b:2,c:3},{a:1,c:3}]; //非严格模式返回的数组包含第2和第3条数据 Uts.filterObjByCondition(arr1,{a:1,c:3}); [ { "a": 1, "b": 2, "c": 3 }, { "a": 1, "c": 3 } ] //严格模式返回的数组只会包含第3条数据 Uts.filterObjByCondition(arr1,{a:1,c:3},true); [ { "a": 1, "c": 3 } ] //条件不匹配时返回空数组 Uts.filterObjByCondition(arr1,{a:1,f:3}); [] */ filterObjByCondition(arr, cond, isStrictMode) { let findResult = Uts.findObjByCondition(arr, cond, isStrictMode); return findResult; }, /** * filterObjByRegexpCondition 用于快速根据正则来搜索对象数组 * @module processArray * @todo Uts.filterObjByRegexpCondition * @param {array} arr 源数组 * @param {object} cond 条件对象,如{name:xxx,yyy:'www'} * @param {function} callbackRunPerItem 逐个回调,参数item,index,isMatch(是否匹配) * @param {boolean} isSingleMode 是否单条件匹配模式,用于匹配多个条件中的任意一个满足即可,如满足a==1或者b==2都可以,即:{a:1,b:2} * @return {array} 返回包含原匹配对象的新数组 * @example * var arr1=[{a:1},{a:3,b:2,c:3},{a:2,c:3}]; //非单条件匹配模式返回的数组包含第1和第3条数据 Uts.filterObjByRegexpCondition(arr1,{a:'1|3'}); [ { "a": 1 }, { "a": 3, "b": 2, "c": 3 } ] //单条件模式,匹配多个条件中的任意一个满足即可,如满足a==1或者b==2都可以,即:{a:1,b:2},注意条件应为正则,如完整匹配应为:a:"^1|2$" Uts.filterObjByRegexpCondition([{a:1},{a:2},{a:3},{b:2}],{a:"1",b:2},null,true) [ { "a": 1 }, { "b": 2 } ] */ filterObjByRegexpCondition(arr, cond, callbackRunPerItem, isSingleMode, isIgnoreCase) { let result = []; let keys = Uts.getObjectKeys(cond); if (Uts.notEmptyArray(arr)) { Uts.each(arr, function(item, index) { let isMatch = isSingleMode ? false : true; //如果是单条件匹配模式,则初始化默认为不match;否则默认为match Uts.each(keys, function(keyItem, keyIndex, run) { let condValue = cond[keyItem]; let itemValue = item[keyItem]; if (isIgnoreCase) { // if (Uts.notEmptyString(condValue)) { condValue = Uts.toLowerCase(condValue); itemValue = Uts.toLowerCase(itemValue); // } } let currentRegexp = new RegExp(condValue); let expResult = currentRegexp.test(itemValue); // expResult = Uts.contain(item[keyItem], cond[keyItem], true, isIgnoreCase); if (isSingleMode) { //在单条件匹配模式下,只有expResult为true才是match的 if (expResult) { isMatch = true; run.stop = true; } } else { //在非单条件匹配模式下,只有expResult为false才能改变match状态为false if (!expResult) { isMatch = false; run.stop = true; } } }); if (isMatch) { result.push(item); } callbackRunPerItem && callbackRunPerItem(item, index, isMatch, result); }); } return result; }, /** * 获取对象的键名列表 * @module processObject * @todo Uts.getObjectKeys * @param {object} obj * @return {array} 键名列表 * @example * Uts.getObjectKeys({useName:'zhangsan',useId:2}) ['useName', 'useId'] */ getObjectKeys(obj) { if (this.isObject(obj)) { return Object.keys(obj); // return Object.getOwnPropertyNames(obj); } }, /** * 判断对象自身及对象的所有值是否相等 * @module processObject * @todo Uts.objectIsEqual * @param {object} rawObject * @param {object} compareObject * @return {boolean} 布尔值 * @example * Uts.objectIsEqual({a:1},{a:1}) true Uts.objectIsEqual({a:1},{a:2}) false * */ objectIsEqual(rawObject, compareObject, resultObj) { /* 1.check if key count the same 2.check if key name the same 3.check if key value the same , recursion */ if (rawObject == compareObject) { return true; } resultObj = resultObj || { isTheSame: true }; if (!resultObj.isTheSame) { return resultObj.isTheSame; } if (Uts.isObject(rawObject) && Uts.isObject(compareObject)) { let rawKeys = Uts.getObjectKeys(rawObject); if (rawKeys.length == Uts.getObjectKeys(compareObject).length) { Uts.each(rawKeys, function(item, index) { let rawItem = rawObject[item]; let compareItem = compareObject[item]; if (Uts.isObject(rawItem) && Uts.isObject(compareItem)) { return Uts.objectIsEqual(rawItem, compareItem, resultObj); } else { if (rawItem != compareItem) { resultObj.isTheSame = false; Uts.pauseEach = true; return resultObj.isTheSame; } } }); return resultObj.isTheSame; } else { resultObj.isTheSame = false; return resultObj.isTheSame; } } else { resultObj.isTheSame = rawObject == compareObject; return resultObj.isTheSame; } }, /** * 判断数组是否相等 * @module processArray * @todo Uts.arrayIsEqual * @param {array} rawObject * @param {array} compareObject * @return {boolean} 布尔值 * @example * Uts.arrayIsEqual([1,2,3],[1]) false Uts.arrayIsEqual([1,2,3],[1,2,3]) true */ arrayIsEqual(arr1, arr2) { // return arr1.length===arr2.length && arr1.every(a=>arr2.some(b=>a===b)) && arr2.every(_b=>arr1.some(_a=>_a===_b)) return Uts.objectIsEqual(arr1, arr2); }, /** * mergeObjectWithReference 合并对象(改变原对象),第三个参数控制是否覆盖原对象 * @module processObject * @todo Uts.mergeObjectWithReference * @param {object} object 原对象 * @param {object} valueObject 要合并进来的对象 * @param {Boolean} isOverride 是否覆盖原对象,即原对象引用不变,但所有旧值删除,只保留新对象的值 * @return {null} * @example * var o1={a:1},o2={b:2}; Uts.mergeObjectWithReference(o1,o2); console.log(o1) {a: 1, b: 2} //覆盖模式 var o1={a:1},o2={b:2}; Uts.mergeObjectWithReference(o1,o2,true); console.log(o1) {b: 2} */ mergeObjectWithReference(object, valueObject, isOverride) { if (!Uts.isObject(object) || !Uts.isObject(object)) { Uts.ce("please check your params"); return false; } if (isOverride) { let propertyList = Uts.getObjectKeys(object); Uts.each(propertyList, function(item, index) { delete object[item]; }); } let newPropertyList = Uts.getObjectKeys(valueObject); Uts.each(newPropertyList, function(item, index) { object[item] = valueObject[item]; }); }, /** * 深度合并对象,不覆盖目标对象的已有属性 * @param {Object} target - 目标对象 * @param {Object} source - 源对象 * @param {boolean} overwrite - 是否覆盖已存在的属性,默认 false * @returns {Object} 合并后的目标对象 */ deepMerge(target, source, overwrite = false) { if (!source || typeof source !== "object") return target; if (!target || typeof target !== "object") return source; Object.keys(source).forEach(key => { const sourceValue = source[key]; const targetValue = target[key]; if (Array.isArray(sourceValue)) { // 处理数组:如果不覆盖且目标已存在,保持原数组 if (!overwrite && targetValue !== undefined) { return; } target[key] = [...sourceValue]; } else if (sourceValue && typeof sourceValue === "object") { // 处理对象:递归合并 if (!target[key] || typeo