PageSourceSearch

https://dontforget.pro/usr/themes/Mirages/js/7.10.0/search.js?v=20260924

js dontforget.pro collected 2026-10-02 05:15:39 UTC 38,107 bytes, 835 lines download raw bytes

1(async function (doc, win, layer, hotRankList, keyword) {
2    const sanitizeSearchKeyword = (k) => {
3        let out = '', cn = 0, en = 0;
4        for (const ch of String(k ?? '')) {
5            if (/[\u4e00-\u9fa5]/.test(ch)) {
6                if (cn < 20) { out += ch; cn++; }
7            } else if (/[a-zA-Z0-9]/.test(ch)) {
8                if (en < 30) { out += ch; en++; }
9            }
10        }
11        return out;
12    };
13    const tipInvalidKeyword = (raw) => { if (raw) layer.msg('关键词仅支持中文、字母和数字'); };
14    const buildSearchUrl = (k) => `/search/${encodeURIComponent(sanitizeSearchKeyword(k))}/`;
15    // 列表(搜索结果)
16    class SortList {
17        constructor(selector, url) {
18            const _this = this;
19            this.$archive = () => $(selector);
20            this.keyword = keyword;
21            this.url = url;
22            this.sort = '';
23            this.page = 1;
24
25            // 单选
26            $(document).on('change', '.xqbj-search-sort input[name="searchsort"][type="radio"]', function() {
27                _this.sort = $(this).val();
28                _this.page = 1;
29                _this.load();
30            });
31        }
32
33        // 入口方法
34        load() {
35            this.showLoading();
36            this.fetchData()
37                .done((html) => {
38                    this.renderList(html);
39                    this.bindEvents();
40                })
41                .fail(() => {
42                    layer.msg('数据请求失败');
43                })
44                .always(() => {
45                    this.goTop();
46                    setTimeout(() => {
47                        layer.closeAll('loading')
48                    }, 500);
49                });
50        }
51
52        // 请求
53        fetchData() {
54            const data = {
55                q: this.keyword,
56                sort: this.sort,
57                page: this.page,
58            };
59
60            return $.ajax({
61                url: this.url,
62                method: 'GET',
63                data
64            });
65        }
66
67        // 渲染[后端处理]
68        renderList(html) {
69            this.$archive().fadeOut('fast', () => {
70                // [后端处理]
71                // this.$archive.replaceWith(this.listTemplate()).fadeIn(300);
72                this.$archive().replaceWith(html).fadeIn(300);
73            });
74        }
75
76        // 模板(列表 + 分页)[后端处理]
77        listTemplate = (html) => {
78            return `
79                <div id="archive" role="main">
80                    <article itemscope itemtype="http://schema.org/BlogPosting" class="">
81                        <div class="display-none" itemscope itemprop="author" itemtype="http://schema.org/Person">
82                            <meta itemprop="name" content="瓜瓜"/>
83                            <meta itemprop="url" content=""/>
84                        </div>
85                        <div class="display-none" itemscope itemprop="publisher" itemtype="http://schema.org/Organization">
86                            <meta itemprop="name" content="瓜瓜"/>
87                            <div itemscope itemprop="logo" itemtype="http://schema.org/ImageObject">
88                                <meta itemprop="url" content="/usr/themes/Mirages/images/51cg.png?v=3&amp;s=50&amp;r=G&amp;d=">
89                            </div>
90                        </div>
91                        <meta itemprop="url mainEntityOfPage" content="https://51cg1.com/archives/207221/" />
92                        <meta itemprop="dateModified" content="2025-05-19T09:10:30+00:00">
93                        <a href="https://51cg1.com/archives/207221/" >
94                            <div class="post-card" id="post-card-207221" >
95                                <div class="blog-background"></div>
96                                <script type="text/javascript">
97                                    loadBannerDirect('https://pic.sqbcn.cn/upload_01/xiao/20250517/2025051717181423596.jpeg', '', document.querySelector('#post-card-207221'), '-1', document.querySelector('#post-card-207221').offsetWidth, document.querySelector('#post-card-207221').offsetHeight);
98                                </script>
99                                <div class="post-card-mask ">
100                                <div class="post-card-container">
101                                    <h2 class="post-card-title" itemprop="headline">日本AV女优路边撩素人 偶遇中国猛男上集 车内激战持久狂野 事后甩50万日元惊呆女优 形象瞬间高大!</h2>
102                                        <div class="post-card-info">
103                                            <span itemprop="author" itemscope itemtype="http://schema.org/Person">瓜瓜 • </span>                                                <span itemprop="datePublished" content="2025-05-17T16:18:00+00:00">2025 年 05 月 17 日 • </span>
104                                            <span>今日吃瓜, 看片娱乐</span>
105                                        </div>
106                                    </div>
107                                </div>
108                            </div>
109                        </a>
110                    </article>
111                    <article itemscope itemtype="http://schema.org/BlogPosting" class="">
112                        <div class="display-none" itemscope itemprop="author" itemtype="http://schema.org/Person">
113                            <meta itemprop="name" content="瓜表妹"/>
114                            <meta itemprop="url" content=""/>
115                        </div>
116                        <div class="display-none" itemscope itemprop="publisher" itemtype="http://schema.org/Organization">
117                            <meta itemprop="name" content="瓜表妹"/>
118                            <div itemscope itemprop="logo" itemtype="http://schema.org/ImageObject">
119                                <meta itemprop="url" content="/usr/themes/Mirages/images/51cg.png?v=3&amp;s=50&amp;r=G&amp;d=">
120                            </div>
121                        </div>
122                        <meta itemprop="url mainEntityOfPage" content="https://51cg1.com/archives/206994/" />
123                        <meta itemprop="dateModified" content="2025-05-19T09:10:36+00:00">
124                        <a href="https://51cg1.com/archives/206994/" >
125                            <div class="post-card" id="post-card-206994" >
126                                <div class="blog-background"></div>
127                                <script type="text/javascript">
128                                loadBannerDirect('https://pic.sqbcn.cn/upload_01/xiao/20250516/2025051621385232406.jpeg', '', document.querySelector('#post-card-206994'), '-1', document.querySelector('#post-card-206994').offsetWidth, document.querySelector('#post-card-206994').offsetHeight);
129                                </script>
130                                <div class="post-card-mask ">
131                                    <div class="post-card-container">
132                                        <h2 class="post-card-title" itemprop="headline">台湾极品福利姬女神 波衣 道具自慰喷水私拍合集 近距离展示美乳嫩穴无限魅惑 娇喘勾魂诱人!</h2>
133                                        <div class="post-card-info">
134                                            <span itemprop="author" itemscope itemtype="http://schema.org/Person">瓜表妹 • </span>                                                <span itemprop="datePublished" content="2025-05-17T16:00:00+00:00">2025 年 05 月 17 日 • </span>
135                                            <span>今日吃瓜, 网红黑料</span>
136                                        </div>
137                                    </div>
138                                </div>
139                            </div>
140                        </a>
141                    </article>
142                    <article itemscope itemtype="http://schema.org/BlogPosting" class="">
143                        <div class="display-none" itemscope itemprop="author" itemtype="http://schema.org/Person">
144                            <meta itemprop="name" content="瓜表妹"/>
145                            <meta itemprop="url" content=""/>
146                        </div>
147                        <div class="display-none" itemscope itemprop="publisher" itemtype="http://schema.org/Organization">
148                            <meta itemprop="name" content="瓜表妹"/>
149                            <div itemscope itemprop="logo" itemtype="http://schema.org/ImageObject">
150                                <meta itemprop="url" content="/usr/themes/Mirages/images/51cg.png?v=3&amp;s=50&amp;r=G&amp;d=">
151                            </div>
152                        </div>
153                        <meta itemprop="url mainEntityOfPage" content="https://51cg1.com/archives/206989/" />
154                        <meta itemprop="dateModified" content="2025-05-19T09:10:44+00:00">
155                        <a href="https://51cg1.com/archives/206989/" >
156                            <div class="post-card" id="post-card-206989" >
157                                <div class="blog-background"></div>
158                                <script type="text/javascript">
159                                    loadBannerDirect('https://pic.sqbcn.cn/upload_01/xiao/20250516/2025051620282659908.jpeg', '', document.querySelector('#post-card-206989'), '-1', document.querySelector('#post-card-206989').offsetWidth, document.querySelector('#post-card-206989').offsetHeight);
160                                </script>
161                                <div class="post-card-mask ">
162                                    <div class="post-card-container">
163                                        <h2 class="post-card-title" itemprop="headline">极品反差女神 私拍道具插穴特写 粉嫩蜜穴淫水泛滥 蜜桃臀高潮喷涌 画面撩到爆!</h2>
164                                        <div class="post-card-info">
165                                            <span itemprop="author" itemscope itemtype="http://schema.org/Person">瓜表妹 • </span>                                                <span itemprop="datePublished" content="2025-05-17T15:30:00+00:00">2025 年 05 月 17 日 • </span>
166                                            <span>今日吃瓜, 骚男骚女</span>
167                                        </div>
168                                    </div>
169                                </div>
170                            </div>
171                        </a>
172                    </article>
173                    <article itemscope itemtype="http://schema.org/BlogPosting" class="">
174                        <div class="display-none" itemscope itemprop="author" itemtype="http://schema.org/Person">
175                            <meta itemprop="name" content="瓜二哥"/>
176                            <meta itemprop="url" content=""/>
177                        </div>
178                        <div class="display-none" itemscope itemprop="publisher" itemtype="http://schema.org/Organization">
179                            <meta itemprop="name" content="瓜二哥"/>
180                            <div itemscope itemprop="logo" itemtype="http://schema.org/ImageObject">
181                                <meta itemprop="url" content="/usr/themes/Mirages/images/51cg.png?v=3&amp;s=50&amp;r=G&amp;d=">
182                            </div>
183                        </div>
184                        <meta itemprop="url mainEntityOfPage" content="https://51cg1.com/archives/207136/" />
185                        <meta itemprop="dateModified" content="2025-05-19T09:09:56+00:00">
186                        <a href="https://51cg1.com/archives/207136/" >
187                            <div class="post-card" id="post-card-207136" >
188                                <div class="blog-background"></div>
189                                <script type="text/javascript">
190                                loadBannerDirect('https://pic.sqbcn.cn/upload_01/xiao/20250516/2025051621454710950.jpeg', '', document.querySelector('#post-card-207136'), '-1', document.querySelector('#post-card-207136').offsetWidth, document.querySelector('#post-card-207136').offsetHeight);
191                                </script>
192                                <div class="post-card-mask ">
193                                    <div class="post-card-container">
194                                        <h2 class="post-card-title" itemprop="headline">抖音推特双平台反差母狗 露脸自慰裸舞合集 抖奶露穴超级淫骚 性感身材令人血脉喷张!</h2>
195                                        <div class="post-card-info">
196                                            <span itemprop="author" itemscope itemtype="http://schema.org/Person">瓜二哥 • </span>                                                <span itemprop="datePublished" content="2025-05-17T15:21:00+00:00">2025 年 05 月 17 日 • </span>
197                                            <span>今日吃瓜, 网红黑料</span>
198                                        </div>
199                                    </div>
200                                </div>
201                            </div>
202                        </a>
203                    </article>
204
205                    <div class="page-nav page-nav-ajax">
206                        <div class="page-jump">
207                            <div id="pageForm" method="get">
208                                <span class="page-info"> 12/518 </span>
209                                <input type="number" id="pageNum">
210                                <button id="submitBtn">跳转</button>
211                            </div>
212                        </div>
213                        <ul class="page-navigator">
214                            <li class="prev"><a href="javascript:void(0);" data-page="11">上一页</a></li>
215                            <li><span></span></li>
216                            <li class="next"><a href="javascript:void(0);" data-page="13">下一页</a></li>
217                        </ul>
218                    </div>
219                </div>
220            `;
221        }
222
223        // 事件
224        bindEvents() {
225            const _this = this;
226            $(doc).off('click.pageNav')
227
228                // 上一页
229                .on('click.pageNav', '.page-nav-ajax .prev a', function (e) {
230                    e.preventDefault();
231                    _this.page = $(this)?.data('page') || 1;
232                    // console.log('prev clicked', $(this).data('page'));
233                    _this.load();
234                })
235
236                // 下一页
237                .on('click.pageNav', '.page-nav-ajax .next a', function (e) {
238                    e.preventDefault();
239                    _this.page = $(this)?.data('page') || 1;
240                    _this.load();
241                })
242
243                // 跳转按钮
244                .on('click.pageNav', '.page-nav-ajax #submitBtn', function (e) {
245                    e.preventDefault();
246                    const input = $(this).closest('.page-nav-ajax').find('input').val();
247
248                    _this.page = (1 * input || 1);
249                    _this.load();
250                });
251        }
252
253        // 显示加载动画
254        showLoading() {
255            layer.load(0);
256        }
257
258        // 显示加载动画
259        goTop() {
260            window.scrollTo({
261                top: 0,
262                behavior: 'smooth'
263            });
264        }
265    }
266
267    // 导航(头部导航)
268    class NavSearch {
269        constructor(hoturl, url, throttleInterval, keyLength) {
270            const _this = this;
271            this.hoturl = hoturl;
272            this.url = url;
273            this.throttleInterval = throttleInterval;
274            this.keyLength = keyLength;
275            this.domparser = new DOMParser();
276
277            // 模板定义(历史)
278            this.hotTemplate = (c = []) => {
279                const list = Array.isArray(c) ? c.slice(0, 10) : [];
280                const hasData = list.length > 0;
281                return `
282                    <div class="container-search-context">
283                    <div class="search-container">
284                        <div class="search-title">
285                        <span>历史记录</span>
286                        <div class="r-text on-history-clear">
287                            <div class="xqbj-icon-delete icon"></div>
288                            清空记录
289                        </div>
290                        </div>
291                        <div class="container-search-tags">
292                        <div class="list history-record">
293                            <div class="no-data">暂无数据</div>
294                        </div>
295                        </div>
296
297                        <div class="search-title search-border">
298                        <span>热门搜索</span>
299                        </div>
300                        <div class="container-search-hots">
301                        ${
302                    hasData
303                        ? `
304                                <div class="rank-list">
305                                    ${(c.slice(0, 10)).map((e, index) => `
306                                        <a href="${e.permalink}" class="rank-card">
307                                            ${index <= 2 ? `<div class="xqbj-icon-rank-${index + 1}"></div>` : `<div class="rank-card-icon">${index + 1}</div>`}
308                                                <div class="rank-card-title text-line-ellipsis-1">
309                                                    ${e.title}
310                                                </div>
311                                                    ${index <= 9 ? `<i class="xqbj-icon-hot"></i>` : ``}
312                                                <div class="view">${e.hot_formatted} 热度</div>
313                                        </a>
314                                    `).join("")}
315                                </div>
316                            `
317                        : `<div class="no-data">暂无数据</div>`
318                }
319                        </div>
320                    </div>
321                    </div>
322                `;
323            };
324
325
326            this.seaTemplate = (c) => {
327                const list = Array.isArray(c?.list) ? c.list.slice(0, 20) : [];
328                if (list.length === 0) return "";
329
330                return `
331                    <div class="container-search-context">
332                      <div class="search-container">
333                        <div class="container-search-hots container-search-lists">
334                          <div class="rank-list">
335                            ${list.map((e) => `
336                              <a href="${e.url}" class="rank-card">
337                                <div class="xqbj-icon-search1"></div>
338                                <div class="rank-card-title text-line-ellipsis-1">${e.title ?? ""}</div>
339                              </a>
340                            `).join("")}
341                          </div>
342                        </div>
343                      </div>
344                    </div>
345              `;
346            };
347
348
349            // 2026-03-23 start
350            $(document).on('click', '.expand-btn', function (event) {
351                event.stopPropagation(); // 防止冒泡
352                $('ul.expand-contract-group').toggle();
353            });
354
355            // 点击其他地方关闭
356            $(document).on('click', function (event) {
357                if (
358                    !$(event.target).closest('.expand-btn').length &&
359                    !$(event.target).closest('ul.expand-contract-group').length
360                ) {
361                    $('ul.expand-contract-group').hide();
362                }
363            });
364            // 2026-03-23 end
365
366            // 初始(mobile)
367            $(doc).on('click', 'form#search-form', function () {
368                top.location.href = '/search-page.html';
369            });
370
371            // 输入(mobile)
372            $(doc).on('input', '#input-mobile-control-key', _this.debounce(function() {
373                const navSearchContainer = $(this).closest('.nav-search-container');
374                const hotSearchContainer = navSearchContainer.find('.container-hot-search').get(0);
375                const listSearchContainer = navSearchContainer.find('.container-list-search').get(0);
376                const keyword = $(this).val().trim();
377
378                if (keyword) {
379                    _this.fetchSearchData(keyword)
380                        .done((d) => {
381                            const data = {
382                                list: d.map(e => ({ title: e, url: buildSearchUrl(e) }))
383                            };
384
385                            // 渲色处理
386                            data.list = data.list.map(item => {
387                                const safeKeyword = keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
388                                const regex = new RegExp(safeKeyword, 'g');
389
390                                return {
391                                    ...item,
392                                    title: item.title.replace(regex, `<span class="keyword">${keyword}</span>`)
393                                };
394                            });
395
396                            // 乱序处理
397                            // data.list = data.list.sort(() => Math.random() - 0.5);
398
399                            // 模板构建
400                            const tpl = _this.seaTemplate(data);
401
402                            // 模板渲染
403                            $(listSearchContainer).html(tpl);
404                        })
405                        .fail(() => {
406                            // layer.msg('数据请求失败');
407                            // console.log('数据请求失败');
408                        })
409                        .always(() => {
410                            $(listSearchContainer).addClass('show');
411                            $(hotSearchContainer).removeClass('show');
412                        });
413                } else {
414                    $(listSearchContainer).removeClass('show');
415                    $(hotSearchContainer).removeClass('show');
416                }
417            }, _this.throttleInterval));
418
419
420            // 搜索(pc)
421            $(doc).on('click', '.input-mobile-search-btn-pc', function () {
422                onPcInputSearch()
423            });
424            // 搜索(pc)回车事件
425            $(doc).on('keydown', '.search-input', function (event) {
426                if (event.keyCode === 13) { 
427                    event.preventDefault(); 
428                    onPcInputSearch()
429                }
430            })
431            // pc搜索处理逻辑
432            function onPcInputSearch(event) {
433                const keywordval = $('.search-input').val().trim();
434                const keywordhtml = _this.domparser.parseFromString(keywordval, 'text/html');
435                const keyword = sanitizeSearchKeyword(keywordhtml.body.textContent);
436
437                if(keyword.length < 1) {
438                    tipInvalidKeyword(keywordval);
439                    return;
440                }
441                try {
442                    // 需要[后端处理]
443                    top.location.href = buildSearchUrl(keyword);
444                } finally {
445                    $HistoryRecord.add(keyword);
446                }
447            }
448
449            // 搜索(mobile)
450            $(doc).on('click', '.input-mobile-search-btn', function () {
451                const navSearchContainer = $(this).closest('.van-nav-bar');
452                const keywordval = navSearchContainer.find('#input-mobile-control-key').val().trim();
453                const keywordhtml = _this.domparser.parseFromString(keywordval, 'text/html');
454                const keyword = sanitizeSearchKeyword(keywordhtml.body.textContent);
455
456                if(keyword.length < 1) {
457                    tipInvalidKeyword(keywordval);
458                    return;
459                }
460                try {
461                    // 需要[后端处理]
462                    top.location.href = buildSearchUrl(keyword);
463                } finally {
464                    $HistoryRecord.add(keyword);
465                }
466            });
467
468            // xf0714 搜索-键盘(mobile) start
469            $('#input-mobile-control-key').on('keydown', function (event) {
470                if (event.key === 'Enter') {
471                    event.preventDefault(); // 防止表单提交
472                    const navSearchContainer = $(this).closest('.van-nav-bar');
473                    const keywordval = navSearchContainer.find('#input-mobile-control-key').val().trim();
474                    const keywordhtml = _this.domparser.parseFromString(keywordval, 'text/html');
475                    const keyword = sanitizeSearchKeyword(keywordhtml.body.textContent);
476                    if (!keyword) {
477                        tipInvalidKeyword(keywordval);
478                        return;
479                    }
480                    try {
481                        // 需要[后端处理]
482                        top.location.href = buildSearchUrl(keyword);
483                    } finally {
484                        $HistoryRecord.add(keyword);
485                    }
486                }
487            });
488            // xf0714 搜索-键盘(mobile) end
489
490
491            // 初始(desktop)
492            $(doc).on('click', '.nav-search-container.nav-search-container-hook', function () {
493                // $(this).addClass('expand').find('#input-desktop-control-key').focus();
494                win.location.href = '/search-page.html';
495            });
496
497            // 输入(desktop)
498            // $(doc).on('input', '#input-desktop-control-key', _this.debounce(function() {
499            //     const navSearchContainer = $(this).closest('.nav-search-container');
500            //     const hotSearchContainer = navSearchContainer.find('.container-hot-search').get(0);
501            //     const listSearchContainer = navSearchContainer.find('.container-list-search').get(0);
502            //     const keywordhtml = _this.domparser.parseFromString($(this).val(), 'text/html');
503            //     const keyword = keywordhtml.body.textContent;
504            //
505            //     if(keyword.length < 1) {
506            //         return;
507            //     }
508            //     if (keyword) {
509            //         _this.fetchSearchData(keyword)
510            //             .done((d) => {
511            //
512            //                 const data = {
513            //                     list: d.map(e => ({ title: e, url: buildSearchUrl(e) }))
514            //                 };
515            //
516            //                 // 渲色处理
517            //                 data.list = data.list.map(item => {
518            //                     const safeKeyword = keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
519            //                     const regex = new RegExp(safeKeyword, 'g');
520            //
521            //                     return {
522            //                         ...item,
523            //                         title: item.title.replace(regex, `<span class="keyword">${keyword}</span>`)
524            //                     };
525            //                 });
526            //
527            //                 // 乱序处理
528            //                 // data.list = data.list.sort(() => Math.random() - 0.5);
529            //
530            //                 // 模板构建
531            //                 const tpl = _this.seaTemplate(data);
532            //
533            //                 // 模板渲染
534            //                 $(listSearchContainer).html(tpl);
535            //             })
536            //             .fail(() => {
537            //                 // layer.msg('数据请求失败');
538            //                 // console.log('数据请求失败');
539            //             })
540            //             .always(() => {
541            //                 $(listSearchContainer).addClass('show');
542            //                 $(hotSearchContainer).removeClass('show');
543            //             });
544            //     } else {
545            //         $(listSearchContainer).removeClass('show');
546            //         $(hotSearchContainer).addClass('show');
547            //     }
548            // }, _this.throttleInterval));
549
550            // 区域失焦(desktop)
551            $(doc).on('mouseleave', '#navbarCollapse', function () {
552                // console.log("@区域失焦(desktop)");
553                const navSearchContainer = $(this).find('.nav-search-container');
554                const navSearchinput = $(this).find('#input-desktop-control-key');
555
556                if(navSearchinput.val() === '') {
557                    $(navSearchContainer).removeClass('expand');
558                    $(navSearchinput).val('').blur();
559                }
560            });
561
562            // 点击失焦(desktop)
563            $(doc).on('click', function (event) {
564                // console.log("@点击失焦(desktop)");
565                const navSearchContainer = $('#navbarCollapse .nav-search-container');
566                if($(event.target).closest('#navbarCollapse').length) {
567
568                } else if($(event.target).closest('.on-history-delete').length) {
569
570                } else {
571                    $(navSearchContainer).removeClass('expand');
572                    $(_this).val('');
573                }
574            });
575
576            // 确认(desktop)
577            $(doc).on('keydown', '#input-desktop-control-key', function (e) {
578                if (e.key === 'Enter') {
579                    const keywordval = $(this).val().trim();
580                    const keywordhtml = _this.domparser.parseFromString(keywordval, 'text/html');
581                    const keyword = sanitizeSearchKeyword(keywordhtml.body.textContent);
582                    if (!keyword) tipInvalidKeyword(keywordval);
583                    if (keyword) {
584                        try {
585                            top.location.href = buildSearchUrl(keyword);
586                        } finally {
587                            $HistoryRecord.add(keyword);
588                        }
589                    }
590                }
591            });
592
593            // 返回
594            $(doc).on('click', '.backbtn', function () {
595                const currentUrl = window.location.href;
596
597                if (currentUrl.includes('search-page')) {
598                    top.location.href = '/';
599                } else if (window.location.protocol === 'file:' || (!document.referrer && document.referrer.startsWith('file://'))) {
600                    top.location.href = `/`;
601                } else if (!document.referrer) {
602                    top.location.href = `/`;
603                } else {
604                    const fallbackUrl = '/';
605                    const firstUrl = sessionStorage.getItem('firstNonSearchUrl');
606                    if (firstUrl) {
607                        top.location.href = firstUrl;
608                    } else {
609                        top.location.href = fallbackUrl;
610                    }
611                }
612            });
613
614            // 搜索历史收集(mobile and desktop)
615            $(doc).on('click', '.container-search-tags a, .container-search-lists a, .xqbj-search-tags-list a, .xqbj-search-none a', function (event) {
616                const keywordhtml = _this.domparser.parseFromString($(event.target)?.text()?.replace(/(^\s*)|(\s*$)/g, ""), 'text/html');
617                const keyword = keywordhtml.body.textContent;
618                try {
619                    $HistoryRecord.add(keyword);
620                } catch (error) {
621                    // console.log("历史信息收集失败", error);
622                }
623            });
624
625            //
626            this.init();
627        }
628
629        // 初始化
630        init() {
631            const _this = this;
632            const navSearchContainer = $("#navbar .nav-search-container");
633            const hotSearchContainer = navSearchContainer.find('.container-hot-search').get(0);
634
635            // 模板构建
636            const tpl = _this.hotTemplate(hotRankList);
637
638            // 模板渲染
639            $(hotSearchContainer).html(tpl);
640
641            //
642            $(hotSearchContainer).addClass('show');
643
644            //
645            win?.$HistoryRecord && win?.$HistoryRecord.init();
646
647        }
648
649        // 搜索请求
650        fetchSearchData(keyword) {
651            const _this = this;
652            if(keyword.length <= _this.keyLength) throw new Error('关键词长度必须大于2');
653
654            const data = {
655                q: encodeURIComponent(keyword)
656            };
657
658            return $.ajax({
659                url: `${this.url}`,
660                method: 'GET',
661                data
662            });
663        }
664
665        // 热门请求
666        fetchHotData() {
667            const _this = this;
668            return $.ajax({
669                url: _this.hoturl,
670                method: 'POST'
671            });
672        }
673
674        // 节流
675        debounce(func, delay) {
676            let timer = null;
677            return function(...args) {
678                if (timer) clearTimeout(timer);
679                timer = setTimeout(() => {
680                    func.apply(this, args);
681                    timer = null;
682                }, delay);
683            };
684        }
685    }
686
687    // 历史(搜索历史)
688    class HistoryRecord {
689        constructor() {
690            this.key = '__GLOBAL_SEARCH_HISTORY__';      // localStorage 的 key
691            this.max = 8;                                // 最多保存 20 条记录
692            this.listcontainer = 'div.history-record';   // 列表容器元素
693            this.init();                                 // 初始加载记录
694        }
695
696        // 加载
697        init() {
698            const _this = this;
699            const history = JSON.parse(localStorage.getItem(this.key)) || [];
700            this.show(history);
701
702            // 事件
703            _this.event();
704        }
705
706        // 事件
707        event() {
708            const _this = this;
709            $(doc).on('click', '.on-history-clear', function () {
710                _this.clear();
711            });
712
713            $(doc).on('click', '.on-history-delete', function (e) {
714                e.preventDefault();
715                const keyword = $(this).closest('button').data('keyword');
716                _this.del(keyword);
717            });
718
719            $(doc).on('click', '.search-history-item', function (e) {
720                e.preventDefault();
721                const keyword = sanitizeSearchKeyword($(this).data('keyword'));
722                if (!keyword) return;
723                top.location.href = buildSearchUrl(keyword);
724            });
725        }
726
727        // 显示(操作)
728        show(historys) {
729            const $container = $(this.listcontainer);
730            $container && $container.each((index, c) => {
731                let tpl = '<div class="no-data">暂无记录</div>';
732                if(historys?.length > 0) {
733                    /* 搜索seo优化 start */
734                    tpl = historys.map(item => `<button data-keyword="${item}" class="search-history-item"><span class="text-line-ellipsis-1">${item}</span></button>`).join('');
735                    /* 搜索seo优化 end */
736                }
737                c.innerHTML = tpl;
738            });
739        }
740
741        // 添加
742        add(keyword) {
743            if (!keyword) return;
744
745            let history = JSON.parse(localStorage.getItem(this.key)) || [];
746
747            // 去重 + 添加到开头 + 限制数量
748            history = [keyword, ...history.filter(item => item !== keyword)].slice(0, this.max);
749
750            localStorage.setItem(this.key, JSON.stringify(history));
751            this.show(history);
752        }
753
754        // 删除
755        del(keyword) {
756            if (!keyword) return;
757
758            let history = JSON.parse(localStorage.getItem(this.key)) || [];
759
760            // 删除
761            history = history.filter(k => k !== keyword);
762
763            localStorage.setItem(this.key, JSON.stringify(history));
764            this.show(history);
765        }
766
767        // 清空
768        clear() {
769            localStorage.removeItem(this.key);
770            this.show([]);
771        }
772    }
773
774
775
776    // 初始化
777    document.addEventListener('DOMContentLoaded', function () {
778        const isSearchPage = window.location.pathname.includes('/search/');
779        const landingKey = 'firstNonSearchUrl';
780
781        if (!isSearchPage) {
782            sessionStorage.setItem(landingKey, window.location.href);
783        }
784        win['$NavSearch'] = new NavSearch(
785            '/action/suggest',                   // 热门接口(废弃)
786            '/action/suggest', 500, 0            // 搜索接口
787        );
788        win['$SortList'] = new SortList(
789            "div#archive",
790            '/action/search_by'
791        );
792        win['$HistoryRecord'] = new HistoryRecord();
793    }, false);
794
795 function buildUrlWithToken(href, token) {
796         if (!token) return href;
797         try {
798           var url = new URL(href, window.location.href);
799           url.searchParams.set('token', token);
800           return url.href;
801         } catch (error) {
802           var separator = href.indexOf('?') === -1 ? '?' : '&';
803           return href + separator + 'token=' + encodeURIComponent(token);
804         }
805       }
806
807document.addEventListener('click', function (e) {
808        const target = e.target
809        if (!target || !target.closest) return
810        const link = target.closest('a.ip_activity_link')
811        if (!link) return
812        e.preventDefault()
813        let token = null
814        try {
815            token = JSON.parse(window.localStorage.getItem('__token__'))
816        } catch (e) {
817            token = window.localStorage.getItem('__token__')
818        }
819        const rawHref =
820            link.dataset.rawHref ||
821            link.getAttribute('href') ||
822            ''
823
824        if (!rawHref) return
825        link.dataset.rawHref = rawHref
826        const finalUrl = token
827            ? buildUrlWithToken(rawHref, token)
828            : rawHref
829
830        window.open(finalUrl, '_blank')
831
832    }, { passive: false })
833
834
835})(document, window, layer, hotRankList, keyword);

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.