自用哪吒监控面板ServerStatus主题的自定义美化【紧凑(强迫症)风格】【V3】

我的所有美化宗旨:紧凑、整齐、优雅、统一

自用常用可自定义css软件自定义主题:

Alist https://salen.eu.org/



uptime kuma https://up.dsuk.top/

vs code

原版的ServerStatus主题美观度差强人意,但由于本人有些许强迫症与审美癖好,故做些微修改

  • 自动夜间模式
  • 界面错位调整
  • 排版优化
  • 其它小优化

预览


demo

https://nz.dsuk.top/

代码

!修改项较多,自行取舍

V1

已存档

V2更新

<link rel="stylesheet" href="https://font.sec.miui.com/font/css?family=MiSans:400:MiSans" />
<style>
    /* 网格布局容器 */
    .accordian-body>div {
        display: grid !important;
        grid-template-columns: repeat(3, 1fr) !important;
        gap: 2px;
        padding: 12px;
        background: #f8f9fa;
        transition: all 0.3s ease;
    }

    /* 基础卡片样式 - 排除特定结构 */
    .node-cell-expand:not(div > .uptime):not(span.load),
    .node-cell-expand.load {
        line-height: unset !important;
        border-radius: 8px;
        padding: 7px 10px;
        display: flex !important;
        min-height: 15px;
        transition: all 0.3s ease;
        background: #ffffff00;
        border: 1px solid #ccc;
        width: unset !important;
    }

    /* 标签样式 */
    .node-cell-expand-label {
        min-width: 45px;
        color: #666;
        font-size: inherit;
        transition: color 0.3s ease;
    }

    /* 值样式 */
    .node-cell-expand>span:not(.node-cell-expand-label) {

        font-size: inherit;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        color: #333;
        transition: color 0.3s ease;
    }

    /* CPU 和系统信息占据整行 */
    .node-cell-expand:has(.node-cell-expand-label:contains("CPU")),
    .node-cell-expand:has(.node-cell-expand-label:contains("系统")) {
        grid-column: 1 / -1;
    }

    /* 使用率指示器 */
    .node-cell-expand:has(span:contains("%")) {
        position: relative;
    }

    .node-cell-expand:has(span:contains("%"))::after {
        content: '';
        position: absolute;
        bottom: 0;
        left: 0;
        height: 2px;
        background: #2ecc71;
        width: var(--usage);
        transition: background 0.3s ease;
    }

    /* 流量信息样式 */
    .node-cell-expand .icon {
        margin: 0 2px;
    }

    /* 图表容器样式 */
    .node-echarts-expand {
        grid-column: 1 / -1 !important;
        margin-top: 12px;
    }

    /* 响应式调整 - 小屏幕适配 */
    @media (max-width: 1024px) {
        .accordian-body>div {
            grid-template-columns: repeat(2, 1fr) !important;
        }
    }

    @media (max-width: 768px) {
        .accordian-body>div {
            grid-template-columns: 1fr !important;
            padding: 8px;
        }

        .node-cell-expand {
            padding: 6px 8px;
        }
    }

    /* 暗色模式 */
    body[theme="dark"] .accordian-body>div {
        background: #1a1a1a;
    }

    body[theme="dark"] .node-cell-expand {
        background: #2d2d2d00;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
    }

    body[theme="dark"] .node-cell-expand-label {
        color: #999;
    }

    body[theme="dark"] .node-cell-expand>span:not(.node-cell-expand-label) {
        color: #e0e0e0;
    }

    body[theme="dark"] .node-cell-expand:has(span:contains("%"))::after {
        background: #2d8659;
    }

    body[theme="dark"] .node-cell-expand[data-usage-high] {
        background: #3d2828;
        border-left-color: #a33;
    }

    body[theme="dark"] .node-cell-expand[data-usage-medium] {
        background: #3d3528;
        border-left-color: #a73;
    }
</style>

<script>

    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            mutation.addedNodes.forEach((node) => {
                if (node.classList?.contains('node-cell-expand')) {
                    const text = node.textContent;
                    const percentMatch = text.match(/\((\d+\.?\d*)%\)/);

                    if (percentMatch) {
                        const usage = parseFloat(percentMatch[1]);
                        node.style.setProperty('--usage', `${usage}%`);

                        if (usage > 80) {
                            node.setAttribute('data-usage-high', '');
                            node.style.borderLeft = '2px solid #ff4757';
                        } else if (usage > 60) {
                            node.setAttribute('data-usage-medium', '');
                            node.style.borderLeft = '2px solid #ffa502';
                        }
                    }
                }
            });
        });
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
</script>

