PageSourceSearch

https://www.dxsport.com/npublic/commonjs/nouglify/gdpr/gdpr.js

js dxsport.com collected 2026-09-25 05:48:25 UTC 27,065 bytes, 661 lines download raw bytes

1$define(['cmsAjax','css!/npublic/commonjs/nouglify/gdpr/gdpr.css','pl_util'],function (c) {
2    const root = document.documentElement
3    const state = {
4        region: 'eu',
5        consented: false,
6        choices: { necessary:true, functional:false, analytics:false, marketing:false,other:false },
7    };
8    const localCookie = {
9        necessary:[],
10        functional:[],
11        analytics:[],
12        marketing:[],
13        other:[],
14    }
15    var LEGAL_DOCS = [],popup = '',config = ''
16    function init(obj){
17        console.log(obj)
18        config = obj
19        state.consented = obj.consented
20        if(!obj.lastAction){
21            state.consented = false
22        }
23        LEGAL_DOCS = obj.docList
24        popup = obj.popup
25
26        popup.accentColor && root.style.setProperty('--gdpr-accentColor', popup.accentColor)
27        popup.bgColor && root.style.setProperty('--gdpr-bgColor', popup.bgColor)
28        popup.bodyFontSize && root.style.setProperty('--gdpr-bodyFontSize', popup.bodyFontSize+'px')
29        popup.borderColor && root.style.setProperty('--gdpr-borderColor', popup.borderColor)
30        popup.borderWidth && root.style.setProperty('--gdpr-borderWidth', popup.borderWidth)
31        popup.btnAcceptColor && root.style.setProperty('--gdpr-btnAcceptColor', popup.btnAcceptColor)
32        popup.btnMoreColor && root.style.setProperty('--gdpr-btnMoreColor', popup.btnMoreColor)
33        popup.btnRejectColor && root.style.setProperty('--gdpr-btnRejectColor', popup.btnRejectColor)
34        popup.linkColor && root.style.setProperty('--gdpr-linkColor', popup.linkColor)
35        popup.switchOffColor && root.style.setProperty('--gdpr-switchOffColor', popup.switchOffColor)
36        popup.switchOnColor && root.style.setProperty('--gdpr-switchOnColor', popup.switchOnColor)
37        popup.tabColor && root.style.setProperty('--gdpr-tabColor', popup.tabColor)
38        popup.textColor && root.style.setProperty('--gdpr-textColor', popup.textColor)
39        popup.themeType && root.style.setProperty('--gdpr-themeType', popup.themeType)
40        popup.titleFontSize && root.style.setProperty('--gdpr-titleFontSize', popup.titleFontSize+'px')
41        popup.btnRadius && root.style.setProperty('--gdpr-btnRadius', popup.btnRadius+'px')
42        popup.popupRadius && root.style.setProperty('--gdpr-popupRadius', popup.popupRadius+'px')
43
44
45        renderDom(obj)
46        renderEvent()
47
48        let scriptConfig = obj.script
49        $.ajax({
50            url:"/thirdcode/scripts",
51            dataType:"json",
52            success:function(res){
53                if(res.length){
54                    for(var i=0;i<res.length;i++){
55                        if(res[i]=='/goo.js'&&scriptConfig.googleAnalytics){
56                            continue   
57                        }
58                        if(res[i]=='/bd.js'&&scriptConfig.baiduAnalytics){
59                            continue
60                        }
61                        $require([res[i]],function(){});
62                    }
63                }
64            }
65        })
66
67    }
68
69    function renderDom(obj){
70        let cookieBannerHtml = cookieBanner(obj)
71        let consentBadgeHtml = consentBadge(obj)
72        $("body").append(cookieBannerHtml)
73        $("body").append(consentBadgeHtml)
74        
75        
76        // 显示banner
77        showBanner()
78    }
79    function renderEvent(){
80        //打开偏好设置
81        $("body").on("click",".js_showPrefCenter",() => showPrefCenter())
82        //关闭偏好设置
83        $("body").on("click","#hidePrefCenter",() => hidePrefCenter())
84        //展开关闭
85        $("body").on("click",".cat_expand",function(){
86            let key = $(this).data("key")
87            $('#cat_' + key).toggleClass('open');
88        })
89        //隐私政策等
90        $("body").on("click",".legal_link",function(){
91            let type = $(this).data("type")
92            showLegalModal(type)
93        })
94        //关闭隐私政策等
95        $("body").on("click",".js_closeLegal",() => hideLegalModal())
96        //删除我的数据
97        $("body").on("click","#showDsarModal",function(){
98            showDsarModal()
99            hideLegalModal()
100        })
101        //取消删除我的数据
102        $("body").on("click",".js_closeDsarModal",function(){
103            hideDsarModal()
104        })
105        //提交删除我的数据
106        $("body").on("click","#dsarSubmitBtn",function(){
107            const emailEl = $('#dsarEmail');
108            const errBar  = $('#dsarErrBar');
109            const errMsg  = $('#dsarErrMsg');
110            const email   = emailEl.val().trim();
111            const emailReg = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
112
113            // ── 校验 ──
114            if (!email) {
115                emailEl.addClass('error')
116                errMsg.text($t('gdpr_email'));
117                errBar.addClass("show");
118                emailEl.focus();
119                return;
120            }
121            if (!emailReg.test(email)) {
122                emailEl.addClass('error')
123                errMsg.text($t('gdpr_emainMsg'));
124                errBar.addClass("show");
125                emailEl.focus();
126                return;
127            }
128            let url = `/fwebapi/member/gdpr/dsar/submit`
129            let p = {
130                userEmail: email,
131            }
132            c.cmsAjax.postJson(url,p).then(res=>{
133                console.log(res)
134                $('#dsarFormArea').hide();
135                $('#dsarSuccessArea').show();
136            })
137        })
138        //重新提交email
139        $("body").on("click",".js_resendDsarEmail",function(){
140            $('#dsarEmail').val("")
141            $('#dsarFormArea').show();
142            $('#dsarSuccessArea').hide();
143        })
144        //关闭
145        $("body").on("click",".c_close",function(){
146            rejectAll(true);
147        })
148        //全部接受
149        $("body").on("click",".js_acceptAll",function(){
150            acceptAll()
151        })
152        //自定义设置
153        $("body").on("click",".js_savePreferences",function(){
154            savePreferences()
155        })
156        //仅必要
157        $("body").on("click",".js_rejectAll",function(){
158            rejectAll()
159        })
160    }
161
162    // ══════════════════════════════
163    // BANNER
164    // ══════════════════════════════
165    //显示banner
166    function showBanner() {
167        if (state.consented) {
168            let lastAction = config.lastAction
169            if(lastAction){
170                state.choices.necessary = Boolean(lastAction.necessary)
171                state.choices.functional = Boolean(lastAction.functional)
172                state.choices.analytics = Boolean(lastAction.analytics)
173                state.choices.marketing = Boolean(lastAction.marketing)
174                state.choices.other = Boolean(lastAction.other)
175            }
176            setBadge(true)
177            return
178        };
179        $('#cookieBanner').addClass('visible');
180        $('#consentBadge').removeClass('visible');
181    }
182    //隐藏banner
183    function hideBanner() {
184        $('#cookieBanner').removeClass('visible');
185    }
186    //仅必要
187    function rejectAll(silent) {
188        state.choices = { necessary:true, functional:false, analytics:false, marketing:false , other:false};
189        ['functional','analytics','marketing','other'].forEach(c => {
190            const t = document.getElementById('tog-' + c);
191            if (t) t.checked = false;
192        });
193        applyConsent(2, silent);
194    }
195    //全部接受
196    function acceptAll(){
197        state.choices = { necessary:true, functional:true, analytics:true, marketing:true, other:true};
198        ['functional','analytics','marketing','other'].forEach(c => {
199            const t = document.getElementById('tog-' + c);
200            if (t) t.checked = true;
201        });
202        applyConsent(1);
203    }
204    //自定义设置
205    function savePreferences() {
206        state.choices.functional  = document.getElementById('tog-functional').checked;
207        state.choices.analytics   = document.getElementById('tog-analytics').checked;
208        state.choices.marketing   = document.getElementById('tog-marketing').checked;
209        state.choices.other   = document.getElementById('tog-other').checked;
210        
211        applyConsent(3);
212    }
213    //应用设置
214    function applyConsent(type, silent) {
215        let p = {
216            actionType:type,
217            sessionId:sessionStorage.getItem('sdkSessionId'),
218        }
219        for(let i in state.choices){
220            p[i] = state.choices[i]?1:0
221        }
222        let url = `/fwebapi/member/gdpr/cookie/consent`
223        c.cmsAjax.postJson(url,p).then(res=>{
224            console.log(res)
225            state.consented = true;
226            
227            hideBanner();
228            hidePrefCenter();
229
230            setBadge(silent)
231            
232            if(window.gtag){
233                gtag('consent', 'update', {
234                    analytics_storage : state.choices.analytics ? 'granted' : 'denied',
235                    ad_storage: state.choices.marketing ? 'granted' : 'denied',
236                    ad_user_data : state.choices.marketing ? 'granted' : 'denied',
237                    ad_personalization : state.choices.marketing ? 'granted' : 'denied',
238                });
239            }
240            console.log(localCookie)
241            for(let i in state.choices){
242                if(!state.choices[i]){
243                    deleteCookies(localCookie[i])
244                }
245            }
246        })
247    }
248    //删除cookie
249    function deleteCookies(names) {
250        const domains = [
251            location.hostname,
252            '.' + location.hostname,
253            location.hostname.replace(/^www\./, ''),
254            '.' + location.hostname.replace(/^www\./, '')
255        ]
256        const paths = ['/', '']
257        names.forEach(name => {
258            domains.forEach(domain => {
259                paths.forEach(path => {
260                    document.cookie =`${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=${path}; domain=${domain}`
261                })
262            })
263        })
264    }
265    //设置badage
266    function setBadge(silent) {
267        const on = ['functional','analytics','marketing','other'].filter(c => state.choices[c]);
268        const map = {functional:$t('gdpr_functional'),analytics:$t('gdpr_analytics'),marketing:$t('gdpr_marketing'),other:$t('gdpr_other')};
269        let label, color;
270        if (on.length === 4)      { label = $t('gdpr_toastAccess');                color = '#52c41a'; }
271        else if (on.length === 0) { label = $t('gdpr_toastReject');           color = '#d9d9d9'; }
272        else                      { label = $t('gdpr_toastCustom',[on.map(k=>map[k]).join(' + ')]); color = '#fa8c16'; }
273
274        // Update consent badge
275        const badge   = $('#consentBadge');
276        const dot     = document.getElementById('cDot');
277        const badgeTxt = $(".c_badgeText");
278        
279        dot.style.background = color;
280        badgeTxt.text('Cookie:' + label)
281        badge.addClass('visible');
282
283        if (!silent) toast($t('gdpr_toast',[label]));
284    }
285    //显示偏好设置
286    function showPrefCenter() {
287        let prefOverlayDom = $('#prefOverlay')
288        if(prefOverlayDom.length==0){
289            let url = `/fwebapi/member/gdpr/cookie/dict`
290            c.cmsAjax.get(url).then(res=>{
291                try{
292                    hideBanner();
293                    let prefOverlayHtml = prefOverlay(config,res.data.data)
294                    $("body").append(prefOverlayHtml)
295                    prefOverlayDom = $('#prefOverlay')
296                    prefOverlayDom.addClass('visible');
297                    document.body.style.overflow = 'hidden';
298                }catch(e){
299                    console.log(e)
300                }
301            })
302            
303        }else{
304            hideBanner();
305            prefOverlayDom.addClass('visible');
306            document.body.style.overflow = 'hidden';
307        }
308        
309    }
310    //隐藏偏好设置
311    function hidePrefCenter() {
312        $('#prefOverlay').removeClass('visible');
313        document.body.style.overflow = '';
314        if (!state.consented) showBanner();
315    }
316    //显示隐私政策等
317    function showLegalModal(type) {
318        let obj = LEGAL_DOCS.find(e=>e.docType === type)
319        const doc = {
320            title:obj.docName,
321            content:obj.docContent.replace(/\n/g,'<br/>'),
322            updated:$.formatDate(new Date(Number(obj.updateDate)),'yyyy-MM-dd') ,
323        }
324        if (!doc) return;
325        let legaModal = document.getElementById('legalOverlay')
326        if(!legaModal){
327            let legalOverlayHtml = legalOverlay(config)
328            $("body").append(legalOverlayHtml)
329            legaModal = document.getElementById('legalOverlay')
330        }
331        document.getElementById('legalModalTitle').textContent = doc.title;
332        document.getElementById('legalModalBody').innerHTML = doc.content;
333        const updatedEl = document.getElementById('legalModalUpdated');
334        updatedEl.textContent = doc.updated || '';
335        // 仅在隐私政策中显示数据删除入口(其他文件不展示)
336        const dsarLink = document.getElementById('legalModalDsarLink');
337        if (dsarLink) dsarLink.style.display = (type == '2') ? 'inline' : 'none';
338        legaModal.classList.add('visible');
339        document.body.style.overflow = 'hidden';
340    }
341    //隐藏隐私政策等
342    function hideLegalModal() {
343        $('#legalOverlay').removeClass('visible');
344        document.body.style.overflow = '';
345    }
346    //显示删除我的数据弹窗
347    function showDsarModal() {
348        let m = $('#dsarModal');
349        if (m.length){
350            m.addClass('visible');
351        }else{
352            let dsarModalHtml = dsarModal()
353            $("body").append(dsarModalHtml)
354            m = $('#dsarModal');
355            m.addClass('visible');
356        }
357        $('#dsarFormArea').show();
358        $('#dsarSuccessArea').hide();
359        const emailEl = $('#dsarEmail');
360        emailEl.val("")
361        $('#dsarErrBar').removeClass("show");
362        setTimeout(() => emailEl.focus(), 120);
363    }
364
365    function hideDsarModal() {
366        $('#dsarModal').removeClass('visible');
367    }   
368    //获取所有cookie
369    function getAllCookies() {
370        const cookies = document.cookie.split(';');
371        const cookieList = [];
372        for (let cookie of cookies) {
373            cookie = cookie.trim();
374            if (!cookie) continue;
375            const firstEqualIndex = cookie.indexOf('=');
376            const name = cookie.substring(0, firstEqualIndex);
377            const value = decodeURIComponent(cookie.substring(firstEqualIndex + 1));
378            cookieList.push({
379                name: name,
380                value: value,
381            });
382        }
383        return cookieList;
384    }
385    //cookie 弹窗
386    function cookieBanner(obj){
387        let popup = obj.popup
388        let linkArr = []
389        LEGAL_DOCS.forEach(e=>{
390            linkArr.push(`<a class="legal_link" data-type="${e.docType}">${e.docName}</a>`)
391        })
392        let logo = popup.logoUrl || '',img = ''
393        if(logo){
394            logo = $.imgxaf($.handleDataImg(logo),104)
395            img = `<div class="c_logo"><img src="${logo}" alt='logo' title='logo' ></div>`
396        }
397        let width = '',style = ``
398        if(popup.layoutTypeSize){
399            width = popup.layoutTypeSize
400        }
401        if(width){
402            style = `style="width:${width}%"`
403        }
404        let html = `<div class="cookieBanner ${popup.layoutType?popup.layoutType.toLowerCase():"bottom_left"}" ${style} id="cookieBanner">
405            <div class="c_stripe"></div>
406            <div class="c_inner">
407                <div class="c_top">
408                    <div class="c_brand">
409                        ${img}
410                        <div class="c_title">${popup.title}</div>
411                    </div>
412                    <button class="c_close">×</button>
413                </div>
414                <div class="c_body">${popup.contentDesc}</div>
415                <div class="c_btns">
416                    <button class="c_btn c_accept js_acceptAll">${$t('gdpr_accessAll')}</button>
417                    <div class="c_btn-row">
418                        <button class="c_btn c_reject js_rejectAll">${$t('gdpr_rejectAll')}</button>
419                        <button class="c_btn c_more js_showPrefCenter">${$t('gdpr_more')}</button>
420                    </div>
421                </div>
422                <div class="c_foot">
423                    <div class="c_links">
424                        ${linkArr.join("")}
425                    </div>
426                </div>
427            </div>
428        </div>`
429        return html
430    }
431    //cookie 偏好设置
432    function prefOverlay(config,dict){
433        let popup = config.popup
434        let arr = []
435        let iconList = [
436            {
437                code:'necessary',
438                icon:'🔒',
439                bgColor:'#f6ffed'
440            },
441            {
442                code:'functional',
443                icon:'⚙️',
444                bgColor:'#e8f0fe'
445            },
446            {
447                code:'analytics',
448                icon:'📈',
449                bgColor:'#fff7e6'
450            },
451            {
452                code:'marketing',
453                icon:'📢',
454                bgColor:'#fff0f6'
455            },
456            {
457                code:'other',
458                icon:'📦',
459                bgColor:'#f0f5ff'
460            }
461        ]
462        let cookieList = getAllCookies()
463        let lastAction = config.lastAction || {}
464        config.categoryList.forEach(e=>{
465            let code = e.categoryCode.toLowerCase()
466            let dictObj = dict[e.categoryCode] || []
467            let dictArr = []
468            dictObj.forEach(d=>{
469                if(d.isWildcard==0){
470                    let cookieObj = cookieList.find(n=>n.name == d.cookieKey)
471                    if(cookieObj){
472                        localCookie[code].push(cookieObj.name)
473                        dictArr.push(`<div class="ck-item">
474                            <div class="ck-name">${d.cookieKey}</div>
475                            <div>
476                                <div class="ck-meta">${d.description}</div>
477                            </div>
478                        </div>`)
479                    }
480                }else if(d.isWildcard==1){
481                    let cookieObj = cookieList.find(n=>n.name.startsWith(d.cookieKey))
482                    if(cookieObj){
483                        dictArr.push(`<div class="ck-item">
484                            <div class="ck-name">${d.cookieKey}</div>
485                            <div>
486                                <div class="ck-meta">${d.description}</div>
487                            </div>
488                        </div>`)
489                    }
490                }
491            })
492            let iconObj = iconList.find(n=>n.code === code) || {}
493            let cateRight = `<div class="cat_right">
494                <span class="always-on">${$t('gdpr_open')}</span>
495                <span class="cat_expand" data-key="necessary">▼</span>
496            </div>`
497            let checked = Boolean(lastAction[code]) ? 'checked' : ''
498            if(code!=='necessary'){
499                cateRight = `<div class="cat_right">
500                    <label class="ptoggle">
501                        <input type="checkbox" ${checked} id="tog-${code}">
502                        <div class="pt-track"></div>
503                    </label>
504                    <span class="cat_expand" data-key="${code}">▼</span>
505                </div>`
506            }
507            arr.push(`<div class="cat_row" id="cat_${code}">
508                <div class="cat_hd">
509                    <div class="cat_ic" style="background:${iconObj.bgColor||''}">${iconObj.icon || ''}</div>
510                    <div class="cat_info">
511                        <div class="cat_name">${e.categoryName}</div>
512                    </div>
513                    ${cateRight}
514                </div>
515                <div class="cat_detail">
516                    <div class="ck-list">
517                        ${dictArr.join("")}
518                    </div>
519                </div>
520            </div>`)
521        })
522        let logo = config.popup.logoUrl || '',img = ''
523        if(logo){
524            logo = $.imgxaf($.handleDataImg(logo),104)
525            img = `<div class="pref_hd-logo"><img src="${logo}" alt='logo' title='logo' ></div>`
526        }
527        let html = `<div class="prefOverlay" id="prefOverlay">
528            <div class="pref_modal">
529                <!-- Header -->
530                <div class="pref_hd">
531                    <div class="pref_hd-left">
532                        ${img}
533                        <div>
534                            <h2>${popup.title}</h2>
535                        </div>
536                    </div>
537                    <button class="pref_close" id="hidePrefCenter">×</button>
538                </div>
539                <!-- Intro -->
540                <div class="pref_intro">${config.popup.contentDesc}</div>
541                <!-- Categories -->
542                <div class="pref_body">
543                    ${arr.join("")}
544                </div>
545                <!-- Footer -->
546                <div class="pref_ft">
547                    <div class="pref_ft-left">
548                        <button class="pref_reject-link js_rejectAll">${$t('gdpr_rejectAll')}</button>
549                    </div>
550                    <button class="pref_save js_savePreferences">${$t('gdpr_custom')}</button>
551                    <button class="pref_accept js_acceptAll">${$t('gdpr_accessAll')}</button>
552                </div>
553            </div>
554        </div>`
555        return html
556    }
557    //cookie标记
558    function consentBadge(){
559        let html = `<div id="consentBadge" class="consentBadge js_showPrefCenter">
560            <div class="c_dot" id="cDot"></div>
561            <span class="c_badgeText"></span>
562            <span class="c_edit">✏️</span>
563        </div>`
564        return html
565    }
566    //隐私政策等弹窗
567    function legalOverlay(){
568        let html = `<div id="legalOverlay" class="legalOverlay">
569            <div class="legal_modal">
570                <div class="legal_modal-hd">
571                    <h3 id="legalModalTitle"></h3>
572                    <button class="lm-close js_closeLegal">×</button>
573                </div>
574                <div class="legal_modal-body" id="legalModalBody"></div>
575                <div class="legal_modal-ft">
576                    <span id="legalModalUpdated"></span>
577                    <span id="legalModalDsarLink" style="display: inline; margin-left: 12px;">
578                        <a class="legal_del-data" id="showDsarModal">${$t('gdpr_deleteApply')}</a>
579                    </span>
580                    <button class="js_closeLegal">${$t('gdpr_close')}</button>
581                </div>
582            </div>
583        </div>`
584        return html
585    }
586    //删除我的数据弹窗
587    function dsarModal(){
588        let html = `<div id="dsarModal" class="dsarModal">
589            <div class="dsar_modal">
590                <!-- ── 表单状态 ── -->
591                <div id="dsarFormArea" class="dsar_formArea">
592                    <div class="dsar_formTitle">${$t('gdpr_deleteTitle')}</div>
593                    <div class="dsar_formDesc">${$t('gdpr_deletePrompt',[30])}</div>
594
595                    <!-- 邮箱输入 -->
596                    <div class="dsar_formCon">
597                        <label class="dsar_formLabel">${$t('gdpr_deleteEmail')}</label>
598                        <input class="dsar_formInput" id="dsarEmail" type="email" placeholder="[email protected]">
599                        <!-- 错误提示条 -->
600                        <div class="dsar_errBar" id="dsarErrBar">
601                            <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" style="flex-shrink:0"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"></path></svg>
602                            <span id="dsarErrMsg">${$t('gdpr_deleteEmailMsg')}</span>
603                        </div>
604                    </div>
605
606                    <!-- 警告说明 -->
607                    <div class="dsar_warning">${$t('gdpr_deletePrompt2',[30])}</div>
608
609                    <!-- 操作按钮 -->
610                    <div class="dsar_operate">
611                        <button class="dsar_submitBtn" id="dsarSubmitBtn">${$t('gdpr_deleteBtn')}</button>
612                        <button class="dsar_closeBtn js_closeDsarModal">${$t('gdpr_deleteCancel')}</button>
613                    </div>
614                </div>
615                <!-- ── 成功状态 ── -->
616                <div class="dsar_success" id="dsarSuccessArea">
617                    <div class="dsar_successIcon">✅</div>
618                    <div class="dsar_successH1">${$t('gdpr_applySuc')}</div>
619                    <div class="dsar_successH2">${$t('gdpr_applyPrompt')}</div>
620                    <div class="dsar_successEmail" id="dsarConfirmEmail"></div>
621                    <!-- 处理流程 -->
622                    <div class="dsar_process">
623                        <div class="dsar_processTitle">${$t('gdpr_applyProgress')}</div>
624                        <div class="dsar_processCon">
625                            <div class="dsar_processItem">
626                                <div class="dsar_processNum" style="background:#e6f7ff;color:#1677ff;">1</div>
627                                <div class="dsar_processContent">${$t('gdpr_applyPrompt2',[30])}</div>
628                            </div>
629                            <div class="dsar_processItem">
630                                <div class="dsar_processNum" style="background:#fff7e6;color:#fa8c16;">2</div>
631                                <div class="dsar_processContent">${$t('gdpr_applyPrompt3')}</div>
632                            </div>
633                            <div class="dsar_processItem">
634                                <div class="dsar_processNum" style="background:#f6ffed;color:#52c41a;">3</div>
635                                <div class="dsar_processContent">${$t('gdpr_applyPrompt4')}</div>
636                            </div>
637                        </div>
638                    </div>
639                    <button class="dsar_closeBtn js_closeDsarModal">${$t('gdpr_know')}</button>
640                </div>
641            </div>
642        </div>`
643        return html
644    }
645    // 消息提示条
646    function toast(msg) {
647        let id = 'toast'+ +new Date()
648        let html = `<div class="cookie_toast" id="${id}">
649            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="20 6 9 17 4 12"/></svg>
650            <span>${msg}</span>
651        </div>`
652        $("body").append(html)
653        $(`#${id}`).addClass('show')
654        let toastT = setTimeout(() => $(`#${id}`).removeClass("show"), 2800);
655        let toastT2 = setTimeout(() => $(`#${id}`).remove(), 3000);
656    }
657
658    return {
659        init : init
660    };
661})

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.