大体完成

剩下有个问题是排序之后,点击其他part跳转的问题,在156-159行

需要先研究一下b站原来是如何实现的

篡改猴脚本

// ==UserScript==
// @name         B站视频合集排序
// @namespace    http://tampermonkey.net/
// @version      1.4
// @description  对B站视频合集重新排序
// @author       武幻空
// @match        https://www.bilibili.com/video/*
// @icon         https://www.bilibili.com/favicon.ico?v=1
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    const checkEpisodes = () => {
        return new Promise((resolve, reject) => {
            let attempts = 0;
            const maxAttempts = 120;

            const interval = setInterval(() => {
                attempts++;
                if (window.__INITIAL_STATE__?.videoData?.ugc_season?.sections[0]?.episodes?.length) {
                    clearInterval(interval);
                    resolve(window.__INITIAL_STATE__.videoData.ugc_season.sections[0].episodes);
                } else if (attempts >= maxAttempts) {
                    clearInterval(interval);
                    reject(new Error("检测超时:未找到视频列表"));
                }
            }, 1000);
        });
    };

    const addButtonContainer = () => {
        return new Promise((resolve, reject) => {
            let attempts = 0;
            const maxAttempts = 120;

            const interval = setInterval(() => {
                attempts++;
                const targetContainer = document.getElementsByClassName("video-pod video-pod")[0];
                if (targetContainer) {
                    clearInterval(interval);
                    resolve(targetContainer);
                } else if (attempts >= maxAttempts) {
                    clearInterval(interval);
                    reject(new Error("检测超时:未找到插入按钮的位置"));
                }
            }, 1000);
        });
    };

    function applyStyles(element) {
        element.style.padding = '14px 0px 12px';
        //element.style.border = '0px 0px 1px solid #E3E5E7';
        element.style.borderRadius = '6px';
        element.style.fontWeight = 'bold';
        element.style.fontSize = '14px';
        element.style.display = 'flex';
        element.style.flexDirection = 'column';
        element.style.alignItems = 'flex-start';
    }

    function createSortContainer(episodes) {
        const container = document.createElement("div");
        container.id = "sort-statistics";
        container.innerHTML = "<strong>视频集合排序</strong>";
        applyStyles(container);

        const controlRow = document.createElement('div');
        controlRow.style.display = 'flex';
        controlRow.style.alignItems = 'center';
        controlRow.style.marginTop = '10px';

        const sortSelect = document.createElement('select');
        sortSelect.style.padding = '5px 8px';
        sortSelect.style.borderRadius = '4px';
        sortSelect.style.border = '1px solid #dcdcdc';
        sortSelect.style.backgroundColor = '#fff';
        sortSelect.style.marginRight = '10px';
        sortSelect.innerHTML = `
            <option value="id">按 ID 排序</option>
            <option value="ctime">按发布时间排序</option>
            <option value="title">按标题排序</option>
        `;
        controlRow.appendChild(sortSelect);

        const orderButton = document.createElement('button');
        orderButton.innerText = '升序';
        orderButton.style.padding = '5px 10px';
        orderButton.style.border = 'none';
        orderButton.style.borderRadius = '4px';
        orderButton.style.backgroundColor = '#409eff';
        orderButton.style.color = '#fff';
        orderButton.style.cursor = 'pointer';
        orderButton.style.fontSize = '14px';
        orderButton.style.marginRight = '10px';

        let isAscending = true;
        orderButton.onclick = () => {
            isAscending = !isAscending;
            orderButton.innerText = isAscending ? '升序' : '降序';
        };
        controlRow.appendChild(orderButton);

        const sortButton = document.createElement('button');
        sortButton.innerText = '确认排序';
        sortButton.style.padding = '5px 10px';
        sortButton.style.border = 'none';
        sortButton.style.borderRadius = '4px';
        sortButton.style.backgroundColor = '#67c23a';
        sortButton.style.color = '#fff';
        sortButton.style.cursor = 'pointer';
        sortButton.style.fontSize = '14px';

        sortButton.onclick = () => {
            const sortBy = sortSelect.value;
            sortEpisodes(sortBy, isAscending, episodes);
        };
        controlRow.appendChild(sortButton);

        container.appendChild(controlRow);

        return container;
    }

    function sortEpisodes(sortMode, isAscending, episodes) {
        const currentScrolledElement = document.querySelector('.video-pod__item[data-scrolled="true"]');
        const currentScrolledKey = currentScrolledElement ? currentScrolledElement.getAttribute('data-key') : null;

        episodes.sort((a, b) => {
            let compareA, compareB;
            if (sortMode === 'id') {
                compareA = a.id;
                compareB = b.id;
                return isAscending ? compareA - compareB : compareB - compareA;
            } else if (sortMode === 'ctime') {
                compareA = a.arc.ctime;
                compareB = b.arc.ctime;
                return isAscending ? compareA - compareB : compareB - compareA;
            } else if (sortMode === 'title') {
                compareA = a.arc.title;
                compareB = b.arc.title;
                return isAscending ? compareA.localeCompare(compareB) : compareB.localeCompare(compareA);
            }
        });

        const videoListContainer = document.querySelector('.video-pod__list.section');
        if (videoListContainer) {
            videoListContainer.innerHTML = '';

            episodes.forEach((episode) => {
                const videoItem = document.createElement('div');
                videoItem.className = 'pod-item video-pod__item simple';
                videoItem.dataset.key = episode.bvid;

                // 添加点击事件
                videoItem.onclick = () => {
                    window.location.href = `https://www.bilibili.com/video/${episode.bvid}`;
                };

                if (episode.bvid === currentScrolledKey) {
                    videoItem.setAttribute('data-scrolled', 'true');
                    videoItem.innerHTML = `
                        <div class="single-p">
                            <div class="simple-base-item active normal">
                                <div title="${episode.title}" class="title">
                                    <div class="playing-gif" style="display:;"></div>
                                    <div class="title-txt">${episode.title}</div>
                                </div>
                                <div class="stats">
                                    <div class="stat-item duration">
                                        ${(episode.arc.duration / 60).toFixed(0)}:${(episode.arc.duration % 60).toString().padStart(2, '0')}
                                    </div>
                                </div>
                            </div>
                        </div>
                    `;
                } else {
                    videoItem.innerHTML = `
                        <div class="single-p">
                            <div class="simple-base-item normal">
                                <div title="${episode.title}" class="title">
                                    <div class="playing-gif" style="display:none;"></div>
                                    <div class="title-txt">${episode.title}</div>
                                </div>
                                <div class="stats">
                                    <div class="stat-item duration">
                                        ${(episode.arc.duration / 60).toFixed(0)}:${(episode.arc.duration % 60).toString().padStart(2, '0')}
                                    </div>
                                </div>
                            </div>
                        </div>
                    `;
                }

                videoListContainer.appendChild(videoItem);
            });
            // 在这里添加滚动逻辑
            if (currentScrolledElement) {
                const newScrolledElement = videoListContainer.querySelector(`.pod-item[data-key="${currentScrolledKey}"]`);
                if (newScrolledElement) {
                    newScrolledElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
                }
            }
        } else {
            console.error("未找到视频展示容器");
        }
    }

    async function main() {
        try {
            const episodes = await checkEpisodes();
            const targetContainer = await addButtonContainer();

            const sortContainer = createSortContainer(episodes);
            targetContainer.insertBefore(sortContainer, targetContainer.firstChild);
        } catch (error) {
            console.error(error.message);
        }
    }

    main();
})();