<style>
    i.icon {
        display: inline-block;
        opacity: 1;
        margin: 0px 0.25rem 0px 0.25rem;
        width: 1.18em;
        height: unset;
        font-family: Icons;
        font-style: normal;
        font-weight: 400;
        text-decoration: inherit;
        text-align: center;
        -moz-osx-font-smoothing: grayscale;
        -webkit-font-smoothing: antialiased;
        -webkit-backface-visibility: hidden;
        backface-visibility: hidden;
    }

    .node-cell.status .status-icon {
        width: 16px;
        height: 16px;
        border-radius: 35%;
    }

    .uptime,
    .load {
        line-height: 26.896px !important;
    }

    .node-cell.center {
        line-height: 26.896px !important;
        text-align: center !important;
    }

    .node-cell.status .status-container {
        height: 26.896px;
    }

    .table-condensed>tbody>tr>td,
    .table-condensed>tbody>tr>th,
    .table-condensed>tfoot>tr>td,
    .table-condensed>tfoot>tr>th,
    .table-condensed>thead>tr>td,
    .table-condensed>thead>tr>th {
        padding: 4px;
    }

    body[theme="light"] .progress {
        height: 26.9px;
        border: 1px rgba(0, 0, 0, 0.3) solid;
        background-color: rgba(28, 29, 38, 0);
    }

    body[theme="dark"] .progress {
        height: 26.9px;
        border: 1px rgba(255, 255, 255, 0.3) solid;
        background-color: rgba(0, 0, 0, 0);
    }

    /* body[theme="dark"] .progress-bar-success, body[theme="dark"] .progress-bar-warning {
    border-radius: 6px;
}
body[theme="light"] .progress-bar-success, body[theme="light"] .progress-bar-warning {
    border-radius: 6px;
} */

    .node-cell.remaining,
    .progress-bar {
        line-height: 26px;
    }

    body[theme="light"] tr.even.expandRow> :hover {
        border-radius: 25px;
    }

    body[theme="dark"] tr.even.expandRow> :hover {
        border-radius: 25px;
    }

    body[theme="light"] tr.odd.expandRow> :hover {
        border-radius: 25px;
    }

    body[theme="dark"] tr.odd.expandRow> :hover {
        border-radius: 25px;
    }

    /* 亮色模式下的表格样式 */
    table tr {
        transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important;
        position: relative !important;
    }

    table tr:hover {
        position: relative !important;
        z-index: 9999 !important;
        outline: 1px solid rgba(0, 0, 0, 0.33) !important;
        border-radius: 10px !important;
        background-color: rgba(0, 0, 0, 0) !important;
    }

    /* 暗色模式下的表格样式 */
    body[theme="dark"] table tr {
        transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important;
        position: relative !important;
    }

    body[theme="dark"] table tr:hover {
        position: relative !important;
        z-index: 9999 !important;
        outline: 1px solid rgba(255, 255, 255, 0.33) !important;
        border-radius: 10px !important;
        background-color: rgba(255, 255, 255, 0) !important;
    }

    /* 为了确保悬停效果在暗色模式下更加明显 */
    body[theme="dark"] table tr:hover td {
        background-color: rgba(255, 255, 255, 0) !important;
    }

    /* 提升表格在页面层级中的位置,确保悬停效果不被其他元素遮挡 */
    table {
        position: relative !important;
        z-index: 1 !important;
    }

    /* 优化表格边框在暗色模式下的显示 */
    body[theme="dark"] table {
        border-color: rgba(255, 255, 255, 0.1) !important;
    }

    body[theme="dark"] table td,
    body[theme="dark"] table th {
        border-color: rgba(255, 255, 255, 0.1) !important;
    }

    /* 1. 全局样式设置 */
    body[theme] {
        font-family: "MiSans", "Microsoft YaHei", Arial, Helvetica, sans-serif;
    }

    .content {
        padding: 5px;
        border-radius: 11px;
    }

    footer.container-fluid,
    ::-webkit-scrollbar {
        display: none !important;
    }

    /* 2. 基础布局 */
    .container-fluid {
        max-width: 2160px;
        width: 90%;
    }

    .outer-container {
        width: 100%;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    .table-container {
        width: 95%;
        min-width: 1200px;
        table-layout: fixed;
        overflow-x: auto;
    }

    /* 3. Accordion 和导航栏样式 */
    .navbar-nav>li>.dropdown-menu {
        border-radius: 8px !important;
    }

    .accordian-body {
        margin-left: 1%;
        margin-right: 1%;
    }

    .accordian-body>div {
        max-width: none !important;
        padding: 3px;
        border: 2px solid #ccc;
        border-radius: 13px;
    }

    /* 4. 表格基础样式 */
    table {
        width: 100%;
        white-space: nowrap;
        border-collapse: separate;
        border-spacing: 0;
    }

    tr {
        display: table-row;
        white-space: nowrap !important;
    }

    th,
    td {
        display: table-cell;
        white-space: nowrap !important;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* 5. 列宽定义 */
    .status {
        flex: 0.5;
        min-width: 50px;
        width: 0% !important;
    }

    .os {
        flex: 0.6;
        min-width: 100px;
        width: 0% !important;
    }

    .location {
        flex: 0.8;
        min-width: 80px;
        width: 0% !important;
    }

    .price {
        flex: 0.8;
        min-width: 60px;
        width: 0% !important;
    }

    .uptime {
        padding-left: 10px;
        width: 5% !important;
        flex: 1;
        min-width: 12%;
    }

    .remaining {
        flex: 1.2;
        width: 10%;
        min-width: 40px;
    }

    .cpu,
    .memory,
    .hdd {
        flex: 1.2;
        min-width: 90px;
    }

    .network,
    .traffic {
        width: 13%;
        min-width: 60px;
    }

    /* 6. 表格对齐和样式 */
    th.node-cell.name.center,
    td.node-cell.name.center {
        text-align: left !important;
        padding-left: 10px;
        width: 0% !important;
    }

    .table-striped tbody>tr,
    .table-striped tbody>tr.odd>td,
    .table-striped tbody>tr.odd>th {
        background-color: rgb(0 0 0 / 0%);
    }

    /* 7. 进度条和数据显示 */
    .progress {
        border-radius: 7px;
        background-clip: padding-box;
        overflow: hidden;
    }

    .progress .progress-bar {
        border-radius: 6px !important;
        transition: width 1s ease;
        box-shadow: inset 0 -1px 0 rgb(255 0 0 / 0%);
    }

    .node-cell-remaining-days {
        display: block;
        opacity: 1;
        transform: translateY(0);
        transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
    }

    span.node-cell-remaining-percent {
        display: none;
        opacity: 0;
        transform: translateY(-20px);
        transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
    }

    /* 8. 悬停效果 */

    /* 默认显示天数,隐藏百分比 */
    .node-cell-remaining-days {
        display: block;
        opacity: 1;
        transform: translateY(0);
        transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
    }

    span.node-cell-remaining-percent {
        display: none;
        opacity: 0;
        transform: translateY(-20px);
        transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
    }

    /* 鼠标悬停时显示百分比,隐藏天数 */
    .node-cell:hover .node-cell-remaining-days {
        opacity: 0;
        transform: translateY(20px);
        display: none;
    }

    .node-cell:hover .node-cell-remaining-percent {
        display: block;
        opacity: 1;
        transform: translateY(0);
    }

    /* 保持原有的悬停效果不变 */
    tr.accordion-toggle:hover {
        border-radius: 30px;
        background-color: rgba(0, 0, 0, 0);
        transition: all 0.3s ease;
    }

    /* 9. 工具箱样式 */
    .toolbox {
        position: fixed;
        bottom: 10px;
        right: 5px;
        z-index: 999999;
        transition: transform 0.3s ease, opacity 0.3s ease;
    }

    .toolbox:hover {
        transform: translateY(0) !important;
        opacity: 1 !important;
    }

    .toolbox i {
        backdrop-filter: blur(2px);
        border: 1.3px solid;
        display: block;
        color: rgba(241, 241, 241, 0);
        cursor: pointer;
        border-radius: 8px;
        font-size: 1rem;
        height: 2.2rem;
        width: 2.2rem;
        line-height: 2.2rem;
        text-align: center;
    }

    .toolbox .setTheme i.setTheme-dark,
    .toolbox .setTheme i.setTheme-light {
        font-size: 1rem;
    }

    /* 10. 模态框样式 */
    .modal-content {
        backdrop-filter: blur(14px);
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        border-radius: 12px;
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%) scale(0.7);
        z-index: 1050;
    }

    .modal-header {
        padding: 15px;
        border-bottom: 1px solid #eee;
        border-radius: 12px 12px 0 0;
    }

    .modal-body {
        overflow: hidden;
        border-radius: 0 0 12px 12px;
    }

    .modal-header h4,
    .modal-header i,
    .modal-body,
    .modal-header .bi {
        font-size: 1.4rem;
    }

    /* 11. 主题相关样式 */
    body[theme="dark"] .modal-content {
        background-color: rgba(28, 29, 38, 0.4);
    }

    body[theme="light"] .modal-content {
        background-color: rgb(255 255 255 / 40%);
    }

    body[theme="dark"] .progress {
        border-radius: 7px;
    }

    body[theme="dark"] span.node-cell-remaining-percent {
        display: none;
    }

    body[theme="dark"] .table>tbody>tr>td:before,
    body[theme="dark"] .table>tfoot>tr>td:before,
    body[theme="dark"] .table>thead>tr>td:before,
    body[theme="dark"] .table>thead>tr.node-group-cell>th:before {
        background-color: rgba(58, 62, 65, 0);
    }

    body[theme="light"] .table>tbody>tr>td:before,
    body[theme="light"] .table>tfoot>tr>td:before,
    body[theme="light"] .table>thead>tr>td:before,
    body[theme="light"] .table>thead>tr.node-group-cell>th:before {
        background-color: rgba(221, 221, 221, 0);
    }

    body[theme="light"] .table-hover>tbody>tr:hover>td {
        background: #ffffff00;
    }

    body[theme="dark"] .table-hover>tbody>tr:hover>td {
        background: #ffffff00;
    }

    body[theme="dark"] .table-hover>tbody>tr:not(.expandRow):hover>td {
        background-color: rgb(183 184 190 / 0%);
    }

    .table-striped>tbody>tr:nth-of-type(odd) {
        background-color: #f9f9f900;
    }

    .table-hover>tbody>tr:hover {
        background-color: #f5f5f500;
    }

    body[theme="light"] .table-striped tbody>tr.even>td,
    body[theme="light"] .table-striped tbody>tr.even>th {
        background-color: #f9f9f900;
    }

    body[theme="dark"] .table-striped tbody>tr,
    body[theme="dark"] .table-striped tbody>tr.even>td,
    body[theme="dark"] .table-striped tbody>tr.even>th {
        background-color: rgb(28 29 38 / 0%);
    }

    body[theme="dark"] .table-striped tbody>tr,
    body[theme="dark"] .table-striped tbody>tr.odd>td,
    body[theme="dark"] .table-striped tbody>tr.odd>th {
        background-color: rgb(34 35 46 / 0%);
    }

    /* 12. 图表容器样式 */
    .chartbox {
        box-shadow: inset 0 2px 11px rgba(0, 0, 0, 1.1);
        width: 100%;
        height: auto;
        user-select: none;
        -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
        position: relative;
        border: 2px solid #ccc;
        border-radius: 10px;
        overflow: hidden;
    }

    .dark .chartbox {
        box-shadow: inset 0 2px 8px rgba(255, 255, 255, 0.1);
    }

    /* 13. 工具提示样式 */
    .tooltip {
        position: absolute;
        display: block;
        background-color: rgba(28, 29, 38, 0.75);
        backdrop-filter: blur(8px);
        -webkit-backdrop-filter: blur(8px);
        border: 1px solid rgba(255, 255, 255, 0.1);
        border-radius: 4px;
        color: rgb(241, 241, 241);
        font: 14px/21px "Microsoft YaHei";
        padding: 10px;
        transform: translate3d(828px, 68px, 0);
        pointer-events: none;
        visibility: hidden;
        opacity: 0;
        transition: all 0.2s cubic-bezier(0.23, 1, 0.32, 1);
    }

    .tooltip.visible {
        visibility: visible;
        opacity: 1;
    }

    small {
        font-size: 100% !important;
    }

    .node-cell.remaining .additional small {
        white-space: nowrap;
        font-size: 100% !important;
    }

    i.icon {
        border: 0px;
        display: unset;
    }

    /* 14. 响应式布局 */
    @media (max-width: 1600px) {
        .container-fluid {
            width: 98%;
        }

        .remaining {
            width: 10%;
            min-width: 60px;
        }
    }

    @media (max-width: 1300px) {

        .price,
        .os,
        .remaining {
            display: none !important;
        }

        .load {
            width: 5%;
            min-width: 20px;
        }

        .cpu,
        .memory,
        .hdd {
            width: 8%;
            min-width: 50px;
        }
    }

    @media (max-width: 1200px) {
        .location {
            display: none !important;
        }

        .cpu,
        .memory,
        .hdd {
            width: 10%;
            min-width: 60px;
        }
    }

    @media (max-width: 1000px) {

        .load,
        .os,
        .price,
        .location,
        .uptime,
        .remaining {
            display: none !important;
        }

        .status {
            width: 6%;
            min-width: 25px;
        }

        .name {
            width: 10%;
            min-width: 45px;
        }

        .network {
            width: 20%;
            min-width: 100px;
        }

        .traffic {
            width: 14%;
            min-width: 100px;
        }

        .cpu,
        .memory,
        .hdd {
            width: 10%;
            min-width: 60px;
        }

        .progress-container {
            min-width: 35px;
        }

        .container-fluid {
            width: 98%;
        }

        .number-value {
            font-size: 11px;
        }
    }

    @media (max-width: 600px) {
        .container-fluid {
            width: 98%;
        }

        .arrow,
        .remaining {
            display: none !important;
        }

        .status {
            width: 5%;
            min-width: 20px;
        }

        .name {
            width: 8%;
            min-width: 40px;
        }

        .network,
        .traffic {
            width: 20%;
            min-width: 120px;
        }

        .cpu,
        .memory,
        .hdd {
            width: 5%;
            min-width: 20px;
        }

        .number-value {
            font-size: 11px;
        }

        .network span,
        .traffic span,
        .cpu span,
        .memory span,
        .hdd span {
            font-size: 10px;
        }

        small {
            font-size: 80% !important;
        }
    }
</style>

<script>
    // 主题切换功能
    (function () {
        function setThemeByPreference() {
            const isDarkMode = window.matchMedia("(prefers-color-scheme: dark)").matches;
            const button = document.querySelector(`.setTheme-${isDarkMode ? 'dark' : 'light'}`);
            button?.click();
        }

        setThemeByPreference();

        window.matchMedia("(prefers-color-scheme: dark)")
            .addEventListener("change", setThemeByPreference);

        window.addEventListener("load", () => {
            setThemeByPreference();
            document.querySelector('.bi-three-dots')?.click();
        });
    })();

</script>
<style>
    /* 基础样式 */
    td.node-cell.network,
    td.node-cell.traffic {
        padding: 4px !important;
        position: relative;
    }

    .node-cell.network {
        min-width: 0px;
        max-width: 0px;
    }

    .data-box {
        position: absolute;
        top: 50%;
        left: 2px;
        right: 2px;
        transform: translateY(-50%);
        padding: 0px 6px;
        border: 1px solid rgba(0, 0, 0, 0.3);
        border-radius: 7px;
        background-color: rgba(255, 255, 255, 1);
        pointer-events: none;
        z-index: 1;
    }

    .value-container {
        display: flex;
        align-items: center;
        justify-content: space-between;
        width: 100%;
        gap: 1px;
    }

    .value-left,
    .value-right {
        flex: 1;
        min-width: 20px;
    }

    .value-left {
        text-align: right;
        padding-right: 2px;
    }

    .value-right {
        text-align: left;
        padding-left: 2px;
    }

    .units-and-arrows {
        display: flex;
        align-items: center;
        gap: 1px;
        white-space: nowrap;
        position: relative;
    }

    /* 固定单位宽度 */
    .unit-left,
    .unit-right {
        min-width: 16px;
        text-align: center;
        padding: 0px 2px;
        background-color: rgba(0, 0, 0, 0.05);
        border-radius: 4px;
        font-size: 0.9em;
        color: rgba(0, 0, 0, 0.6);
        border: 0.5px solid rgba(0, 0, 0, 0.1);
    }

    /* 速度单位颜色区分 */
    .unit-left[data-unit="b"],
    .unit-right[data-unit="b"] {
        color: #666;
        background-color: rgba(200, 200, 200, 0.2);
    }

    .unit-left[data-unit="k"],
    .unit-right[data-unit="k"] {
        color: #2196F3;
        background-color: rgba(33, 150, 243, 0.1);
    }

    .unit-left[data-unit="m"],
    .unit-right[data-unit="m"] {
        color: #4CAF50;
        background-color: rgba(76, 175, 80, 0.1);
    }

    .unit-left[data-unit="g"],
    .unit-right[data-unit="g"] {
        color: #FF9800;
        background-color: rgba(255, 152, 0, 0.1);
    }

    .arrow {
        padding: 0px 1px;
        background-color: rgba(0, 0, 0, 0);
        border-radius: 4px;
        font-size: 0.9em;
        color: rgba(0, 0, 0, 0.6);
        border: 0.5px solid rgba(0, 0, 0, 0.1);
    }

    .spacer {
        width: 1px;
        height: 25.3px;
        background-color: rgba(0, 0, 0, 0.2);
        margin: 0 1px;
    }

    /* 暗色主题适配 */
    body[theme="dark"] .unit-left,
    body[theme="dark"] .unit-right {
        border-color: rgba(255, 255, 255, 0.2);
    }

    body[theme="dark"] .unit-left[data-unit="b"],
    body[theme="dark"] .unit-right[data-unit="b"] {
        color: #aaa;
        background-color: rgba(255, 255, 255, 0.1);
    }

    body[theme="dark"] .unit-left[data-unit="k"],
    body[theme="dark"] .unit-right[data-unit="k"] {
        color: #64B5F6;
        background-color: rgba(33, 150, 243, 0.2);
    }

    body[theme="dark"] .unit-left[data-unit="m"],
    body[theme="dark"] .unit-right[data-unit="m"] {
        color: #81C784;
        background-color: rgba(76, 175, 80, 0.2);
    }

    body[theme="dark"] .unit-left[data-unit="g"],
    body[theme="dark"] .unit-right[data-unit="g"] {
        color: #FFB74D;
        background-color: rgba(255, 152, 0, 0.2);
    }

    body[theme="dark"] .spacer {
        background-color: rgba(255, 255, 255, 0.2);
    }

    body[theme="dark"] .data-box {
        border-color: rgba(255, 255, 255, 0.3);
        background-color: rgb(28 29 38);
    }

    body[theme="dark"] .arrow {
        background-color: rgba(255, 255, 255, 0.03);
        /* 与其他暗色元素保持一致 */
        color: rgba(255, 255, 255, 0.6);
        /* 暗色主题下的文字颜色 */
        border-color: rgba(255, 255, 255, 0.2);
        /* 与其他暗色边框保持一致 */
    }
</style>

<script>
    function splitValueAndUnit(text) {
        const match = text.trim().match(/^(\d+(?:\.\d+)?)\s*([a-zA-Z]*)$/);
        if (match) {
            const number = parseFloat(match[1]);
            const formattedValue = number.toFixed(1);
            // 将单位转换为小写用于样式匹配,但显示为大写
            const unit = match[2].toLowerCase();
            return {
                value: formattedValue,
                unit: unit.toUpperCase(), // 显示为大写
                unitClass: unit // 用于样式匹配的小写单位
            };
        }
        return { value: text, unit: '', unitClass: '' };
    }

    function createOverlay() {
        const cells = document.querySelectorAll('td.node-cell.network, td.node-cell.traffic');

        cells.forEach(cell => {
            if (!cell.querySelector('.data-box')) {
                const overlay = document.createElement('div');
                overlay.className = 'data-box';
                overlay.innerHTML = `
                <div class="value-container">
                    <span class="value-left"></span>
                    <div class="units-and-arrows">
                        <span class="unit-left"></span>
                        <span class="arrow">↓</span>
                        <span class="spacer"></span>
                        <span class="arrow">↑</span>
                        <span class="unit-right"></span>
                    </div>
                    <span class="value-right"></span>
                </div>
            `;
                cell.appendChild(overlay);
            }
        });
    }

    function updateOverlays() {
        const cells = document.querySelectorAll('td.node-cell.network, td.node-cell.traffic');

        cells.forEach(cell => {
            const overlay = cell.querySelector('.data-box');
            if (!overlay) return;

            const text = Array.from(cell.childNodes)
                .find(node => node.nodeType === Node.TEXT_NODE)?.textContent.trim() || '';

            if (!text || !text.includes('|')) return;

            const [left, right] = text.split('|').map(s => s.trim());
            const leftParts = splitValueAndUnit(left);
            const rightParts = splitValueAndUnit(right);

            const leftValue = overlay.querySelector('.value-left');
            const rightValue = overlay.querySelector('.value-right');
            const leftUnit = overlay.querySelector('.unit-left');
            const rightUnit = overlay.querySelector('.unit-right');

            if (leftValue && rightValue && leftUnit && rightUnit) {
                leftValue.textContent = leftParts.value;
                rightValue.textContent = rightParts.value;
                leftUnit.textContent = leftParts.unit;
                rightUnit.textContent = rightParts.unit;

                // 使用小写的unitClass来匹配CSS样式
                leftUnit.setAttribute('data-unit', leftParts.unitClass);
                rightUnit.setAttribute('data-unit', rightParts.unitClass);
            }
        });
    }

    // 初始化
    document.addEventListener('DOMContentLoaded', () => {
        createOverlay();
        updateOverlays();
    });

    // 定期更新
    setInterval(updateOverlays, 100);

    document.addEventListener('DOMContentLoaded', function () {
        document.querySelector('th.node-cell.network.center').innerHTML = '【下行】&nbsp;网速&nbsp【上行】';
        document.querySelector('th.node-cell.traffic.center').innerHTML = '【下载】&nbsp;流量&nbsp【上传】';
    });
</script>

V3更新

  • 优化了展开页面的布局,使其更整齐

  • 布局颜色细节修改了一下

因为我小鸡不多,所以分组页面没有修改,感兴趣的可以F12自行修改

代码完全没有排版和优化,凑活看,哪里不喜欢可以右键检查然后ctrl+f搜索关键词修改

<link rel="stylesheet" href="https://font.sec.miui.com/font/css?family=MiSans:400:MiSans" />
<style>

    div>span:nth-child(2) {
        grid-column: 1 / -1;
        order: -1
    }

    body[theme="dark"] .chartbox {
        box-shadow: inset 0 0px 13px 0px rgba(0, 0, 0, 1.1);
        width: 100%;
        height: auto;
        user-select: none;
        -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
        position: relative;
        border: 1px solid #ffffff63;
        border-radius: 10px;
        overflow: hidden;
    }

    body[theme="dark"] tr.even.expandRow> :hover {
        border-radius: 14px;
    }

    body[theme="light"] tr.even.expandRow> :hover {
        border-radius: 14px;
    }

    body[theme="light"] tr.odd.expandRow> :hover {
        border-radius: 14px;
    }

    body[theme="dark"] tr.odd.expandRow> :hover {
        border-radius: 14px;
    }

    body[theme="light"] .navbar .dropdown-menu {
        border-radius: 10px;
        outline: 2px solid rgba(0, 0, 0, 0.33) !important;
        background-color: rgba(255, 255, 255, 1);
        border-top: none;
        border-color: rgba(206, 206, 206, 0.65);
        box-shadow: rgba(255, 255, 255, 0.18) 0px 6px 12px;
    }

    body[theme="dark"] .navbar .dropdown-menu {
        border-radius: 10px;
        outline: 2px solid rgb(255 255 255 / 33%) !important;
        background-color: rgba(23, 26, 30, 1);
        border-color: rgba(49, 54, 59, 1);
        box-shadow: rgba(0, 0, 0, 0.18) 0px 6px 12px;
    }

    .accordian-body>div {
        display: grid !important;
        grid-template-columns: repeat(4, 1fr) !important;
        gap: 2px;
        padding: 12px;
        background: #f8f9fa;
        transition: all 0.3s ease;
    }

    .node-cell-expand:not(div > .uptime):not(span.load),
    .node-cell-expand.load {
        line-height: unset !important;
        border-radius: 7px;
        padding: 5px 7px;
        display: flex !important;
        min-height: 15px;
        transition: all 0.3s ease;
        background: #ffffff00;
        border: 1px solid #ccc;
        width: unset !important;
    }

    body[theme="dark"] .node-cell-expand:not(div > .uptime):not(span.load),
    .node-cell-expand.load {
        line-height: unset !important;
        border-radius: 7px;
        padding: 5px 7px;
        display: flex !important;
        min-height: 15px;
        transition: all 0.3s ease;
        background: #ffffff00;
        border: 1px solid #ccccccad;
        width: unset !important;
    }

    .node-cell-expand-label {
        min-width: 45px;
        color: #666;
        font-size: inherit;
        transition: color 0.3s ease;
    }

    .node-cell-expand>span:not(.node-cell-expand-label) {
        font-size: inherit;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        color: #333;
        transition: color 0.3s ease;
    }

    .node-cell-expand:has(.node-cell-expand-label:contains("CPU")),
    .node-cell-expand:has(.node-cell-expand-label:contains("系统")) {
        grid-column: 1 / -1;
    }

    .node-cell-expand:has(span:contains("%")) {
        position: relative;
    }

    .node-cell-expand:has(span:contains("%"))::after {
        content: '';
        position: absolute;
        bottom: 0;
        left: 0;
        height: 2px;
        background: #2ecc71;
        width: var(--usage);
        transition: background 0.3s ease;
    }

    .node-cell-expand .icon {
        margin: 0 2px;
    }

    .node-echarts-expand {
        grid-column: 1 / -1 !important;
        margin-top: 0px;
    }

    @media (max-width: 1024px) {
        .accordian-body>div {
            grid-template-columns: repeat(2, 1fr) !important;
        }
    }

    @media (max-width: 768px) {
        .accordian-body>div {
            grid-template-columns: 1fr !important;
            padding: 8px;
        }

        .node-cell-expand {
            padding: 6px 8px;
        }
    }

    body[theme="dark"] .accordian-body>div {
        background: #1a1a1a00;
    }

    body[theme="dark"] .node-cell-expand {
        background: #2d2d2d00;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
    }

    body[theme="dark"] .node-cell-expand-label {
        color: #999;
    }

    body[theme="dark"] .node-cell-expand>span:not(.node-cell-expand-label) {
        color: #e0e0e0;
    }

    body[theme="dark"] .node-cell-expand:has(span:contains("%"))::after {
        background: #2d8659;
    }

    body[theme="dark"] .node-cell-expand[data-usage-high] {
        background: #3d2828;
        border-left-color: #a33;
    }

    body[theme="dark"] .node-cell-expand[data-usage-medium] {
        background: #3d3528;
        border-left-color: #a73;
    }

    i.icon {
        display: inline-block;
        opacity: 1;
        margin: 0px 0.25rem 0px 0.25rem;
        width: 1.18em;
        height: unset;
        font-family: Icons;
        font-style: normal;
        font-weight: 400;
        text-decoration: inherit;
        text-align: center;
        -moz-osx-font-smoothing: grayscale;
        -webkit-font-smoothing: antialiased;
        -webkit-backface-visibility: hidden;
        backface-visibility: hidden;
    }

    .node-cell.status .status-icon {
        width: 16px;
        height: 16px;
        border-radius: 35%;
    }

    .uptime,
    .load {
        line-height: 26.896px !important;
    }

    .node-cell.center {
        line-height: 26.896px !important;
        text-align: center !important;
    }

    .node-cell.status .status-container {
        height: 26.896px;
    }

    .table-condensed>tbody>tr>td,
    .table-condensed>tbody>tr>th,
    .table-condensed>tfoot>tr>td,
    .table-condensed>tfoot>tr>th,
    .table-condensed>thead>tr>td,
    .table-condensed>thead>tr>th {
        padding: 4px;
    }

    body[theme="light"] .progress {
        height: 26.9px;
        border: 1px rgba(0, 0, 0, 0.3) solid;
        background-color: rgba(28, 29, 38, 0);
    }

    body[theme="dark"] .progress {
        height: 26.9px;
        border: 1px rgba(255, 255, 255, 0.3) solid;
        background-color: rgba(0, 0, 0, 0);
    }

    .node-cell.remaining,
    .progress-bar {
        line-height: 26px;
    }

    table tr {
        transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important;
        position: relative !important;
    }

    table tr:hover {
        position: relative !important;
        z-index: 9999 !important;
        outline: 2px dashed rgba(0, 0, 0, 0.33) !important;
        border-radius: 10px !important;
        background-color: rgba(0, 0, 0, 0) !important;
    }

    body[theme="dark"] table tr {
        transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1) !important;
        position: relative !important;
    }

    body[theme="dark"] table tr:hover {
        position: relative !important;
        z-index: 9999 !important;
        outline: 2px dashed rgba(255, 255, 255, 0.33) !important;
        border-radius: 10px !important;
        background-color: rgba(255, 255, 255, 0) !important;
    }

    body[theme="dark"] table tr:hover td {
        background-color: rgba(255, 255, 255, 0) !important;
    }

    table {
        position: relative !important;
        z-index: 1 !important;
    }

    body[theme="dark"] table {
        border-color: rgba(255, 255, 255, 0.1) !important;
    }

    body[theme="dark"] table td,
    body[theme="dark"] table th {
        border-color: rgba(255, 255, 255, 0.1) !important;
    }

    body[theme] {
        font-family: "MiSans", "Microsoft YaHei", Arial, Helvetica, sans-serif;
    }

    .content {
        padding: 5px;
        border-radius: 14px;
    }

    footer.container-fluid,
    ::-webkit-scrollbar {
        display: none !important;
    }

    .container-fluid {
        max-width: 2160px;
        width: 90%;
    }

    .outer-container {
        width: 100%;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    .table-container {
        width: 95%;
        min-width: 1200px;
        table-layout: fixed;
        overflow-x: auto;
    }

    .navbar-nav>li>.dropdown-menu {
        border-radius: 8px !important;
    }

    .accordian-body {
        margin-left: 0.2%;
        margin-right: 0.2%;
        margin: 1px 1px 1px 1px;
    }

.accordian-body>div {
    border-right: 2px solid #ccc;
    border-left: 2px solid #ccc;
    max-width: none !important;
    padding: 3px;
    /* border: 2px solid #ccc; */
    border-radius: 13px;
}

    table {
        width: 100%;
        white-space: nowrap;
        border-collapse: separate;
        border-spacing: 0;
    }

    tr {
        display: table-row;
        white-space: nowrap !important;
    }

    th,
    td {
        display: table-cell;
        white-space: nowrap !important;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .status {
        flex: 0.5;
        min-width: 50px;
        width: 0% !important;
    }

    .os {
        flex: 0.6;
        min-width: 100px;
        width: 0% !important;
    }

    .location {
        flex: 0.8;
        min-width: 80px;
        width: 0% !important;
    }

    .price {
        flex: 0.8;
        min-width: 60px;
        width: 0% !important;
    }

    .uptime {
        padding-left: 10px;
        width: 5% !important;
        flex: 1;
        min-width: 12%;
    }

    .remaining {
        flex: 1.2;
        width: 10%;
        min-width: 40px;
    }

    .cpu,
    .memory,
    .hdd {
        flex: 1.2;
        min-width: 90px;
    }

    .network,
    .traffic {
        width: 13%;
        min-width: 60px;
    }

    th.node-cell.name.center,
    td.node-cell.name.center {
        text-align: left !important;
        padding-left: 10px;
        width: 0% !important;
    }

    .table-striped tbody>tr,
    .table-striped tbody>tr.odd>td,
    .table-striped tbody>tr.odd>th {
        background-color: rgb(0 0 0 / 0%);
    }

    .progress {
        border-radius: 7px;
        background-clip: padding-box;
        overflow: hidden;
    }

    .progress .progress-bar {
        border-radius: 6px !important;
        transition: width 1s ease;
        box-shadow: inset 0 -1px 0 rgb(255 0 0 / 0%);
    }

    .node-cell-remaining-days {
        display: block;
        opacity: 1;
        transform: translateY(0);
        transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
    }

    span.node-cell-remaining-percent {
        display: none;
        opacity: 0;
        transform: translateY(-20px);
        transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
    }

    .node-cell-remaining-days {
        display: block;
        opacity: 1;
        transform: translateY(0);
        transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
    }

    span.node-cell-remaining-percent {
        display: none;
        opacity: 0;
        transform: translateY(-20px);
        transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
    }

    .node-cell:hover .node-cell-remaining-days {
        opacity: 0;
        transform: translateY(20px);
        display: none;
    }

    .node-cell:hover .node-cell-remaining-percent {
        display: block;
        opacity: 1;
        transform: translateY(0);
    }

    tr.accordion-toggle:hover {
        border-radius: 30px;
        background-color: rgba(0, 0, 0, 0);
        transition: all 0.3s ease;
    }

    .toolbox {
        position: fixed;
        bottom: 10px;
        right: 5px;
        z-index: 999999;
        transition: transform 0.3s ease, opacity 0.3s ease;
    }

    .toolbox:hover {
        transform: translateY(0) !important;
        opacity: 1 !important;
    }

    .toolbox i {
        backdrop-filter: blur(2px);
        border: 1.3px solid;
        display: block;
        color: rgba(241, 241, 241, 0);
        cursor: pointer;
        border-radius: 8px;
        font-size: 1rem;
        height: 2.2rem;
        width: 2.2rem;
        line-height: 2.2rem;
        text-align: center;
    }

    .toolbox .setTheme i.setTheme-dark,
    .toolbox .setTheme i.setTheme-light {
        font-size: 1rem;
    }

    .modal-content {
        backdrop-filter: blur(14px);
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        border-radius: 12px;
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%) scale(0.7);
        z-index: 1050;
    }

    .modal-header {
        padding: 15px;
        border-bottom: 1px solid #eee;
        border-radius: 12px 12px 0 0;
    }

    .modal-body {
        overflow: hidden;
        border-radius: 0 0 12px 12px;
    }

    .modal-header h4,
    .modal-header i,
    .modal-body,
    .modal-header .bi {
        font-size: 1.4rem;
    }

    body[theme="dark"] .modal-content {
        background-color: rgba(28, 29, 38, 0.4);
    }

    body[theme="light"] .modal-content {
        background-color: rgb(255 255 255 / 40%);
    }

    body[theme="dark"] .progress {
        border-radius: 7px;
    }

    body[theme="dark"] span.node-cell-remaining-percent {
        display: none;
    }

    body[theme="dark"] .table>tbody>tr>td:before,
    body[theme="dark"] .table>tfoot>tr>td:before,
    body[theme="dark"] .table>thead>tr>td:before,
    body[theme="dark"] .table>thead>tr.node-group-cell>th:before {
        background-color: rgba(58, 62, 65, 0);
    }

    body[theme="light"] .table>tbody>tr>td:before,
    body[theme="light"] .table>tfoot>tr>td:before,
    body[theme="light"] .table>thead>tr>td:before,
    body[theme="light"] .table>thead>tr.node-group-cell>th:before {
        background-color: rgba(221, 221, 221, 0);
    }

    body[theme="light"] .table-hover>tbody>tr:hover>td {
        background: #ffffff00;
    }

    body[theme="dark"] .table-hover>tbody>tr:hover>td {
        background: #ffffff00;
    }

    body[theme="dark"] .table-hover>tbody>tr:not(.expandRow):hover>td {
        background-color: rgb(183 184 190 / 0%);
    }

    .table-striped>tbody>tr:nth-of-type(odd) {
        background-color: #f9f9f900;
    }

    .table-hover>tbody>tr:hover {
        background-color: #f5f5f500;
    }

    body[theme="light"] .table-striped tbody>tr.even>td,
    body[theme="light"] .table-striped tbody>tr.even>th {
        background-color: #f9f9f900;
    }

    body[theme="dark"] .table-striped tbody>tr,
    body[theme="dark"] .table-striped tbody>tr.even>td,
    body[theme="dark"] .table-striped tbody>tr.even>th {
        background-color: rgb(28 29 38 / 0%);
    }

    body[theme="dark"] .table-striped tbody>tr,
    body[theme="dark"] .table-striped tbody>tr.odd>td,
    body[theme="dark"] .table-striped tbody>tr.odd>th {
        background-color: rgb(34 35 46 / 0%);
    }

    .chartbox {
        box-shadow: inset 0 0px 13px 0px rgba(0, 0, 0, 1.1);
        width: 100%;
        height: auto;
        user-select: none;
        -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
        position: relative;
        border: 2px solid #cccccc00;
        border-radius: 10px;
        overflow: hidden;
    }

    .tooltip {
        position: absolute;
        display: block;
        background-color: rgba(28, 29, 38, 0.75);
        backdrop-filter: blur(8px);
        -webkit-backdrop-filter: blur(8px);
        border: 1px solid rgba(255, 255, 255, 0.1);
        border-radius: 4px;
        color: rgb(241, 241, 241);
        font: 14px/21px "Microsoft YaHei";
        padding: 10px;
        transform: translate3d(828px, 68px, 0);
        pointer-events: none;
        visibility: hidden;
        opacity: 0;
        transition: all 0.2s cubic-bezier(0.23, 1, 0.32, 1);
    }

    .tooltip.visible {
        visibility: visible;
        opacity: 1;
    }

    small {
        font-size: 100% !important;
    }

    .node-cell.remaining .additional small {
        white-space: nowrap;
        font-size: 100% !important;
    }

    i.icon {
        border: 0px;
        display: unset;
    }

    @media (max-width: 1600px) {
        .container-fluid {
            width: 98%;
        }

        .remaining {
            width: 10%;
            min-width: 60px;
        }
    }

    @media (max-width: 1300px) {

        .price,
        .os,
        .remaining {
            display: none !important;
        }

        .load {
            width: 5%;
            min-width: 20px;
        }

        .cpu,
        .memory,
        .hdd {
            width: 8%;
            min-width: 50px;
        }
    }

    @media (max-width: 1200px) {
        .location {
            display: none !important;
        }

        .cpu,
        .memory,
        .hdd {
            width: 10%;
            min-width: 60px;
        }
    }

    @media (max-width: 1000px) {

        .load,
        .os,
        .price,
        .location,
        .uptime,
        .remaining {
            display: none !important;
        }

        .status {
            width: 6%;
            min-width: 25px;
        }

        .name {
            width: 10%;
            min-width: 45px;
        }

        .network {
            width: 20%;
            min-width: 100px;
        }

        .traffic {
            width: 14%;
            min-width: 100px;
        }

        .cpu,
        .memory,
        .hdd {
            width: 10%;
            min-width: 60px;
        }

        .progress-container {
            min-width: 35px;
        }

        .container-fluid {
            width: 98%;
        }

        .number-value {
            font-size: 11px;
        }
    }

    @media (max-width: 600px) {
        .container-fluid {
            width: 100%;
        }

        .arrow,
        .remaining {
            display: none !important;
        }

        .status {
            width: 5%;
            min-width: 20px;
        }

        .name {
            width: 8%;
            min-width: 40px;
        }

        .network,
        .traffic {
            width: 24%;
            min-width: 120px;
        }

        .cpu,
        .memory,
        .hdd {
            width: 4%;
            min-width: 15px;
        }

        .number-value {
            font-size: 10px;
        }

        .network span,
        .traffic span,
        .cpu span,
        .memory span,
        .hdd span {
            font-size: 10px;
        }

        small {
            font-size: 10px !important;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
        }
    }

    td.node-cell.network,
    td.node-cell.traffic {
        padding: 4px !important;
        position: relative;
    }

    .node-cell.network {
        min-width: 0px;
        max-width: 0px;
    }

    .data-box {
        position: absolute;
        top: 50%;
        left: 2px;
        right: 2px;
        transform: translateY(-50%);
        padding: 0px 6px;
        border: 1px solid rgba(0, 0, 0, 0.3);
        border-radius: 7px;
        background-color: rgba(255, 255, 255, 1);
        pointer-events: none;
        z-index: 1;
    }

    .value-container {
        display: flex;
        align-items: center;
        justify-content: space-between;
        width: 100%;
        gap: 1px;
    }

    .value-left,
    .value-right {
        flex: 1;
        min-width: 20px;
    }

    .value-left {
        text-align: right;
        padding-right: 2px;
    }

    .value-right {
        text-align: left;
        padding-left: 1px;
    }

    .units-and-arrows {
        display: flex;
        align-items: center;
        gap: 1px;
        white-space: nowrap;
        position: relative;
    }

    .unit-left,
    .unit-right {
        min-width: 16px;
        text-align: center;
        padding: 0px 2px;
        background-color: rgba(0, 0, 0, 0.05);
        border-radius: 4px;
        font-size: 0.9em;
        color: rgba(0, 0, 0, 0.6);
        border: 0.5px solid rgba(0, 0, 0, 0.1);
    }

    .unit-left[data-unit="b"],
    .unit-right[data-unit="b"] {
        color: #666;
        background-color: rgba(200, 200, 200, 0.2);
    }

    .unit-left[data-unit="k"],
    .unit-right[data-unit="k"] {
        color: #2196F3;
        background-color: rgba(33, 150, 243, 0.1);
    }

    .unit-left[data-unit="m"],
    .unit-right[data-unit="m"] {
        color: #4CAF50;
        background-color: rgba(76, 175, 80, 0.1);
    }

    .unit-left[data-unit="g"],
    .unit-right[data-unit="g"] {
        color: #FF9800;
        background-color: rgba(255, 152, 0, 0.1);
    }

    .arrow {
        padding: 0px 1px;
        background-color: rgba(0, 0, 0, 0);
        border-radius: 4px;
        font-size: 0.9em;
        color: rgba(0, 0, 0, 0.6);
        border: 0.5px solid rgba(0, 0, 0, 0.1);
    }

    .spacer {
        width: 1px;
        height: 25.3px;
        background-color: rgba(0, 0, 0, 0.2);
        margin: 0 1px;
    }

    body[theme="dark"] .unit-left,
    body[theme="dark"] .unit-right {
        border-color: rgba(255, 255, 255, 0.2);
    }

    body[theme="dark"] .unit-left[data-unit="b"],
    body[theme="dark"] .unit-right[data-unit="b"] {
        color: #aaa;
        background-color: rgba(255, 255, 255, 0.1);
    }

    body[theme="dark"] .unit-left[data-unit="k"],
    body[theme="dark"] .unit-right[data-unit="k"] {
        color: #64B5F6;
        background-color: rgba(33, 150, 243, 0.2);
    }

    body[theme="dark"] .unit-left[data-unit="m"],
    body[theme="dark"] .unit-right[data-unit="m"] {
        color: #81C784;
        background-color: rgba(76, 175, 80, 0.2);
    }

    body[theme="dark"] .unit-left[data-unit="g"],
    body[theme="dark"] .unit-right[data-unit="g"] {
        color: #FFB74D;
        background-color: rgba(255, 152, 0, 0.2);
    }

    body[theme="dark"] .spacer {
        background-color: rgba(255, 255, 255, 0.2);
    }

    body[theme="dark"] .data-box {
        border-color: rgba(255, 255, 255, 0.3);
        background-color: rgb(28 29 38);
    }

    body[theme="dark"] .arrow {
        background-color: rgba(255, 255, 255, 0.03);
        color: rgba(255, 255, 255, 0.6);
        border-color: rgba(255, 255, 255, 0.2);
    }
</style>
<script>
    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            mutation.addedNodes.forEach((node) => {
                if (node.classList?.contains('node-cell-expand')) {
                    const text = node.textContent;
                    const percentMatch = text.match(/\((\d+\.?\d*)%\)/);
                    if (percentMatch) {
                        const usage = parseFloat(percentMatch[1]);
                        node.style.setProperty('--usage', `${usage}%`);
                        if (usage > 80) {
                            node.setAttribute('data-usage-high', '');
                            node.style.borderLeft = '2px solid #ff4757';
                        } else if (usage > 60) {
                            node.setAttribute('data-usage-medium', '');
                            node.style.borderLeft = '2px solid #ffa502';
                        }
                    }
                }
            });
        });
    });
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
    // 主题切换功能
    (function () {
        function setThemeByPreference() {
            const isDarkMode = window.matchMedia("(prefers-color-scheme: dark)").matches;
            const button = document.querySelector(`.setTheme-${isDarkMode ? 'dark' : 'light'}`);
            button?.click();
        }
        setThemeByPreference();
        window.matchMedia("(prefers-color-scheme: dark)")
            .addEventListener("change", setThemeByPreference);
        window.addEventListener("load", () => {
            setThemeByPreference();
            document.querySelector('.bi-three-dots')?.click();
        });
    })();

    function splitValueAndUnit(text) {
        const match = text.trim().match(/^(\d+(?:\.\d+)?)\s*([a-zA-Z]*)$/);
        if (match) {
            const number = parseFloat(match[1]);
            const formattedValue = number.toFixed(1);
            // 将单位转换为小写用于样式匹配,但显示为大写
            const unit = match[2].toLowerCase();
            return {
                value: formattedValue,
                unit: unit.toUpperCase(), // 显示为大写
                unitClass: unit // 用于样式匹配的小写单位
            };
        }
        return { value: text, unit: '', unitClass: '' };
    }
    function createOverlay() {
        const cells = document.querySelectorAll('td.node-cell.network, td.node-cell.traffic');
        cells.forEach(cell => {
            if (!cell.querySelector('.data-box')) {
                const overlay = document.createElement('div');
                overlay.className = 'data-box';
                overlay.innerHTML = `
<div class="value-container">
    <span class="value-left"></span>
    <div class="units-and-arrows">
        <span class="unit-left"></span>
        <span class="arrow">↓</span>
        <span class="spacer"></span>
        <span class="arrow">↑</span>
        <span class="unit-right"></span>
    </div>
    <span class="value-right"></span>
</div>
`;
                cell.appendChild(overlay);
            }
        });
    }
    function updateOverlays() {
        const cells = document.querySelectorAll('td.node-cell.network, td.node-cell.traffic');
        cells.forEach(cell => {
            const overlay = cell.querySelector('.data-box');
            if (!overlay) return;
            const text = Array.from(cell.childNodes)
                .find(node => node.nodeType === Node.TEXT_NODE)?.textContent.trim() || '';
            if (!text || !text.includes('|')) return;
            const [left, right] = text.split('|').map(s => s.trim());
            const leftParts = splitValueAndUnit(left);
            const rightParts = splitValueAndUnit(right);
            const leftValue = overlay.querySelector('.value-left');
            const rightValue = overlay.querySelector('.value-right');
            const leftUnit = overlay.querySelector('.unit-left');
            const rightUnit = overlay.querySelector('.unit-right');
            if (leftValue && rightValue && leftUnit && rightUnit) {
                leftValue.textContent = leftParts.value;
                rightValue.textContent = rightParts.value;
                leftUnit.textContent = leftParts.unit;
                rightUnit.textContent = rightParts.unit;
                // 使用小写的unitClass来匹配CSS样式
                leftUnit.setAttribute('data-unit', leftParts.unitClass);
                rightUnit.setAttribute('data-unit', rightParts.unitClass);
            }
        });
    }
    // 初始化
    document.addEventListener('DOMContentLoaded', () => {
        createOverlay();
        updateOverlays();
    });
    // 定期更新
    setInterval(updateOverlays, 100);
    document.addEventListener('DOMContentLoaded', function () {
        document.querySelector('th.node-cell.network.center').innerHTML = '【下行】&nbsp;网速&nbsp【上行】';
        document.querySelector('th.node-cell.traffic.center').innerHTML = '【下载】&nbsp;流量&nbsp【上传】';
    });
