油猴脚本:便于Google AI Studio移动端用户的快捷操作栏
- 内容介绍
- 文章标签
- 相关推荐
4月20日开始Google one(Gemini Pro套餐)在Google AI Studio有更多额度了,在此分享一个本人自制移动端用户专用的油猴脚本。
经常在移动端用Google AI Studio的佬友应该都懂,填充个提示词需要点好几个地方,开启新对话按钮太靠上点击费力,还有不打开侧边栏看不见当前所选的模型,这个脚本就是解决这个问题的,我在输入框上方集成了这些功能的按钮,具体效果如图所示。
Screenshot2026-04-21-20-03-55-472com.xbrowser.play1220×2712 242 KB
// ==UserScript==
// @name Google AI Studio 移动端快捷操作栏
// @namespace https://tampermonkey.net/
// @version 5.6
// @description “NEW”按钮用于开启新对话窗口,“ON”按钮用于打开填充System instructions面板,“OFF”按钮用于关闭System instructions面板;按钮上方横列显示当前模型名称。
// @match https://aistudio.google.com/*
// @run-at document-idle
// @grant none
// ==/UserScript==
(function () {
'use strict';
const SCAN_INTERVAL = 500;
const GAP_TO_INPUT = 20;
const wrap = document.createElement('div');
wrap.id = 'aiStudioCustomBtnGroup';
const css = document.createElement('style');
css.textContent = `
#aiStudioCustomBtnGroup {
position: fixed;
display: flex;
flex-direction: column;
align-items: center;
gap: 5px;
z-index: 2147483647;
pointer-events: none;
transform: translate(-50%, -100%);
transition: opacity 0.2s ease;
opacity: 0;
padding-bottom: 2px;
}
#custom-model-name {
font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', sans-serif;
font-size: 10.5px;
font-weight: 600;
letter-spacing: 0.04em;
color: rgba(50, 42, 36, 0.88);
white-space: nowrap;
pointer-events: none;
user-select: none;
padding: 3px 10px;
background: rgba(255, 248, 242, 0.82);
border-radius: 20px;
border: 0.5px solid rgba(180, 140, 110, 0.25);
margin-bottom: 1px;
}
.custom-btn-row {
display: flex;
gap: 6px;
pointer-events: none;
align-items: center;
justify-content: center;
}
.custom-circle-btn {
display: flex;
align-items: center;
justify-content: center;
width: 34px;
height: 34px;
border-radius: 50%;
color: #fff;
font-weight: 700;
font-size: 11px;
letter-spacing: 0.04em;
font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', sans-serif;
border: none;
pointer-events: auto;
cursor: pointer;
user-select: none;
transition: transform 0.12s ease, filter 0.12s ease;
padding: 0;
margin: 0;
-webkit-font-smoothing: antialiased;
background: #CC785C;
box-shadow: 0 1px 6px rgba(180, 90, 60, 0.4);
}
.custom-circle-btn:hover {
transform: scale(1.07);
filter: brightness(1.1);
}
.custom-circle-btn:active {
transform: scale(0.92);
filter: brightness(0.88);
}
`;
document.head.appendChild(css);
const modelLabel = document.createElement('div');
modelLabel.id = 'custom-model-name';
modelLabel.textContent = '—';
const makeBtn = (id, txt) => {
const el = document.createElement('button');
el.id = id;
el.className = 'custom-circle-btn';
el.textContent = txt;
return el;
};
const btnNew = makeBtn('custom-btn-new', 'NEW');
const btnOn = makeBtn('custom-btn-on', 'ON');
const btnOff = makeBtn('custom-btn-off', 'OFF');
const rowNew = document.createElement('div');
rowNew.className = 'custom-btn-row';
rowNew.appendChild(btnNew);
const rowOnOff = document.createElement('div');
rowOnOff.className = 'custom-btn-row';
rowOnOff.append(btnOn, btnOff);
wrap.append(modelLabel, rowNew, rowOnOff);
document.body.appendChild(wrap);
const updatePosition = () => {
let targetInput = null;
const selectors = ['[placeholder*="Start typing a prompt"]', '[placeholder*="Optional tone"]'];
for (const sel of selectors) {
const el = document.querySelector(sel);
if (el && el.getBoundingClientRect().width > 0) {
targetInput = el;
break;
}
}
if (targetInput) {
const rect = targetInput.getBoundingClientRect();
if (rect.top > 0) {
wrap.style.opacity = '1';
wrap.style.left = `${window.innerWidth / 2}px`;
wrap.style.top = `${rect.top - GAP_TO_INPUT}px`;
} else {
wrap.style.opacity = '0';
}
} else {
wrap.style.opacity = '0';
}
requestAnimationFrame(updatePosition);
};
const attachToTopLayer = () => {
try {
const vw = window.innerWidth;
const vh = window.innerHeight;
let bestEl = document.body;
let bestZ = -Infinity;
const all = document.body.querySelectorAll('*');
for (let i = 0; i < all.length; i++) {
const el = all[i];
if (el === wrap) continue;
const rect = el.getBoundingClientRect();
if (rect.width >= vw * 0.9 && rect.height >= vh * 0.9 && rect.left <= vw * 0.1 && rect.top <= vh * 0.1) {
const style = getComputedStyle(el);
if ((style.position === 'fixed' || style.position === 'absolute') && style.visibility !== 'hidden' && style.display !== 'none') {
let zi = parseInt(style.zIndex, 10);
if (Number.isNaN(zi)) zi = 0;
if (zi >= bestZ) { bestZ = zi; bestEl = el; }
}
}
}
if (!bestEl.contains(wrap) || bestEl.lastElementChild !== wrap) {
bestEl.appendChild(wrap);
}
} catch (e) {}
};
const readModel = () => {
try {
const raw = localStorage.getItem('aiStudioUserPreference');
if (!raw) return '—';
const pm = JSON.parse(raw)?.promptModel;
return pm ? pm.replace('models/', '') : '—';
} catch (e) {
return '—';
}
};
let lastModel = '';
const tickModel = () => {
const now = readModel();
if (now !== lastModel) { modelLabel.textContent = now; lastModel = now; }
};
requestAnimationFrame(updatePosition);
setInterval(attachToTopLayer, SCAN_INTERVAL);
tickModel();
setInterval(tickModel, 1000);
btnNew.addEventListener('click', () => {
document.querySelector('a[href*="prompts/new_chat"]')?.click();
setTimeout(() => {
document.querySelector("button[data-test-category-id='17']")?.click();
}, 50);
});
btnOn.addEventListener('click', () => {
const sysBtn = document.querySelector("button[aria-label='System instructions']");
if (sysBtn) {
sysBtn.click();
} else {
document.querySelector("button[aria-label='Toggle run settings panel']")?.click();
setTimeout(() => {
document.querySelector("button[aria-label='System instructions']")?.click();
}, 300);
}
});
btnOff.addEventListener('click', () => {
document.querySelector("button[aria-label='关闭面板'], button[aria-label='Close panel'], button[aria-label='Close']")?.click();
});
})();
网友解答:
--【壹】--:
佬的移动端用的是啥软件能支持油猴脚本的?
4月20日开始Google one(Gemini Pro套餐)在Google AI Studio有更多额度了,在此分享一个本人自制移动端用户专用的油猴脚本。
经常在移动端用Google AI Studio的佬友应该都懂,填充个提示词需要点好几个地方,开启新对话按钮太靠上点击费力,还有不打开侧边栏看不见当前所选的模型,这个脚本就是解决这个问题的,我在输入框上方集成了这些功能的按钮,具体效果如图所示。
Screenshot2026-04-21-20-03-55-472com.xbrowser.play1220×2712 242 KB
// ==UserScript==
// @name Google AI Studio 移动端快捷操作栏
// @namespace https://tampermonkey.net/
// @version 5.6
// @description “NEW”按钮用于开启新对话窗口,“ON”按钮用于打开填充System instructions面板,“OFF”按钮用于关闭System instructions面板;按钮上方横列显示当前模型名称。
// @match https://aistudio.google.com/*
// @run-at document-idle
// @grant none
// ==/UserScript==
(function () {
'use strict';
const SCAN_INTERVAL = 500;
const GAP_TO_INPUT = 20;
const wrap = document.createElement('div');
wrap.id = 'aiStudioCustomBtnGroup';
const css = document.createElement('style');
css.textContent = `
#aiStudioCustomBtnGroup {
position: fixed;
display: flex;
flex-direction: column;
align-items: center;
gap: 5px;
z-index: 2147483647;
pointer-events: none;
transform: translate(-50%, -100%);
transition: opacity 0.2s ease;
opacity: 0;
padding-bottom: 2px;
}
#custom-model-name {
font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', sans-serif;
font-size: 10.5px;
font-weight: 600;
letter-spacing: 0.04em;
color: rgba(50, 42, 36, 0.88);
white-space: nowrap;
pointer-events: none;
user-select: none;
padding: 3px 10px;
background: rgba(255, 248, 242, 0.82);
border-radius: 20px;
border: 0.5px solid rgba(180, 140, 110, 0.25);
margin-bottom: 1px;
}
.custom-btn-row {
display: flex;
gap: 6px;
pointer-events: none;
align-items: center;
justify-content: center;
}
.custom-circle-btn {
display: flex;
align-items: center;
justify-content: center;
width: 34px;
height: 34px;
border-radius: 50%;
color: #fff;
font-weight: 700;
font-size: 11px;
letter-spacing: 0.04em;
font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', sans-serif;
border: none;
pointer-events: auto;
cursor: pointer;
user-select: none;
transition: transform 0.12s ease, filter 0.12s ease;
padding: 0;
margin: 0;
-webkit-font-smoothing: antialiased;
background: #CC785C;
box-shadow: 0 1px 6px rgba(180, 90, 60, 0.4);
}
.custom-circle-btn:hover {
transform: scale(1.07);
filter: brightness(1.1);
}
.custom-circle-btn:active {
transform: scale(0.92);
filter: brightness(0.88);
}
`;
document.head.appendChild(css);
const modelLabel = document.createElement('div');
modelLabel.id = 'custom-model-name';
modelLabel.textContent = '—';
const makeBtn = (id, txt) => {
const el = document.createElement('button');
el.id = id;
el.className = 'custom-circle-btn';
el.textContent = txt;
return el;
};
const btnNew = makeBtn('custom-btn-new', 'NEW');
const btnOn = makeBtn('custom-btn-on', 'ON');
const btnOff = makeBtn('custom-btn-off', 'OFF');
const rowNew = document.createElement('div');
rowNew.className = 'custom-btn-row';
rowNew.appendChild(btnNew);
const rowOnOff = document.createElement('div');
rowOnOff.className = 'custom-btn-row';
rowOnOff.append(btnOn, btnOff);
wrap.append(modelLabel, rowNew, rowOnOff);
document.body.appendChild(wrap);
const updatePosition = () => {
let targetInput = null;
const selectors = ['[placeholder*="Start typing a prompt"]', '[placeholder*="Optional tone"]'];
for (const sel of selectors) {
const el = document.querySelector(sel);
if (el && el.getBoundingClientRect().width > 0) {
targetInput = el;
break;
}
}
if (targetInput) {
const rect = targetInput.getBoundingClientRect();
if (rect.top > 0) {
wrap.style.opacity = '1';
wrap.style.left = `${window.innerWidth / 2}px`;
wrap.style.top = `${rect.top - GAP_TO_INPUT}px`;
} else {
wrap.style.opacity = '0';
}
} else {
wrap.style.opacity = '0';
}
requestAnimationFrame(updatePosition);
};
const attachToTopLayer = () => {
try {
const vw = window.innerWidth;
const vh = window.innerHeight;
let bestEl = document.body;
let bestZ = -Infinity;
const all = document.body.querySelectorAll('*');
for (let i = 0; i < all.length; i++) {
const el = all[i];
if (el === wrap) continue;
const rect = el.getBoundingClientRect();
if (rect.width >= vw * 0.9 && rect.height >= vh * 0.9 && rect.left <= vw * 0.1 && rect.top <= vh * 0.1) {
const style = getComputedStyle(el);
if ((style.position === 'fixed' || style.position === 'absolute') && style.visibility !== 'hidden' && style.display !== 'none') {
let zi = parseInt(style.zIndex, 10);
if (Number.isNaN(zi)) zi = 0;
if (zi >= bestZ) { bestZ = zi; bestEl = el; }
}
}
}
if (!bestEl.contains(wrap) || bestEl.lastElementChild !== wrap) {
bestEl.appendChild(wrap);
}
} catch (e) {}
};
const readModel = () => {
try {
const raw = localStorage.getItem('aiStudioUserPreference');
if (!raw) return '—';
const pm = JSON.parse(raw)?.promptModel;
return pm ? pm.replace('models/', '') : '—';
} catch (e) {
return '—';
}
};
let lastModel = '';
const tickModel = () => {
const now = readModel();
if (now !== lastModel) { modelLabel.textContent = now; lastModel = now; }
};
requestAnimationFrame(updatePosition);
setInterval(attachToTopLayer, SCAN_INTERVAL);
tickModel();
setInterval(tickModel, 1000);
btnNew.addEventListener('click', () => {
document.querySelector('a[href*="prompts/new_chat"]')?.click();
setTimeout(() => {
document.querySelector("button[data-test-category-id='17']")?.click();
}, 50);
});
btnOn.addEventListener('click', () => {
const sysBtn = document.querySelector("button[aria-label='System instructions']");
if (sysBtn) {
sysBtn.click();
} else {
document.querySelector("button[aria-label='Toggle run settings panel']")?.click();
setTimeout(() => {
document.querySelector("button[aria-label='System instructions']")?.click();
}, 300);
}
});
btnOff.addEventListener('click', () => {
document.querySelector("button[aria-label='关闭面板'], button[aria-label='Close panel'], button[aria-label='Close']")?.click();
});
})();
网友解答:
--【壹】--:
佬的移动端用的是啥软件能支持油猴脚本的?

