// ==UserScript==
// @name Multi Screen Manager/多屏分屏管理器
// @namespace http://lozn.top/
// @version 1.02
// @description 支持任意数量屏幕的分屏管理器 可以在一个标签选项卡打开2个百度展示2个实时k线行情 Support Multi page show same tab, ,coustm frame split!
// @author lozn
// @license MIT
// @match *://*/*
// @grant none
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
console.log('多屏管理器已加载');
let screens = [];
let isEnabled = false;
let nextScreenId = 1;
// 存档和恢复功能
const STORAGE_KEY = 'multiscreen_config';
// 保存配置到localStorage
function saveConfig() {
const config = {
screens: screens,
isEnabled: isEnabled,
nextScreenId: nextScreenId,
timestamp: Date.now()
};
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(config));
console.log('配置已保存:', config);
} catch (e) {
console.error('保存配置失败:', e);
}
}
// 从localStorage恢复配置
function loadConfig() {
try {
const saved = localStorage.getItem(STORAGE_KEY);
if (saved) {
const config = JSON.parse(saved);
screens = config.screens || [];
isEnabled = config.isEnabled || false;
nextScreenId = config.nextScreenId || 1;
console.log('配置已恢复:', config);
// 如果之前是启用状态,自动恢复
if (isEnabled && screens.length > 0) {
setTimeout(() => {
enableSplitMode();
}, 1500); // 稍微延迟确保页面完全加载
}
return true;
}
} catch (e) {
console.error('恢复配置失败:', e);
}
return false;
}
// 清除存档
function clearConfig() {
try {
localStorage.removeItem(STORAGE_KEY);
console.log('配置已清除');
} catch (e) {
console.error('清除配置失败:', e);
}
}
// 创建主控制悬浮窗
function createMainFloatingWindow() {
const floatingWindow = document.createElement('div');
floatingWindow.id = 'multi-screen-float';
floatingWindow.innerHTML = '📺';
floatingWindow.style.cssText = `
position: fixed;
top: 20%;
right: 20px;
width: 50px;
height: 50px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 12px;
cursor: pointer;
font-size: 20px;
z-index: 999999;
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
font-family: Arial, sans-serif;
`;
// 悬停效果
floatingWindow.onmouseenter = () => {
floatingWindow.style.transform = 'scale(1.1)';
floatingWindow.style.boxShadow = '0 6px 25px rgba(0,0,0,0.4)';
};
floatingWindow.onmouseleave = () => {
floatingWindow.style.transform = 'scale(1)';
floatingWindow.style.boxShadow = '0 4px 20px rgba(0,0,0,0.3)';
};
floatingWindow.onclick = () => {
console.log('主控制窗口被点击');
if (isEnabled) {
showManageDialog();
} else {
showInitDialog();
}
};
document.body.appendChild(floatingWindow);
return floatingWindow;
}
// 初始化对话框
function showInitDialog() {
const dialog = createDialog('🚀 多屏分屏管理器');
dialog.innerHTML += `
<div style="margin-bottom: 20px; text-align: center; color: #666;">
创建您的第一个分屏布局
</div>
<div style="margin-bottom: 15px;">
<label style="display: block; margin-bottom: 5px; font-weight: bold;">初始屏幕数量:</label>
<select id="screen-count" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 5px;">
<option value="2">2个屏幕</option>
<option value="3">3个屏幕</option>
<option value="4">4个屏幕</option>
<option value="6">6个屏幕 (2x3)</option>
</select>
</div>
<div style="text-align: center; margin-top: 20px;">
<button id="create-screens" style="background: #667eea; color: white; padding: 12px 24px; border: none; border-radius: 5px; cursor: pointer; margin-right: 10px; font-size: 14px;">创建屏幕</button>
<button id="cancel-init" style="background: #ccc; color: #333; padding: 12px 24px; border: none; border-radius: 5px; cursor: pointer; font-size: 14px;">取消</button>
</div>
`;
document.getElementById('create-screens').onclick = () => {
const count = parseInt(document.getElementById('screen-count').value);
createInitialScreens(count);
closeDialog();
};
document.getElementById('cancel-init').onclick = closeDialog;
}
// 管理对话框
function showManageDialog() {
const dialog = createDialog('🎛️ 屏幕管理器');
let screensHtml = '';
screens.forEach((screen, index) => {
screensHtml += `
<div style="display: flex; align-items: center; margin-bottom: 10px; padding: 10px; background: #f8f9fa; border-radius: 5px;">
<span style="font-weight: bold; margin-right: 10px; min-width: 60px;">屏幕${index + 1}:</span>
<input type="text" id="url-${screen.id}" value="${screen.url}" placeholder="https://example.com"
style="flex: 1; padding: 5px; border: 1px solid #ddd; border-radius: 3px; margin-right: 10px;">
<button onclick="updateScreenUrl(${screen.id})" style="background: #28a745; color: white; border: none; padding: 5px 10px; border-radius: 3px; cursor: pointer; margin-right: 5px;">更新</button>
<button onclick="removeScreen(${screen.id})" style="background: #dc3545; color: white; border: none; padding: 5px 10px; border-radius: 3px; cursor: pointer;">删除</button>
</div>
`;
});
dialog.innerHTML += `
<div style="max-height: 300px; overflow-y: auto; margin-bottom: 20px;">
${screensHtml}
</div>
<div style="text-align: center; margin-bottom: 15px;">
<button id="add-screen" style="background: #17a2b8; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; margin-right: 10px;">➕ 添加屏幕</button>
<button id="reset-layout" style="background: #ffc107; color: #333; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; margin-right: 10px;">🔄 重置布局</button>
</div>
<div style="text-align: center; margin-bottom: 15px;">
<button id="save-config" style="background: #28a745; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; margin-right: 10px;">💾 保存配置</button>
<button id="load-config" style="background: #17a2b8; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; margin-right: 10px;">📂 恢复配置</button>
<button id="clear-config" style="background: #fd7e14; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer;">🗑️ 清除存档</button>
</div>
<div style="text-align: center;">
<button id="close-manager" style="background: #6c757d; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; margin-right: 10px;">关闭管理器</button>
<button id="exit-split" style="background: #dc3545; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer;">退出分屏</button>
</div>
<div style="margin-top: 15px; font-size: 12px; color: #999; text-align: center;">
当前共有 ${screens.length} 个屏幕 | 配置会自动保存
</div>
`;
// 将函数添加到全局作用域以便onclick调用
window.updateScreenUrl = updateScreenUrl;
window.removeScreen = removeScreen;
document.getElementById('add-screen').onclick = () => {
addNewScreen();
closeDialog();
showManageDialog(); // 重新打开以刷新列表
};
document.getElementById('reset-layout').onclick = () => {
resetLayout();
closeDialog();
};
document.getElementById('save-config').onclick = () => {
saveConfig();
alert('✅ 配置已保存!下次打开页面会自动恢复。');
};
document.getElementById('load-config').onclick = () => {
if (loadConfig()) {
alert('✅ 配置已恢复!');
closeDialog();
if (isEnabled) {
updateLayout();
}
} else {
alert('❌ 没有找到保存的配置。');
}
};
document.getElementById('clear-config').onclick = () => {
if (confirm('确定要清除所有存档配置吗?')) {
clearConfig();
alert('🗑️ 存档已清除!');
}
};
document.getElementById('close-manager').onclick = closeDialog;
document.getElementById('exit-split').onclick = () => {
exitSplitMode();
closeDialog();
};
}
// 创建通用对话框
function createDialog(title) {
const overlay = document.createElement('div');
overlay.id = 'dialog-overlay';
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
z-index: 1000000;
display: flex;
align-items: center;
justify-content: center;
`;
const dialog = document.createElement('div');
dialog.id = 'screen-dialog';
dialog.style.cssText = `
background: white;
padding: 30px;
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
font-family: Arial, sans-serif;
min-width: 500px;
max-width: 80vw;
max-height: 80vh;
overflow-y: auto;
`;
dialog.innerHTML = `
<div style="font-size: 20px; font-weight: bold; margin-bottom: 20px; color: #333; text-align: center;">
${title}
</div>
`;
overlay.appendChild(dialog);
document.body.appendChild(overlay);
overlay.onclick = (e) => {
if (e.target === overlay) closeDialog();
};
return dialog;
}
function closeDialog() {
const overlay = document.getElementById('dialog-overlay');
if (overlay) overlay.remove();
}
// 创建初始屏幕
function createInitialScreens(count) {
screens = [];
for (let i = 0; i < count; i++) {
screens.push({
id: nextScreenId++,
url: i === 0 ? 'https://www.baidu.com' : i === 1 ? 'https://www.google.com' : 'about:blank'
});
}
enableSplitMode();
// 自动保存配置
saveConfig();
}
// 添加新屏幕
function addNewScreen() {
screens.push({
id: nextScreenId++,
url: 'about:blank'
});
if (isEnabled) {
updateLayout();
}
// 自动保存配置
saveConfig();
}
// 删除屏幕
function removeScreen(screenId) {
if (screens.length <= 1) {
alert('至少需要保留一个屏幕!');
return;
}
screens = screens.filter(screen => screen.id !== screenId);
updateLayout();
// 自动保存配置
saveConfig();
// 重新打开管理对话框以刷新列表
closeDialog();
setTimeout(() => showManageDialog(), 100);
}
// 更新屏幕URL
function updateScreenUrl(screenId) {
const urlInput = document.getElementById(`url-${screenId}`);
const newUrl = urlInput.value.trim();
if (!newUrl) {
alert('请输入有效的URL!');
return;
}
const screen = screens.find(s => s.id === screenId);
if (screen) {
screen.url = newUrl;
if (isEnabled) {
const iframe = document.getElementById(`iframe-${screenId}`);
if (iframe) {
iframe.src = newUrl;
}
}
// 自动保存配置
saveConfig();
}
alert('URL已更新并保存!');
}
// 启用分屏模式
function enableSplitMode() {
if (screens.length === 0) return;
// 隐藏原始内容
document.body.style.overflow = 'hidden';
createScreenLayout();
updateFloatingWindow();
isEnabled = true;
// 自动保存配置
saveConfig();
console.log('分屏模式已启用,共', screens.length, '个屏幕');
}
// 创建屏幕布局
function createScreenLayout() {
const container = document.createElement('div');
container.id = 'multi-screen-container';
container.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: grid;
gap: 2px;
background: #333;
z-index: 999998;
`;
// 计算网格布局
const { rows, cols } = calculateGridLayout(screens.length);
container.style.gridTemplateRows = `repeat(${rows}, 1fr)`;
container.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
// 创建iframe
screens.forEach(screen => {
const iframe = document.createElement('iframe');
iframe.id = `iframe-${screen.id}`;
iframe.src = screen.url;
iframe.style.cssText = `
width: 100%;
height: 100%;
border: none;
background: white;
`;
container.appendChild(iframe);
});
document.body.appendChild(container);
}
// 计算网格布局
function calculateGridLayout(count) {
if (count <= 2) return { rows: 1, cols: count };
if (count <= 4) return { rows: 2, cols: 2 };
if (count <= 6) return { rows: 2, cols: 3 };
if (count <= 9) return { rows: 3, cols: 3 };
if (count <= 12) return { rows: 3, cols: 4 };
return { rows: Math.ceil(Math.sqrt(count)), cols: Math.ceil(Math.sqrt(count)) };
}
// 更新布局
function updateLayout() {
const container = document.getElementById('multi-screen-container');
if (container) {
container.remove();
createScreenLayout();
}
}
// 重置布局
function resetLayout() {
updateLayout();
}
// 退出分屏模式
function exitSplitMode() {
const container = document.getElementById('multi-screen-container');
if (container) {
container.remove();
}
document.body.style.overflow = '';
updateFloatingWindow();
isEnabled = false;
// 保存退出状态
saveConfig();
console.log('已退出分屏模式');
}
// 更新悬浮窗状态
function updateFloatingWindow() {
const floatingWindow = document.getElementById('multi-screen-float');
if (floatingWindow) {
if (isEnabled) {
floatingWindow.innerHTML = '⚙️';
floatingWindow.style.background = 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)';
floatingWindow.title = '管理屏幕';
} else {
floatingWindow.innerHTML = '📺';
floatingWindow.style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
floatingWindow.title = '启动多屏';
}
}
}
// 检查是否在iframe中
function isInIframe() {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
// 初始化 - 只在主页面运行
function init() {
// 如果在iframe中,不执行任何操作
if (isInIframe()) {
console.log('在iframe中,跳过脚本初始化');
return;
}
// 先尝试恢复配置
const configLoaded = loadConfig();
setTimeout(() => {
createMainFloatingWindow();
if (configLoaded) {
console.log('欢迎回来!已自动恢复之前的配置。');
}
}, 1000);
}
init();
})();