</script>

基于我自己的站点修改,如果可以的话把你们的页面展示出来,看看哪里不合适

58 Likes

大佬太强了!

2 Likes

看着挺好的:+1:

3 Likes

感谢大佬分享 。

5 Likes

感谢分享 多谢大佬

2 Likes

css大佬 :+1:

1 Like

很好看的主题 谢谢分享

3 Likes

请教下,价格如何弄上去的

1 Like

用上了感谢佬!

1 Like

我必须马上开搞

5 Likes

真不错啊真不错,用上了谢谢佬

感谢分享大佬厉害啊

佬友,哪吒面板的水滴和地图是怎么搞的 :blush:

有点厉害支持~~

什么水滴呢?是原版自带的吗?


右下角那个

补丁

右下角按钮自动隐藏
放js里

class ToolboxManager {
    constructor() {
        this.toolbox = document.querySelector('.toolbox');
        this.lastScrollY = 0;
        this.scrollThreshold = 5;
        this.isHidden = false;
        
        this.initScrollListener();
    }

    initScrollListener() {
        let lastScrollY = window.scrollY;
        let ticking = false;

        window.addEventListener("scroll", () => {
            if (!ticking) {
                window.requestAnimationFrame(() => {
                    this.handleScroll(window.scrollY, lastScrollY);
                    lastScrollY = window.scrollY;
                    ticking = false;
                });
                ticking = true;
            }
        });
    }

    handleScroll(currentScrollY, lastScrollY) {
        if (Math.abs(currentScrollY - lastScrollY) > this.scrollThreshold) {
            if (currentScrollY > lastScrollY && !this.isHidden) {
                this.hideToolbox();
            } else if (currentScrollY < lastScrollY && this.isHidden) {
                this.showToolbox();
            }
        }
        
        if (currentScrollY <= 0) {
            this.showToolbox();
        }
    }

    hideToolbox() {
        // 计算需要位移的距离为工具栏的宽度加上右侧间距
        const toolboxWidth = this.toolbox.offsetWidth;
        this.toolbox.style.transform = `translateX(${toolboxWidth + 10}px)`;  // 10px作为额外位移确保完全隐藏
        this.isHidden = true;
    }

    showToolbox() {
        this.toolbox.style.transform = "translateX(0)";
        this.isHidden = false;
    }
}

// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', () => {
    new ToolboxManager();
});

这是原版就有的啊

1 Like

啊,那应该是我的版本太老了。好久没更新了
哈哈,谢谢佬友

大佬AList美化代码可以分享吗?