摸鱼给Linuxdo写了个油猴主题

主题自动获取bing每日壁纸,天气信息

佬友们赏个脸把玩一下 :yum:

// ==UserScript==
// @name         Linux do 主题
// @namespace    linux.do
// @version      2024-03-12
// @description  try to take over the world!
// @author       sinry
// @match        https://linux.do/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @require      https://cdn.staticfile.net/jquery/3.7.1/jquery.min.js
// @require      https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @connect      global.bing.com
// @connect      sipv4.com
// @connect      tools.mgtv100.com
// @grant        GM.xmlHttpRequest
// ==/UserScript==
//
// == description ==
// 2024-3-13 改版:增加滚动翻页功能(回到顶部、上翻、下翻),增加时间动态
// 2024-3-15 改版:增加增加了浏览时间统计、以及颜色显示,调整标题过长时间显示被覆盖时隐藏
// 2024-3-21 改版:增加暗夜模式切换、侧边栏调整为可上下拖动
// == /description ==

(async function () {
    'use strict';

    var startTop, startY;

    listenerViewTime()
    initSidebar()
    // setThemeButton()
    listenerChange('title', () => loadTheme())
    listenerChange('.home-logo-wrapper-outlet', () => loadTheme())

    // 监听dom变化
    function listenerChange(dom,fn) {
        new MutationObserver(() =>fn()).observe( document.querySelector(dom),  { subtree: true, characterData: true, childList: true } );
    }

    // 加载主题
    function loadTheme() {
        const isDarkTheme = localStorage.getItem('diyTheme') === 'dark';
        if (isDarkTheme) {
            setBlackTheme();
        } else {
            setWhiteTheme();
        }
    }


    // 设置暗黑主题
    function setBlackTheme() {
        // console.log("设置暗黑主题");
        $('.d-header').css("filter", "invert(1) hue-rotate(180deg)")
        $('.sidebar-wrapper').css("filter", "invert(1) hue-rotate(180deg)")
        $('#main-outlet').css("filter", "invert(1) hue-rotate(180deg)")
        $("img").css("filter", "invert(1) hue-rotate(180deg)");
        $('html').css("filter", "brightness(70%)");
        $('#theme-btn').text('暗夜')
        localStorage.setItem('diyTheme', 'dark');
    }

    // 设置白色主题
    function setWhiteTheme() {
        // console.log("设置白色主题");
        $('.d-header').css("filter", "")
        $('.sidebar-wrapper').css("filter", "")
        $('#main-outlet').css("filter", "")
        $("img:not(.excluded)").css("filter", "");
        $('html').css('filter', 'brightness(100%)');
        $('#theme-btn').text('明亮')
        localStorage.setItem('diyTheme', '');
    }

    // 监听浏览时间
    function listenerViewTime() {
        let viewIntervelIndex;
        function setIntervelFunc() {

            viewIntervelIndex = setInterval(() => {
                let curDate = new Date(new Date().toISOString())
                // 读取浏览器缓存
                let view = localStorage.getItem("view");
                // console.log("浏览时间", view, '秒');
                if (view == null) {
                    view = { time: 1, date: curDate };
                } else {
                    view = JSON.parse(view)
                }
                // 判断时间是否为今天
                let date = curDate;
                let existDate = new Date(new Date(view.date).toISOString());
                console.log(existDate)
                if (date.getDate() != existDate.getDate()) {
                    console.log('不是今天')
                    view.time = 1;
                    view.date = curDate;
                }
                let viewTime = parseInt(view.time)
                viewTime += 1; // 秒
                view.time = viewTime
                view.date = curDate
                // 设置浏览器缓存
                localStorage.setItem("view", JSON.stringify(view));
                let color = "rgb(0 0 0 / 51%)";
                // 浏览时间大于1小时小于2小时为蓝色,浏览时间大于2小时小于3小时为橙色,浏览时间大于3小时为红色
                if (viewTime > 3600 && viewTime < 7200) {
                    color = "rgb(0 0 255 / 51%)";
                } else if (viewTime > 7200 && viewTime < 10800) {
                    color = "rgb(255 165 0 / 51%)";
                } else if (viewTime > 10800) {
                    color = "rgb(255 0 0 / 51%)";
                }
                // 显示时间
                let viewTimeStr = '<span style="color:' + color + '">今日累计浏览 ' + getHoursInfo(viewTime) + "</span>";
                $('#viewTime').html(viewTimeStr);
            }, 1000);
        }
        setIntervelFunc()
        document.addEventListener("visibilitychange", function () {
            if (document.hidden) {
                console.log("页面不可见", getTime());
                clearInterval(viewIntervelIndex)
            } else {
                console.log("页面可见", getTime());
                setIntervelFunc()
            }
        });

    }

    // 设置鼠标经过按钮高亮
    function hightlight(dom) {

        dom.mouseenter(function () {
            $(this).css("background-color", "rgb(156 155 155 / 78%)");
        });
        dom.mouseleave(function () {
            $(this).css("background-color", "");
        });
    }

    // 浏览器滚动按钮事件
    function initSidebar() {
        const style = `
        position: fixed;
        z-index: 9999;
        right: 0;
        width: 40px;
        z-index: 9999;
        font-size: 16px;
        background-color: rgba(0, 0, 0, 0.5);
        color: #fff;
        cursor: pointer;
        writing-mode: vertical-rl;
        text-orientation: upright;
        text-align: center;
        display: flex;
        justify-content: center;
        align-items: center;
        top: 400px;
        border-radius: 10px 0px 0px 10px;
        resize: both;
        `
        const sidebarId = 'sidebar-btn'
        $('body').append($(`<div id="${sidebarId}" style="${style}"></div>`))

        var sidebarDom = $(`#${sidebarId}`)

        // 回到顶部按钮
        var backTopDiv = $(`<div id="backTop">回到顶部</div>`);
        sidebarDom.prepend(backTopDiv);

        backTopDiv.click(function () {
            $('html, body').animate({
                scrollTop: 0
            }, 1000);
        });

        // 下翻按钮
        var downTopDiv = $(`<div id="backTop">下翻</div>`);
        sidebarDom.prepend(downTopDiv);
        downTopDiv.click(function () {
            window.scrollTo({
                top: window.scrollY + window.innerHeight,
                behavior: 'smooth'
            });
        });

        // 上翻按钮
        var upTopDiv = $(`<div id="backTop">上翻</div>`);
        sidebarDom.prepend(upTopDiv);
        upTopDiv.click(function () {
            window.scrollTo({
                top: window.scrollY - window.innerHeight,
                behavior: 'smooth'
            });
        });


        // 切换主题按钮
        let theme = localStorage.getItem('diyTheme');
        let str = '明亮'
        if (theme == 'dark') {
            str = '暗夜'
        }
        let themeButton = $(`<div id="theme-btn">${str}</div>`);
        sidebarDom.prepend(themeButton);
        hightlight(themeButton)
        themeButton.click(function () {
            let theme = localStorage.getItem('diyTheme');
            if (theme == 'dark') {
                setWhiteTheme();
            } else {
                setBlackTheme();
            }

        })

        let sidebarBtn = $('#sidebar-btn>div');
        hightlight(sidebarBtn)
        sidebarBtn.css({
            'padding': '12px 5px',
            'border-radius': '10px'
        })

        // 监听鼠标拖动
        sidebarDom.mousedown(function(event) {
            startTop = sidebarDom.offset().top; // 记录初始位置
            startY = event.pageY; // 记录鼠标按下时的Y坐标

            $(document).on('mousemove', function(event) {
                // 更新div的位置,仅改变垂直方向(top)
                var moveY = event.pageY - startY;
                sidebarDom.offset({ top: startTop + moveY });

                // 阻止默认行为
                event.preventDefault();
            });

            $(document).one('mouseup mouseleave', function() {
                // 鼠标抬起或离开文档时移除mousemove事件监听器
                $(document).off('mousemove');
            });
        });

    }

    function setTopStyle(str) {
        // 创建一个新的 div 元素
        var headerNewDiv = $(`<div id="topStyle">${str}</div>`);

        // 添加任何你想要的内容或者属性到新的 div 元素中
        headerNewDiv.css({
            "text-align": "center", /* 使内容水平居中 */
            "position": "absolute",
            "top": "110px", /* 从顶部偏移50% */
            "left": "50%", /* 从左侧偏移50% */
            "margin-top": "-100px", /* 使元素上边缘向上偏移自身高度的一半 */
            "margin-left": "-100px", /* 使元素左边缘向左偏移自身宽度的一半 */
            "transition": "opacity 0.5s",
            "color": "rgb(0 0 0 / 51%)"
        });

        // 将新的 div 元素插入到 <body> 中
        $(".d-header").append(headerNewDiv);

        window.addEventListener('scroll', function () {
            if (window.scrollY > 50) {
                $("#topStyle")[0].style.opacity = '0';
            } else {
                $("#topStyle")[0].style.opacity = '1';
            }
        });

        $('#ember5').css({
           'box-shadow': 'rgb(23 22 22) 0px 0px 20px 1px'
        })
    }

    function getTime() {
        const date = new Date()
        const year = date.getFullYear()
        const month = date.getMonth() + 1
        const day = date.getDate()
        const hour = date.getHours()
        const minute = date.getMinutes()
        const second = date.getSeconds()
        const time = `${year}-${month}-${day} ${hour}:${minute}:${second}`
        return time
    }
    function getHoursInfo(totalSeconds) {
        var hours = Math.floor(totalSeconds / 3600);
        totalSeconds %= 3600;
        var minutes = Math.floor(totalSeconds / 60);
        if (hours > 0) {
            return hours + "小时" + minutes + "分钟";
        } else {
            return minutes + "分钟";
        }
    }
    function loadTime() {
        $('#topTime').text(getTime())
        setInterval(() => {
            $('#topTime').text(getTime())
        }, 1000)
    }

    function setTopInfo() {
        GM.xmlHttpRequest({
            method: "GET",
            url: "https://sipv4.com/json",
            headers: {
                "Content-Type": "application/json"
            },
            onload: function (response) {
                const data = JSON.parse(response.responseText)
                // 分割数组
                const address = data.address.split(" ")
                // 获取数组最后一个
                const city = address[address.length - 1]

                GM.xmlHttpRequest({
                    method: "GET",
                    url: `https://tools.mgtv100.com/external/v1/weathers/query?city=${city}&extensions=base&output=JSON`,
                    headers: {
                        "Content-Type": "application/json"
                    },
                    onload: function (response) {
                        const data = JSON.parse(response.responseText)
                        const weather = data.data.lives[0]

                        const weatherStr = `
                                <div><span id="topTime"></span> | ${weather.city} ${weather.weather} ${weather.temperature}°C</div>

                                <div style="font-size: 12px;" id="viewTime"></div>

                                `

                        setTopStyle(weatherStr)

                        loadTime()

                    }
                });
            }
        });
    }


    console.log('设置 Linux do 主题')
    let intervalIndex = setInterval(() => {
        let hasDom = $('#main-outlet-wrapper').html()
        if (hasDom) {
            clearInterval(intervalIndex)
            // 主内容框
            $('#main-outlet-wrapper').css({
                "margin-top": "30px",
                "border-radius": "20px",
                "overflow": "hidden"
            })
            // 右侧菜单
            $('.sidebar-wrapper').css({
                "background-color": "rgba(255, 255, 255, 0.7)",
                "top": "0",
                "border-radius": "20px"
            })
            // 顶部栏边缘模糊
            $(".d-header").css({
                "box-shadow": "rgb(255 255 255) 0px 5px 10px 5px"
            });

            $('#main-outlet').css({
                "background-color": "white",
                "padding": "20px",
                "border-radius": "20px",
                "box-shadow": "rgb(255 255 255) 0px 5px 10px 5px"
            })

            setTopInfo()
        }
    }, 500)


    function setBodyBackground(imageUrl) {
        // 设置body不滚动
        $('body').css({
            'background-image': `url(${imageUrl})`,
            'background-repeat': 'no-repeat',
            'background-size': 'cover',
            'background-attachment': 'fixed'
        })
        // 创建一个新的 div 元素
        var newDiv = $(`<div id="mask" style="
                width: 100%;
                height: 100vh;
                position: fixed;
                z-index: 999999999999;
                pointer-events: none;
                top: 0;
                left: 0;"></div>`);
        // 将新的 div 元素插入到 <body> 内容的开头
        $("body").prepend(newDiv);
        loadTheme();
    }

    GM.xmlHttpRequest({
        method: "GET",
        url: "https://global.bing.com/HPImageArchive.aspx?format=js&idx=0&n=9&pid=hp&FORM=BEHPTB&uhd=1&uhdwidth=3840&uhdheight=2160&setmkt=zh_cn&setlang=zh",
        headers: {
            "Content-Type": "application/json"
        },
        onload: function (response) {
            const data = JSON.parse(response.responseText)
            const imageUrl = 'https://global.bing.com/' + data.images[0].url
            setBodyBackground(imageUrl)
        }
    });

})();

2024-3-13 改版:增加滚动翻页功能(回到顶部、上翻、下翻),增加时间动态
image

2024-3-15 改版:增加增加了浏览时间统计、以及颜色显示,调整标题过长时间显示被覆盖时隐藏

2024-3-21 改版:增加暗夜模式切换、侧边栏调整为可上下拖动

84 个赞

支持,搞起来

2 个赞

常规话题软件开发

1 个赞

这个好玩

1 个赞

支持

1 个赞

侧边透明,看的眼睛疼

2 个赞

哈哈哈哈可以自己改里面的css透明度

2 个赞

玩得挺花 :grin:

3 个赞

:+1:

1 个赞

牛的

1 个赞

怎么改,求教:grin:

1 个赞

测试,手机可用,但是上面天气会覆盖功能按钮,导致按钮无法点击。

1 个赞


这个右侧菜单的0.7就是透明度

1 个赞

:smiling_face_with_tear:手机也有油猴吗,还没适配这个

1 个赞

牛 可用

1 个赞

还是不行,看的眼睛疼:rofl:

1 个赞

手机有浏览器支持

1 个赞

那就别用了呗

1 个赞

改为1就是不透明

1 个赞

厉害了:call_me_hand:

1 个赞