PageSourceSearch

https://news.sdchina.com/template/1/sdong/js/utils.js?v=2.0.1

js sdchina.com collected 2026-10-02 07:29:23 UTC 23,276 bytes, 759 lines download raw bytes

1var CONSTOBJ = {
2    mapobj:{
3       'en': 'en',
4       'jp': 'ja',
5       'kr': 'kr',
6       'ru': 'ru',
7    },
8    i18nMessages: {
9        'zh-Hans': {
10            'localeChange': '根据您所在的区域和设置偏好,您可能要访问',
11            'switch':',是否切换?',
12            'prompt': '提示',
13            'confirm': '确定',
14            'cancle': '取消',
15        },
16        'en': {
17            'localeChange': 'Depending on your region and settings preferences, you may need to access ',
18            'switch':'. Do you want to switch?',
19            'prompt': 'Prompt',
20            'confirm': 'Confirm',
21            'cancle': 'Cancel',
22        },
23        'ja': {
24            'localeChange': '場所と設定の好みに応じて、アクセスすることができます',
25            'switch':'、言語を変更しますか?',
26            'prompt': 'ヒント',
27            'confirm': '確認',
28            'cancle': '取り消し',
29        },
30        'kr': {
31            'localeChange': '현재 위치 및 설정 선호도에 따라 ',            
32            'switch':'으로 전환하겠습니까?',
33            'prompt': '팁',
34            'confirm': '확인',
35            'cancle': '취소',
36        },
37        'ru': {
38            'localeChange': 'В зависимости от зоны и настройки предпочтений, вы можете получить доступ',            
39            'switch':'Переключать или нет?',
40            'prompt': 'подсказк',
41            'confirm': 'Подтвердить',
42            'cancle': 'Отмена',
43        }
44    }
45}
46Vue.use(VueI18n)
47var i18n = new VueI18n({
48    locale: 'zh-Hans',
49    messages:CONSTOBJ.i18nMessages
50})
51//是否登录:登录回调,是否显示提示信息
52function gIsLogin(cb, isShowMsg) {
53  ms.http
54    .post(ms.base + "/api/checkLoginStatus.do")
55    .then((data) => {
56      if (!data.result && isShowMsg) {
57        // Vue.prototype.$message.error(`请先点击右上角登录`);
58        Vue.prototype.$notify({
59          title: "提示",
60          message: "请先点击右上角登录",
61          type: "warning",
62        });
63      }
64      //true/false
65      cb(data.result);
66    })
67    .catch((err) => {
68      console.log(err);
69    });
70}
71
72//获取用户信息
73function getUserInfo(cb) {
74  ms.http
75    .get(ms.base + "/api/people/user/info.do")
76    .then((data) => {
77      data.result && cb(data.data);
78      /* let data = {
79        del: 0,
80        id: "653",
81        peopleAutoLogin: 0,
82        peopleIp: "127.0.0.1",
83        peopleDateTime: "2023-01-11 15:12:36",
84        peopleMailCheck: -1,
85        peopleName: "yaoyao",
86        peoplePhoneCheck: -1,
87        peopleState: 1,
88        newUser: true,
89        peopleLoginCount: "0",
90        peopleId: 653,
91        puRealName: "yaoyao",
92        puNickname: "yaoyao",
93        puLanguagePreference: 0,
94        puListStyle: 0,
95      }; */
96    })
97    .catch(function (err) {});
98}
99
100//是否开启评论
101function getCommentSwitch(cb) {
102  ms.http
103    .get(ms.base + "/api/mdiy/config/feedback.do")
104    .then(function (data) {
105      //true/false
106      cb(Boolean(data.data));
107    })
108    .catch(function (err) {});
109}
110
111//上下滚动推荐
112/*
113 * @description: 上下滚动推荐的插件,跑马灯效果
114 * @require jquery
115 * @param {opt.wrap} required 父容器
116 * @param {opt.stepTime} required  滚动时间间隔 minseconds
117 * @return: 实例
118 */
119
120function RecCarousel(opt) {
121  const $this = this
122  this.recTimer = null
123  this.step = 1
124  this.wrap = opt.wrap  
125  this.stepTime = opt.stepTime
126  
127  if(!this.wrap){
128    console.error('wrap is required')
129    return 
130  }
131  this.start = function(){
132    clearInterval($this.recTimer)
133      $this.recTimer = null
134      if($this.wrap.attr('bind')){
135          return
136      }
137    $this.recTimer = setInterval(()=>{
138      $this.setRecCarousel()
139    }, $this.stepTime)
140  }
141
142  this.stop = function(){
143    const timer = $this.recTimer
144    if(timer){
145      clearInterval(timer)
146      $this.recTimer = null
147    }
148  }
149
150  this.setRecCarousel = function(){
151    const listbox = this.wrap.find('.channel-recommend-h-list')
152    const listboxHeight = listbox.height()
153    const listAll = listbox.find('.channel-recommend-news')
154    const stepSpace = this.wrap.height()
155    const step = this.step
156    const row = Math.ceil(listboxHeight/stepSpace)
157    if(row >= 2){
158        // const row = Math.ceil(listAll.length/2)
159        if(step >= row){
160            this.step = 1
161        }else{
162            this.step++
163        }
164        this.wrap.find(".channel-recommend-h-list").animate({top: -(this.step-1)*stepSpace+'px'});
165        this.wrap.attr('bind','true')
166    }
167  }
168  this.stop()
169  this.start()
170  
171  this.wrap.hover(function(){
172      $this.wrap.removeAttr('bind')
173    $this.stop()
174  },function(){
175    $this.start()
176  })
177  return this
178}
179//是否开启点赞
180function getPrizeSwitch(cb) {
181    ms.http
182      .get(ms.base + "/api/mdiy/config/approve.do")
183      .then(function (data) {
184        //true/false
185          if (data.data === 'false'){
186              cb(Boolean(false));
187          }else {
188              cb(Boolean(true));
189          }
190      })
191      .catch(function (err) {});
192  }
193
194  // 查询是否收藏
195function collectStatus (dataId,cb) {
196    const params = {
197        dataId: dataId,
198        dataType: 2,
199    }
200    ms.http.post(ms.base + "/api/attention/collectionLog/isExists.do", params).then(function (res) {
201        let obj={
202            collectStatue:res.result, // 第一个参数是收藏状态
203            isLogIn: true // 第二个登录状态
204        }
205        cb(obj)
206    }).catch(function (err) {
207        console.log(err);
208        let obj={
209            collectStatue:false, // 第一个参数是收藏状态
210            isLogIn: false// 第二个登录状态
211        }
212        cb(obj)
213    });
214}
215// 查询是否点赞
216function prizeStatus (dataId,cb) {
217    const params = {
218        dataId: dataId,
219        dataType: 1,
220    }
221    ms.http.post(ms.base + "/api/attention/collectionLog/isExists.do", params).then(function (res) {
222        let obj={
223            collectStatue:res.result, // 第一个参数是点赞状态
224            isLogIn: true // 第二个登录状态
225        }
226        cb(obj)
227    }).catch(function (err) {
228        console.log(err);
229        let obj={
230            collectStatue:false, // 第一个参数是点赞状态
231            isLogIn: false// 第二个登录状态
232        }
233        cb(obj)
234    });
235}
236// 收藏
237function  collect(params,cb){
238    ms.http.post(ms.base + "/api/people/attention/collectionLog/save.do", params).then(function (res) {
239        if (res.result) {
240            let isCollect = true
241            cb(Boolean(isCollect))
242            this.$message.success(`收藏成功`);
243        } else {
244            this.$message.error(data.data.msg);
245        }
246
247    }).catch(function (err) {
248        console.log(err);
249    });
250}
251// 取消收藏
252function  cancleCollect(params,cb){
253    ms.http.post(ms.base + "/api/people/attention/collectionLog/delete.do", params).then(function (res) {
254        if (res.result) {
255            let isCollect = false
256            cb(Boolean(isCollect))
257            this.$message.success(`取消收藏`);
258        } else {
259            this.$message.error(data.data.msg);
260        }
261    }).catch(function (err) {
262        console.log(err);
263    });
264}
265
266// 点赞
267function  prize(params,cb){
268    ms.http.post(ms.base + "/api/people/attention/collectionLog/save.do", params).then(function (res) {
269        if (res.result) {
270            let isPrize = true
271            cb(Boolean(isPrize))
272            this.$message.success(`点赞成功`);
273        } else {
274            this.$message.error(data.data.msg);
275        }
276
277    }).catch(function (err) {
278        console.log(err);
279    });
280}
281// 取消点赞
282function  canclePrize(params,cb){
283    ms.http.post(ms.base + "/api/people/attention/collectionLog/delete.do", params).then(function (res) {
284        if (res.result) {
285            let isPrize = false
286            cb(Boolean(isPrize))
287            this.$message.success(`取消点赞`);
288        } else {
289            this.$message.error(data.data.msg);
290        }
291    }).catch(function (err) {
292        console.log(err);
293    });
294}
295function getDeviceId(){
296    let options = {
297        excludes: {
298            language: true,
299            colorDepth: true,
300            deviceMemory: true,
301            pixelRatio: true,
302            availableScreenResolution: true,
303            timezoneOffset: true,
304            timezone: true,
305            sessionStorage: true,
306            localStorage: true,
307            indexedDb: true,
308            addBehavior: true,
309            openDatabase: true,
310            cpuClass: true,
311            doNotTrack: true,
312            plugins: true,
313            canvas: true,
314            webglVendorAndRenderer: true,
315            adBlock: true,
316            hasLiedLanguages: true,
317            hasLiedResolution: true,
318            hasLiedOs: true,
319            hasLiedBrowser: true,
320            touchSupport: true,
321            audio: false,
322            enumerateDevices: true,
323            hardwareConcurrency: true,
324        },
325    }
326    const cb = function (components, resolve, reject) {
327        let time = new Date().getTime();
328        components.push({
329            key:'timeStr',
330            value: time
331        });
332        const values = components.map((component) => {
333            return component.value;
334        });
335        // 指纹
336        const finger = Fingerprint2.x64hash128(values.join(''), 31);
337        localStorage.setItem('localeDeviceId',finger)
338        resolve(finger)
339    }
340    const promise = new Promise(function (resolve, reject){
341        const localeDeviceId = localStorage.getItem('localeDeviceId')
342        if(localeDeviceId){
343            resolve(localeDeviceId)
344        }else{
345            if (window.requestIdleCallback) {
346                requestIdleCallback(function () {
347                    Fingerprint2.get(options,function (components) {
348                        cb(components,resolve, reject)
349                    })
350                })
351            } else {
352                setTimeout(function () {
353                    Fingerprint2.get(options,function (components) {
354                        cb(components,resolve, reject)
355                    })
356                }, 500)
357            }
358        }
359
360    })
361
362    return promise
363}
364// 设置和获取默认语言
365function  setAndGetLocale(params, locationStr, cb){
366    // const mapobj = {
367    //     'zh-Hans': '0',
368    //     'en': '1',
369    //     'ja': '2',
370    //     'ru': '3',
371    //     'kr': '4'
372    // }
373    // const language = mapobj[params]||'0'
374    // const obj = params?{language:language}:{}
375    // const host = location.host
376    // console.log("setAndGetLocale----host:"+host)
377    // if(obj.language==null&&location.href.endsWith("index.html")){
378    //     console.log("setAndGetLocale----预览")
379    //     return
380    // }
381    // getDeviceId().then((res)=>{
382        // obj.deviceId = res
383        siteid = params||'1'
384        ms.http.get((ms.base||'') + "/api/cms/content/appList").then(function (res) {           
385            if (res.data&&Array.isArray(res.data)) {
386                res.data.forEach(item => {
387                    if(item.id===params){
388                        location.href = item.appUrl
389                    }
390                });
391            } else {
392                // this.$message.error(res.data.msg);
393            }
394        }).catch(function (err) {
395            console.log(err);
396        });
397    // })
398
399
400}
401function $t(args) { 
402    return i18n.t.call(i18n, args); 
403  } 
404function setLocaleLanguage(strurl){
405    let realLang = null
406    if(strurl){
407        const mapobj = CONSTOBJ.mapobj
408        const langKeys = Object.keys(mapobj)
409        const filterlang = langKeys.filter(function(item){
410            return strurl.indexOf(item) >= 0
411        })
412        realLang =filterlang.length? mapobj[filterlang[0]] : 'zh-Hans'
413        if(realLang){
414            i18n.locale = realLang
415        }
416        
417    }
418}
419// 设置和获取默认语言
420function  checkSetLocale(strurl){
421    
422
423    const host = location.host
424    let realLang = null
425    let confirmLocale = localStorage.getItem('confirmLocalenew')
426    // if(location.href.endsWith("index.html")){
427    //     console.log("setAndGetLocale----预览")
428    //     return
429    // }
430    if(strurl){
431        // const lastPathsplit = strurl.lastIndexOf('/')
432        // const len = strurl.length
433        // if(lastPathsplit !== len-1){
434        //     const lanStr = strurl.substr(lastPathsplit+1,len)
435            const mapobj = CONSTOBJ.mapobj
436            const langKeys = Object.keys(mapobj)
437            const filterlang = langKeys.filter(function(item){
438                return strurl.indexOf(item) >= 0
439            })
440            realLang =filterlang.length? mapobj[filterlang[0]] : 'zh-Hans'
441            if(realLang){
442                i18n.locale = realLang
443            }
444        // }
445        
446    }
447    if(confirmLocale === '1'){
448        return
449    }
450    //按照ip获取
451    getDeviceId().then((res)=>{
452        ms.http.get((ms.base||'') + "/api/cms/category/getIpLanguage").then(function (res) {
453            if (res.data) {
454                const appName = res.data.appName
455                const appId = res.data.id
456                const objSite={
457                    '1':'中文站',
458                    '36':'日本語',
459                    '37':'한국어',
460                    '38':'English',
461                    '42':'Русский язык'
462                }
463                if (typeof appId == 'string' && appId.length > 0){
464                    var appmapName = objSite[appId]||'English'
465                    //弹窗提示上次选择的站点,确认调设置语言站点接口,
466                    Vue.prototype.$confirm($t('localeChange') + '"' + appmapName + '"' + $t('switch') , $t('prompt'), {
467                        confirmButtonText: $t('confirm'),
468                        cancelButtonText: $t('cancle'),
469                        type: 'warning'
470                    }).then(() => {
471                        localStorage.setItem('confirmLocalenew','1')
472                        setAndGetLocale(res.data.id)
473                    }).catch(() => {
474                        // setAndGetLocale(realLang||'zh-Hans')
475                        localStorage.setItem('confirmLocalenew','1')
476                    });
477                }
478            }
479        }).catch(function (err) {
480            console.log(err);
481        });
482    })
483
484
485}
486// 匹配host语言
487function  checkHostSite(strurl){
488    var promise = new Promise(function(res,rej){
489        let realLang = null
490        if(strurl){
491            const mapobj = CONSTOBJ.mapobj
492            const langKeys = Object.keys(mapobj)
493            const filterlang = langKeys.filter(function(item){
494                return strurl.indexOf(item) >= 0
495            })
496            realLang = filterlang.length? mapobj[filterlang[0]] : 'zh-Hans'
497            res({
498                code:200,
499                lang:realLang
500            })
501            
502        }else{
503            res({
504                code: 200,
505                lang: 'zh-Hans'
506            })
507        }
508        
509    })
510    
511    return promise
512
513}
514function redictToh5(url, par){
515    if(par && par.param && par.param.code === 200 && browserSys.versions.mobile){
516        var param = deepCopy(par.param)
517        var suffixPath = par.suffixPath
518        
519        var urlarr = [url,'#']
520        delete param.code
521        var h5url = getUrlFromObj(suffixPath, param)
522        urlarr.push(h5url)
523        var fullUrl = urlarr.join('')
524
525        location.href = fullUrl
526    }
527}
528/**
529 * 传入对象返回url参数
530 * @param {Object} data {a:1}
531 * @returns {string}
532 */
533function getParamFromObj(data){
534    let url = '';
535    for(var k in data){
536        let value = data[k] !==undefined ? data[k] : '';
537        url += `&${k}=${encodeURIComponent(value)}`
538    }
539    return url ? url.substring(1) : ''
540}
541
542/**
543 * 将url和参数拼接成完整地址
544 * @param {string} url url地址
545 * @param {Json} data json对象
546 * @returns {string}
547 */
548function getUrlFromObj(url, data){
549    //看原始url地址中开头是否带?,然后拼接处理好的参数
550    return url += (url.indexOf('?') < 0 ? '?' : '&') + getParamFromObj(data)
551}
552
553//获取url某key值
554const getParamByUrl = (key) => {
555  const url = new URL(location.href)
556  return url.searchParams.get(key)
557}
558function typeOf(obj) {
559  const toString = Object.prototype.toString
560  const map = {
561    '[object Boolean]': 'boolean',
562    '[object Number]': 'number',
563    '[object String]': 'string',
564    '[object Function]': 'function',
565    '[object Array]': 'array',
566    '[object Date]': 'date',
567    '[object RegExp]': 'regExp',
568    '[object Undefined]': 'undefined',
569    '[object Null]': 'null',
570    '[object Object]': 'object',
571  }
572  return map[toString.call(obj)]
573}
574
575function deepCopy(data) {
576  const t = typeOf(data)
577  let o
578
579  if (t === 'array') {
580    o = []
581  } else if (t === 'object') {
582    o = {}
583  } else {
584    return data
585  }
586
587  if (t === 'array') {
588    for (let i = 0; i < data.length; i++) {
589      o.push(deepCopy(data[i]))
590    }
591  } else if (t === 'object') {
592    for (let i in data) {
593      o[i] = deepCopy(data[i])
594    }
595  }
596  return o
597}
598
599function getImgUrl(data) {
600  return data && window.location.origin+JSON.parse(data)[0].url;
601}
602
603// setAndGetLocale()
604
605//处理后台数据:"[{\"url\":\"/upload/1/cms/content/1674007726555.png\",\"desc\":\"\"}]"
606//示例:getImgUrl(contentImg, 'img34')
607function getImgUrlBySize(data, size) {
608		try {
609			var key = size || "url";
610
611			if (data) {
612				var img = JSON.parse(data)[0];
613				// console.log(API_URL + (img[key] || img.url))
614				//兼容老数据没有imgxx这种字段
615				return window.location.origin + (img[key] || img.url);
616			}
617		} catch (e) {
618			return "";
619		}
620}
621
622function throttle(fn, delay) {
623    let timer = null;
624  
625    return function () {
626        if (timer) return;//如果定时器还在,说明上一次延迟执行还没有完成,则不再执行
627        timer = setTimeout(() => {
628        fn.apply(this, arguments);
629        timer = null;
630        }, delay);
631    };
632}
633
634function debounce (fn, wait) {
635    let timer = null;
636    return function(){
637      clearTimeout(timer);
638      timer = setTimeout(()=>{
639        fn.apply(this, arguments);
640      }, wait);
641    };
642  };
643function isUrl(url) {
644    return /(http|https):\/\/([\w.]+\/?)\S*/.test(url);
645}
646/**
647 * 微信分享默认图标(取不到封面时的兜底)
648 * @description utils.js 是静态文件,{ms:global.host/}、{ms:global.style/} 不会被替换,
649 *              所以由各模板页面在引入 head-file.htm 之后,把解析好的地址赋进来(image/180x180.png)
650 */
651var WX_SHARE_DEFAULT_IMG = ''
652/**
653 * 规范化分享图标地址
654 * @description {ms:global.host/} 结尾带 /,而 litpic/imageUrl 的 url 开头也带 /,拼接后会出现 host//path
655 *              微信侧偶尔会因此取不到图,这里统一收敛成单斜杠(协议后的 // 保留)
656 * @param {string} imgUrl
657 * @returns {string}
658 */
659function normalizeWxImgUrl(imgUrl) {
660    if (!imgUrl) return ''
661    return imgUrl.replace(/^(https?:\/\/[^/]+)\/+/, '$1/')
662}
663
664/**
665 * 直播详情页微信分享初始化(公共方法)
666 * @description 直播类页面都是栏目页(/list/{栏目id}.html?liveId=xxx),服务端没有文章 id/field,
667 *              wx-share.htm 里的 <#if id??> 判断不成立会输出空内容,
668 *              所以只能在 getLiveDetail 拉到详情后,由客户端取标题封面来初始化
669 * @param {Object} detail 直播详情对象(各模板里的 detailObj)
670 */
671function initLiveWxShare(detail) {
672    detail = detail || {}
673    let imgUrl = ''
674    try {
675        var arr = detail.imageUrl ? JSON.parse(detail.imageUrl) : []
676        var rawImg = arr.length ? (arr[0].url || arr[0].img169 || '') : ''
677        //utils.js 是静态文件,{ms:global.host/} 不会被替换,统一取当前站点域名(与 getImgUrl 一致)
678        imgUrl = /^https?:\/\//.test(rawImg) ? rawImg : (rawImg ? window.location.origin + rawImg : '')
679    } catch (e) {
680        imgUrl = ''
681    }
682    initWxShare({
683        title: detail.title || document.title,
684        imgUrl: imgUrl
685    })
686}
687
688/**
689 * 微信内自定义分享(公共方法,供各详情页调用)
690 * @description 非微信环境直接返回;jWeixin 只按需加载一次,签名复用 ms.http 自带的签名头
691 * @param {Object} opt
692 * @param {string} opt.title     分享标题
693 * @param {string} [opt.desc]    分享描述,默认“来自新感知客户端”
694 * @param {string} [opt.imgUrl]  分享图标,必须是绝对地址
695 * @param {string} [opt.link]    分享链接,默认当前页面地址(去掉 hash)
696 */
697function initWxShare(opt) {
698    opt = opt || {}
699    // 仅微信内执行,非微信环境(浏览器/其它 APP)直接返回
700    if (!/micromessenger/i.test(navigator.userAgent.toLowerCase())) return
701
702    var shareData = {
703        title: opt.title || document.title,
704        desc: opt.desc || '来自新感知客户端',
705        link: opt.link || location.href.split('#')[0],
706        //取不到封面时兜底成站点默认图标(由 head-file.htm 赋值)
707        imgUrl: normalizeWxImgUrl(opt.imgUrl || WX_SHARE_DEFAULT_IMG)
708    }
709
710    // 只加载一次微信 jssdk
711    if (typeof jWeixin === 'undefined' && !document.getElementById('wx-jweixin-script')) {
712        var script = document.createElement('script')
713        script.id = 'wx-jweixin-script'
714        script.async = true
715        script.src = 'https://res.wx.qq.com/open/js/jweixin-1.6.0.js'
716        document.head.appendChild(script)
717    }
718    // jWeixin 为异步加载,且本方法可能在页面早期调用,需同时等待 jWeixin 与 ms 就绪
719    var checkCount = 0
720    var timer = setInterval(function () {
721        if (typeof jWeixin !== 'undefined' && typeof ms !== 'undefined') {
722            clearInterval(timer)
723            applyWxShare(shareData)
724        } else if (++checkCount > 100) { // 最多等 5 秒
725            clearInterval(timer)
726        }
727    }, 50)
728}
729
730/**
731 * 拉取签名并配置微信分享,由 initWxShare 在环境就绪后调用
732 * @param {Object} shareData {title, desc, link, imgUrl}
733 */
734function applyWxShare(shareData) {
735    // 复用 ms.http.post:自带 SignFilter 签名头,无需后端加白名单
736    ms.http
737        .post(ms.base + '/api/wechat/getWechatShareData', { url: shareData.link })
738        .then(function (res) {
739            var cfg = res.data || {}
740            jWeixin.config({
741                debug: false,
742                appId: cfg.appId,
743                timestamp: cfg.timestamp,
744                nonceStr: cfg.nonceStr,
745                signature: cfg.signature,
746                jsApiList: [
747                    'updateAppMessageShareData', // 分享给朋友(1.4+)
748                    'updateTimelineShareData',   // 分享到朋友圈(1.4+)
749                    'onMenuShareAppMessage'      // 旧版兼容
750                ]
751            });
752            jWeixin.ready(function () {
753                jWeixin.updateAppMessageShareData(shareData);
754                jWeixin.updateTimelineShareData(shareData);
755                jWeixin.onMenuShareAppMessage(shareData);
756            });
757        })
758        .catch(function () {});
759}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.