您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
专业级OSS文件查看器
- // ==UserScript==
- // @name OSS JSON Viewer Pro
- // @namespace http://your-namespace.com
- // @version 5.1
- // @description 专业级OSS文件查看器
- // @match *://*.aliyuncs.com/*
- // @grant GM_xmlhttpRequest
- // @grant GM_addStyle
- // @run-at document-start
- // @license MIT
- // ==/UserScript==
- (function() {
- 'use strict';
- // 立即停止原始加载
- window.stop();
- document.documentElement.innerHTML = '';
- // 创建容器
- const container = document.createElement('div');
- container.id = 'json-viewer-pro';
- document.documentElement.appendChild(container);
- // 加载动画
- container.innerHTML = `<div class="loader"></div>`;
- // 样式注入
- GM_addStyle(`
- #json-viewer-pro {
- padding: 20px;
- font-family: 'Consolas', monospace;
- background: #1e1e1e;
- color: #d4d4d4;
- min-height: 100vh;
- }
- .json-key {
- color: #9cdcfe;
- font-weight: bold;
- }
- .json-string {
- color: #ce9178;
- background: rgba(206,145,120,0.1);
- padding: 2px 4px;
- border-radius: 3px;
- }
- .json-number {
- color: #b5cea8;
- font-weight: bold;
- }
- .json-boolean {
- color: #569cd6;
- font-style: italic;
- }
- .json-null {
- color: #808080;
- font-style: italic;
- }
- .loader {
- border: 4px solid #f3f3f3;
- border-top: 4px solid #3498db;
- border-radius: 50%;
- width: 40px;
- height: 40px;
- animation: spin 2s linear infinite;
- margin: 20px auto;
- }
- @keyframes spin {
- 0% { transform: rotate(0deg); }
- 100% { transform: rotate(360deg); }
- }
- .json-item {
- margin: 4px 0;
- padding-left: 20px;
- position: relative;
- border-left: 1px solid rgba(255,255,255,0.1);
- }
- .json-item::before {
- content: '';
- position: absolute;
- left: 0;
- top: 0;
- width: 12px;
- height: 100%;
- border-left: 1px solid rgba(255,255,255,0.1);
- }
- .json-item:hover {
- background: rgba(255,255,255,0.03);
- }
- .json-collapse {
- cursor: pointer;
- margin-right: 5px;
- }
- .json-collapse::after {
- content: '▼';
- font-size: 10px;
- color: #9cdcfe;
- margin-right: 5px;
- }
- .json-collapse.collapsed::after {
- content: '▶';
- }
- .json-count {
- color: #888;
- font-size: 0.9em;
- margin-left: 5px;
- }
- .json-image {
- max-width: 100%;
- max-height: 200px;
- margin: 5px 0;
- border-radius: 3px;
- box-shadow: 0 0 5px rgba(0,0,0,0.2);
- }
- .json-text {
- white-space: pre-wrap;
- background: rgba(255,255,255,0.05);
- padding: 5px;
- border-radius: 3px;
- margin: 5px 0;
- }
- .json-content {
- margin-left: 8px;
- padding-left: 12px;
- border-left: 1px dashed rgba(255,255,255,0.1);
- }
- button:hover {
- background: #1177bb !important;
- }
- button:active {
- background: #0e5389 !important;
- }
- `);
- // 获取数据
- GM_xmlhttpRequest({
- method: 'GET',
- url: location.href,
- responseType: 'arraybuffer',
- onload: (res) => {
- container.innerHTML = '';
- try {
- const decoder = new TextDecoder('utf-8');
- const jsonData = JSON.parse(decoder.decode(res.response));
- renderJSON(jsonData);
- } catch(e) {
- container.innerHTML = `<div class="error">数据解析失败: ${e.message}</div>`;
- }
- },
- onerror: (err) => {
- container.innerHTML = `<div class="error">请求失败: ${err.statusText}</div>`;
- }
- });
- function addControlButtons(container, data) {
- const buttonStyle = `
- padding: 6px 12px;
- margin-right: 10px;
- background: #0e639c;
- color: white;
- border: none;
- border-radius: 4px;
- cursor: pointer;
- font-size: 12px;
- `;
- const buttonContainer = document.createElement('div');
- buttonContainer.style.marginBottom = '20px';
- // 复制按钮
- const copyButton = document.createElement('button');
- copyButton.textContent = '复制 JSON';
- copyButton.style.cssText = buttonStyle;
- copyButton.onclick = () => {
- navigator.clipboard.writeText(JSON.stringify(data, null, 2))
- .then(() => {
- copyButton.textContent = '已复制!';
- setTimeout(() => copyButton.textContent = '复制 JSON', 2000);
- })
- .catch(err => alert('复制失败: ' + err));
- };
- // 展开全部按钮
- const expandButton = document.createElement('button');
- expandButton.textContent = '展开全部';
- expandButton.style.cssText = buttonStyle;
- expandButton.onclick = () => {
- container.querySelectorAll('.json-content').forEach(content => {
- content.style.display = '';
- });
- container.querySelectorAll('.json-collapse').forEach(collapse => {
- collapse.classList.remove('collapsed');
- });
- };
- // 折叠全部按钮
- const collapseButton = document.createElement('button');
- collapseButton.textContent = '折叠全部';
- collapseButton.style.cssText = buttonStyle;
- collapseButton.onclick = () => {
- container.querySelectorAll('.json-content').forEach(content => {
- content.style.display = 'none';
- });
- container.querySelectorAll('.json-collapse').forEach(collapse => {
- collapse.classList.add('collapsed');
- });
- };
- buttonContainer.appendChild(copyButton);
- buttonContainer.appendChild(expandButton);
- buttonContainer.appendChild(collapseButton);
- return buttonContainer;
- }
- function renderJSON(data) {
- const countChildren = (obj) => {
- if (!obj || typeof obj !== 'object') return 0;
- return Object.keys(obj).length;
- };
- const render = (obj, indent = 0) => {
- if (Array.isArray(obj)) {
- return obj.map(item => {
- if (typeof item === 'object' && item !== null) {
- return `
- <div class="json-item">
- {
- ${renderObject(item, indent + 1)}
- }
- </div>
- `;
- }
- return `
- <div class="json-item">
- ${formatValue(item)}
- </div>
- `;
- }).join('');
- }
- return renderObject(obj, indent);
- };
- const renderObject = (obj, indent = 0) => {
- return Object.entries(obj).map(([key, value]) => {
- const indentStr = ' '.repeat(indent * 4);
- const count = countChildren(value);
- if (typeof value === 'object' && value !== null) {
- const isArray = Array.isArray(value);
- return `
- <div class="json-item" data-json='${JSON.stringify(value)}'>
- <span class="json-collapse"></span>
- <span class="json-key">"${key}"</span>:
- ${isArray ?
- `[<span class="json-count">${count} items</span>` :
- `{<span class="json-count">${count} keys</span>`}
- <div class="json-content">
- ${render(value, indent + 1)}
- </div>
- ${isArray ? ']' : '}'},
- </div>
- `;
- }
- // Handle image URLs
- if (typeof value === 'string' &&
- (value.match(/\.(jpeg|jpg|gif|png)$/) ||
- value.startsWith('data:image/'))) {
- return `
- <div class="json-item">
- <span class="json-key">"${key}"</span>:
- <img src="${value}" class="json-image" alt="${key} image"/>
- </div>
- `;
- }
- // Handle multi-line text
- if (typeof value === 'string' && value.includes('\n')) {
- return `
- <div class="json-item">
- <span class="json-key">"${key}"</span>:
- <div class="json-text">${value}</div>
- </div>
- `;
- }
- return `
- <div class="json-item">
- <span class="json-key">"${key}"</span>:
- ${formatValue(value)},
- </div>
- `;
- }).join('');
- };
- const formatValue = (value) => {
- if (typeof value === 'string') {
- // Skip formatting if it's an image URL or multi-line text
- if (value.match(/\.(jpeg|jpg|gif|png)$/) ||
- value.startsWith('data:image/') ||
- value.includes('\n')) {
- return '';
- }
- return `<span class="json-string">"${value}"</span>`;
- }
- if (typeof value === 'number') return `<span class="json-number">${value}</span>`;
- if (typeof value === 'boolean') return `<span class="json-boolean">${value}</span>`;
- if (value === null) return `<span class="json-null">null</span>`;
- return '';
- };
- container.innerHTML = '';
- container.appendChild(addControlButtons(container, data));
- const jsonContainer = document.createElement('div');
- jsonContainer.style.marginTop = '20px';
- jsonContainer.innerHTML = render(data);
- container.appendChild(jsonContainer);
- // 修改折叠功能
- document.querySelectorAll('.json-collapse').forEach(collapse => {
- collapse.addEventListener('click', function() {
- const parent = this.parentElement;
- const content = parent.querySelector('.json-content');
- const countSpan = parent.querySelector('.json-count');
- const jsonData = JSON.parse(parent.getAttribute('data-json'));
- const isArray = Array.isArray(jsonData);
- if (content.style.display === 'none') {
- content.style.display = '';
- countSpan.textContent = isArray ?
- `${jsonData.length} items` :
- `${Object.keys(jsonData).length} keys`;
- } else {
- content.style.display = 'none';
- countSpan.textContent = isArray ?
- `${jsonData.length} items` :
- `${Object.keys(jsonData).length} keys`;
- }
- this.classList.toggle('collapsed');
- });
- });
- }
- })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址