// ==UserScript== // @name 独角鲸云 VPS 价格排序助手 // @namespace https://dash.fuckip.me/ // @version 1.0 // @description 在独角鲸云新建实例页面展示所有地区VPS方案,按价格从低到高排序,显示库存状态 // @author You // @match https://dash.fuckip.me/deploy* // @match https://dash.fuckip.me/* // @icon https://dash.fuckip.me/favicon.ico // @grant none // @run-at document-idle // ==/UserScript== (function () { 'use strict'; // ==================== 配置 ==================== const API_BASE = 'https://api.fuckip.me/api/v1'; const REFRESH_INTERVAL = 5 * 60 * 1000; // 5分钟自动刷新 // ==================== 样式注入 ==================== const STYLES = ` #narwhal-sort-panel { position: fixed; top: 70px; right: 16px; width: 480px; max-height: 85vh; background: #1a1b2e; border: 1px solid #2d2f45; border-radius: 12px; box-shadow: 0 8px 32px rgba(0,0,0,0.4); z-index: 10000; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; overflow: hidden; transition: all 0.3s ease; } #narwhal-sort-panel.collapsed { width: 44px; height: 44px; max-height: 44px; border-radius: 22px; cursor: pointer; display: flex; align-items: center; justify-content: center; } #narwhal-sort-panel.collapsed .panel-content { display: none; } #narwhal-sort-panel.collapsed .panel-toggle { display: none; } #narwhal-sort-panel.collapsed .panel-collapsed-icon { display: block; } .panel-header { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; font-size: 14px; font-weight: 600; cursor: move; user-select: none; } .panel-header .header-left { display: flex; align-items: center; gap: 8px; } .panel-toggle { background: rgba(255,255,255,0.2); border: none; color: white; padding: 2px 8px; border-radius: 4px; cursor: pointer; font-size: 12px; } .panel-toggle:hover { background: rgba(255,255,255,0.3); } .panel-toolbar { display: flex; align-items: center; gap: 8px; padding: 8px 16px; background: #1e1f36; border-bottom: 1px solid #2d2f45; flex-wrap: wrap; } .panel-toolbar select, .panel-toolbar input { background: #2d2f45; border: 1px solid #3d3f55; color: #e0e0e0; padding: 4px 8px; border-radius: 6px; font-size: 12px; outline: none; } .panel-toolbar select:focus, .panel-toolbar input:focus { border-color: #667eea; } .panel-toolbar input::placeholder { color: #666; } .toolbar-btn { background: #667eea; border: none; color: white; padding: 4px 10px; border-radius: 6px; cursor: pointer; font-size: 12px; white-space: nowrap; } .toolbar-btn:hover { background: #7c8ff0; } .toolbar-btn.danger { background: #e74c3c; } .toolbar-btn.danger:hover { background: #ff5e4f; } .stats-text { font-size: 11px; color: #888; margin-left: auto; } .panel-content { overflow-y: auto; max-height: calc(85vh - 120px); padding: 8px; } .panel-content::-webkit-scrollbar { width: 6px; } .panel-content::-webkit-scrollbar-track { background: transparent; } .panel-content::-webkit-scrollbar-thumb { background: #3d3f55; border-radius: 3px; } .vps-card { background: #252640; border: 1px solid #2d2f45; border-radius: 8px; padding: 10px 12px; margin-bottom: 6px; transition: all 0.2s ease; cursor: default; } .vps-card:hover { border-color: #667eea; background: #2a2b48; transform: translateX(-2px); } .vps-card.sold-out { opacity: 0.55; } .vps-card.is-free { border-color: #2ecc71; background: rgba(46,204,113,0.05); } .vps-card.is-free:hover { background: rgba(46,204,113,0.1); } .card-top { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 6px; } .card-name { font-size: 13px; font-weight: 600; color: #e0e0e0; max-width: 280px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .card-region { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: #aaa; background: #1a1b2e; padding: 2px 6px; border-radius: 4px; } .card-specs { display: flex; gap: 10px; flex-wrap: wrap; font-size: 11px; color: #888; margin-bottom: 6px; } .card-specs span { display: flex; align-items: center; gap: 3px; } .spec-label { color: #666; } .card-bottom { display: flex; justify-content: space-between; align-items: center; } .card-price { font-size: 16px; font-weight: 700; color: #2ecc71; } .card-price.is-free { color: #2ecc71; } .card-price.is-expensive { color: #e74c3c; } .card-tags { display: flex; gap: 4px; flex-wrap: wrap; } .tag { font-size: 10px; padding: 1px 5px; border-radius: 3px; background: #3d3f55; color: #aaa; } .tag.hot { background: rgba(231,76,60,0.2); color: #e74c3c; } .tag.cool { background: rgba(46,204,113,0.2); color: #2ecc71; } .stock-badge { font-size: 11px; padding: 2px 8px; border-radius: 10px; font-weight: 500; } .stock-badge.in-stock { background: rgba(46,204,113,0.15); color: #2ecc71; } .stock-badge.limited { background: rgba(241,196,15,0.15); color: #f1c40f; } .stock-badge.out-of-stock { background: rgba(231,76,60,0.15); color: #e74c3c; } .panel-footer { padding: 8px 16px; background: #1e1f36; border-top: 1px solid #2d2f45; display: flex; justify-content: space-between; align-items: center; font-size: 11px; color: #666; } .loading-overlay { display: flex; align-items: center; justify-content: center; padding: 40px; color: #888; font-size: 13px; gap: 8px; } .loading-spinner { width: 16px; height: 16px; border: 2px solid #3d3f55; border-top: 2px solid #667eea; border-radius: 50%; animation: spin 0.8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .error-msg { padding: 20px; text-align: center; color: #e74c3c; font-size: 13px; } .panel-collapsed-icon { display: none; font-size: 20px; } `; // 注入样式 const styleEl = document.createElement('style'); styleEl.textContent = STYLES; document.head.appendChild(styleEl); // ==================== 工具函数 ==================== function getToken() { try { const authStr = localStorage.getItem('auth-storage'); if (!authStr) return null; const auth = JSON.parse(authStr); return auth?.state?.token || null; } catch (e) { return null; } } function formatPrice(price) { if (price === 0) return 'FREE'; return '$' + price.toFixed(2) + '/mo'; } function getPriceClass(price) { if (price === 0) return 'is-free'; if (price >= 0.5) return 'is-expensive'; return ''; } function getStockBadge(soldOut, available, maxQty) { if (soldOut || available === 0) { return '售罄'; } if (available <= 5) { return `仅剩 ${available}`; } return `库存 ${available}`; } function formatRam(mb) { if (mb >= 1024) return (mb / 1024) + 'GB'; return mb + 'MB'; } function formatTraffic(gb) { if (gb >= 1000) return (gb / 1000).toFixed(gb % 1000 === 0 ? 0 : 1) + 'TB'; return gb + 'GB'; } function getTagClass(tag) { const hotWords = ['解锁', '快乐', '直连', 'CN2', 'cn2']; const coolWords = ['落地', '独立']; if (hotWords.some(w => tag.includes(w))) return 'hot'; if (coolWords.some(w => tag.includes(w))) return 'cool'; return ''; } // ==================== 主逻辑 ==================== let allPlans = []; let currentSort = 'price-asc'; let currentRegion = 'all'; let searchKeyword = ''; let hideSoldOut = false; // 创建面板 DOM function createPanel() { const panel = document.createElement('div'); panel.id = 'narwhal-sort-panel'; panel.innerHTML = `