快捷输入
一、前言
由于洛谷在聊天时插入图片太过麻烦,所以我制作了快捷输入脚本 , 效果如下:
二、安装步骤
Edge 浏览器安装
- 打开 Edge 浏览器,点击右上角的 三个点 ,在下拉菜单中选择 扩展 , 然后点击 管理扩展(或直接访问
edge://extensions/) 。 - 开启页面左侧的 开发人员模式 模式 。
- 点击底部的 获取 Microsoft Edge 扩展,搜索“Tampermonkey”,点击“获取” ,安装后浏览器右上角会显示油猴图标。
Google Chrome 浏览器安装
由于 Chrome 的应用商店无法直接访问,所以请参考第三方教程安装:谷歌浏览器 Tampermonkey 安装方式 。
安装快捷输入脚本
- 点击浏览器右上角 油猴图标,在弹出的选项中选择 添加新脚本 。
- 删除默认的内容,将下面的脚本复制进去:
// ==UserScript==
// @name 快捷输入(跨站跨浏览器版)
// @namespace http://tampermonkey.net/
// @version 12.0
// @description 支持跨网站存储,可导出导入数据实现跨浏览器记忆
// @author p1
// @match *://*/*
// @grant GM_addStyle
// @grant GM_getResourceText
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @resource FONTAWESOME_CSS https://cdn.jsdelivr.net/npm/[email protected]/css/font-awesome.min.css
// @run-at document-end
// ==/UserScript==
(function() {'use strict';
const CONSTANTS = Object.freeze({
GRID_COLUMNS: 3, // 网格列数
FIXED_ITEM_SIZE: 60, // 项目尺寸(px)
MAX_WIDTH: 600, // 最大宽度(px)
MIN_HEIGHT: 120, // 最小高度(px)
INITIAL_HEIGHT: 150, // 初始高度(px)
CONTENT_EXTRA_SPACE: 60, // 内容额外空间(px)
MAX_EXTRA_SPACE: 20, // 最大额外空间(px)
INPUT_LINE_HEIGHT: 1.6, // 输入框行高
OPEN_SCALE: 1, // 打开时缩放比例
ALLOW_HORIZONTAL_RESIZE: false, // 允许水平调整
ALLOW_VERTICAL_RESIZE: true, // 允许垂直调整
AUTO_RESIZE_ON_CONTENT_CHANGE: false, // 内容变化时自动调整
INPUT_PLUS_CHAR: "+", // 输入框加号字符
INPUT_PLUS_SIZE: "24px", // 加号大小
INPUT_PLUS_COLOR: "#666", // 加号颜色
INPUT_BACKGROUND: "#f8f9fa", // 输入框背景色
INPUT_BORDER: "1px dashed #ccc", // 输入框边框
INPUT_BORDER_RADIUS: "4px", // 输入框圆角
INPUT_BOX_SHADOW: "0 2px 5px rgba(0,0,0,0.1)", // 输入框阴影
DELETE_BUTTON_SIZE: 16, // 删除按钮大小(px)
DELETE_BUTTON_X_SIZE: "9px", // 删除按钮X符号大小
DELETE_BUTTON_X_OFFSET: "0px", // X符号偏移
IMAGE_PLACEHOLDER_PREFIX: "![]", // 图片占位符前缀
IMAGE_PLACEHOLDER_SUFFIX: "", // 图片占位符后缀
STORAGE_KEY: "customQuickInputItems", // 存储键名
EXPORT_FILE_NAME: "QuickInput_data.json" // 导出文件名
});
const MIN_WIDTH = CONSTANTS.GRID_COLUMNS * CONSTANTS.FIXED_ITEM_SIZE + (CONSTANTS.GRID_COLUMNS - 1) * 8 + 20;
let domCache = { list: null, input: null, overlay: null, activeInput: null };
const faCss = GM_getResourceText("FONTAWESOME_CSS");
GM_addStyle(faCss);
initStyles();
const StorageUtil = {
getItem: () => { try { const value = GM_getValue(CONSTANTS.STORAGE_KEY, []); return Array.isArray(value) ? value : []; } catch (e) { console.error('获取存储失败:', e); return []; } },
setItem: (value) => { try { if (Array.isArray(value)) GM_setValue(CONSTANTS.STORAGE_KEY, value); } catch (e) { console.error('设置存储失败:', e); } },
exportData: () => {
const data = StorageUtil.getItem();
const jsonStr = JSON.stringify(data, null, 2);
const blob = new Blob([jsonStr], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = CONSTANTS.EXPORT_FILE_NAME;
document.body.appendChild(a);
a.click();
setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 0);
},
importData: (file) => {
const reader = new FileReader();
reader.onload = (e) => {
try {
const data = JSON.parse(e.target.result);
if (Array.isArray(data)) {
StorageUtil.setItem(data);
if (domCache.list) renderListItems(domCache.list);
alert('导入成功!共导入 ' + data.length + ' 条数据');
} else alert('导入失败:文件格式不正确');
} catch (e) { console.error('导入解析失败:', e); alert('导入失败:文件格式错误'); }
};
reader.readAsText(file);
}
};
GM_registerMenuCommand("导出快捷输入数据", StorageUtil.exportData);
GM_registerMenuCommand("导入快捷输入数据", () => {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.json';
input.onchange = (e) => { const file = e.target.files[0]; if (file) StorageUtil.importData(file); };
input.click();
});
const DomUtil = {
createFragment: () => document.createDocumentFragment(),
removeElement: (el) => { if (el && el.parentNode) el.parentNode.removeChild(el); },
removeElements: (selector) => { document.querySelectorAll(selector).forEach(el => DomUtil.removeElement(el)); },
debounce: (func, wait = 100) => { let timeout; return function(...args) { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, args), wait); }; },
triggerInputEvents: (element) => {
element.dispatchEvent(new Event('input', { bubbles: true, cancelable: true }));
element.dispatchEvent(new Event('change', { bubbles: true, cancelable: true }));
element.dispatchEvent(new KeyboardEvent('keydown', { key: 'Insert', bubbles: true }));
element.dispatchEvent(new KeyboardEvent('keyup', { key: 'Insert', bubbles: true }));
if (element._valueTracker) element._valueTracker.setValue(element.value);
if (element.isContentEditable) {
element.dispatchEvent(new Event('DOMNodeInserted', { bubbles: true }));
element.dispatchEvent(new Event('DOMSubtreeModified', { bubbles: true }));
element.dispatchEvent(new Event('input', { bubbles: true, cancelable: true, composed: true }));
}
},
completeImageUrl: (url) => {
if (!url) return '';
if (/^https?:\/\//i.test(url)) return url;
if (url.startsWith('/')) return window.location.origin + url;
return `${window.location.protocol}//${url.replace(/^\/\//, '')}`;
},
insertContent: (inputElement, content) => {
if (isImageFormat(content)) {
const imageUrl = extractImageUrl(content);
const completedUrl = DomUtil.completeImageUrl(imageUrl);
return DomUtil.insertImage(inputElement, completedUrl);
} else return DomUtil.insertText(inputElement, content);
},
insertText: (inputElement, text) => {
try {
if (inputElement.isContentEditable) {
const selection = window.getSelection();
if (selection.rangeCount) {
const range = selection.getRangeAt(0);
range.deleteContents();
const textNode = document.createTextNode(text);
range.insertNode(textNode);
range.setStartAfter(textNode);
range.collapse(true);
selection.removeAllRanges();
selection.addRange(range);
return true;
}
} else {
const startPos = inputElement.selectionStart;
const endPos = inputElement.selectionEnd;
const currentValue = inputElement.value;
inputElement.value = currentValue.substring(0, startPos) + text + currentValue.substring(endPos);
const newCursorPos = startPos + text.length;
inputElement.setSelectionRange(newCursorPos, newCursorPos);
inputElement.focus();
return true;
}
} catch (e) { console.error('插入文本失败:', e); return false; }
},
insertImage: (inputElement, url) => {
try {
if (inputElement.isContentEditable) {
const selection = window.getSelection();
if (selection.rangeCount) {
const range = selection.getRangeAt(0);
range.deleteContents();
const img = document.createElement('img');
img.src = url;
img.alt = '插入的图片';
img.style.maxWidth = '100%';
range.insertNode(img);
const spaceNode = document.createTextNode(' ');
range.setStartAfter(img);
range.insertNode(spaceNode);
range.setStartAfter(spaceNode);
range.collapse(true);
selection.removeAllRanges();
selection.addRange(range);
return true;
}
} else {
const markdownImg = ``;
return DomUtil.insertText(inputElement, markdownImg);
}
} catch (e) { console.error('插入图片失败:', e); return DomUtil.insertText(inputElement, url); }
}
};
function initStyles() {
GM_addStyle(`.custom-right-click-list{position:absolute;background:white;border:1px solid #ccc;border-radius:4px;box-shadow:0 2px 10px rgba(0,0,0,0.1);padding:10px;margin:0;list-style:none;z-index:99999;display:grid;grid-template-columns:repeat(${CONSTANTS.GRID_COLUMNS},1fr);gap:8px;opacity:0;transform-origin:top left;transition:all 0.2s ease-out;pointer-events:none;overflow:auto;box-sizing:border-box;justify-items:start;align-items:start;align-content:start;scrollbar-width:none;}.custom-right-click-list::-webkit-scrollbar{display:none;}.custom-right-click-list.visible{opacity:1;transform:scale(${CONSTANTS.OPEN_SCALE});pointer-events:auto;}.custom-right-click-list li{width:${CONSTANTS.FIXED_ITEM_SIZE}px;height:${CONSTANTS.FIXED_ITEM_SIZE}px;padding:8px;cursor:pointer;transition:all 0.2s;position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center;text-align:center;box-sizing:border-box;border:1px solid transparent;box-shadow:0 2px 5px rgba(0,0,0,0.08);-webkit-user-select:none;user-select:none;}.custom-right-click-list li:hover{background-color:#f0f0f0;border-color:#ddd;border-radius:3px;box-shadow:0 3px 8px rgba(0,0,0,0.12);}.custom-right-click-list li:active{background-color:#e0e0e0;transform:scale(0.95);transition:all 0.1s;box-shadow:0 1px 3px rgba(0,0,0,0.05);}.custom-right-click-active{box-shadow:0 0 0 2px rgba(52,152,219,0.3)!important;transition:box-shadow 0.2s;}.custom-item-input-container{width:${CONSTANTS.FIXED_ITEM_SIZE}px;height:${CONSTANTS.FIXED_ITEM_SIZE}px;padding:0;cursor:pointer;position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center;box-sizing:border-box;border-radius:${CONSTANTS.INPUT_BORDER_RADIUS};box-shadow:${CONSTANTS.INPUT_BOX_SHADOW};background-color:${CONSTANTS.INPUT_BACKGROUND};border:${CONSTANTS.INPUT_BORDER};}.custom-item-plus-char{font-size:${CONSTANTS.INPUT_PLUS_SIZE};color:${CONSTANTS.INPUT_PLUS_COLOR};font-weight:bold;-webkit-user-select:none;user-select:none;}.custom-item-input{display:none;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:80%;max-width:500px;padding:15px;border:1px solid #ccc;border-radius:6px;box-shadow:0 4px 20px rgba(0,0,0,0.15);background:white;z-index:100000;min-height:120px;font-size:16px;line-height:${CONSTANTS.INPUT_LINE_HEIGHT};resize:vertical;max-height:300px;}.custom-item-input.visible{display:block;}.input-overlay{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.5);z-index:99999;}.input-overlay.visible{display:block;}.delete-item-btn{position:absolute;right:2px;top:2px;color:#ff4444;opacity:0;visibility:hidden;transition:all 0.2s ease;font-size:${CONSTANTS.DELETE_BUTTON_X_SIZE};width:${CONSTANTS.DELETE_BUTTON_SIZE}px;height:${CONSTANTS.DELETE_BUTTON_SIZE}px;display:flex;align-items:center;justify-content:center;padding:0;background:rgba(255,255,255,0.8);border-radius:50%;z-index:1;cursor:pointer;-webkit-user-select:none;user-select:none;transform:scale(0.9);}.delete-item-btn::before{content:'×';display:inline-block;line-height:1;position:relative;top:${CONSTANTS.DELETE_BUTTON_X_OFFSET};left:${CONSTANTS.DELETE_BUTTON_X_OFFSET};}.custom-right-click-list li:hover .delete-item-btn{opacity:0.85;visibility:visible;transform:scale(1);}.delete-item-btn:hover{background-color:#ff4444;color:white;opacity:0.9;transform:scale(1.1);box-shadow:0 0 2px rgba(255,68,68,0.5);}.delete-item-btn:active{transform:scale(0.95);opacity:0.95;}.menu-image-preview{max-width:100%;max-height:100%;object-fit:contain;border-radius:3px;box-shadow:0 1px 3px rgba(0,0,0,0.1);pointer-events:none;-webkit-user-select:none;user-select:none;}.item-text{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;max-height:100%;-webkit-user-select:none;user-select:none;}.image-item-indicator{position:absolute;bottom:2px;right:2px;font-size:8px;background:rgba(0,0,0,0.3);color:white;padding:1px 3px;border-radius:2px;}`);
}
function createList() {
if (domCache.list) return domCache.list;
DomUtil.removeElements('.custom-item-input, .input-overlay, #customRightClickList');
const list = document.createElement('ul');
list.className = 'custom-right-click-list';
list.id = 'customRightClickList';
list.style.width = `${MIN_WIDTH}px`;
list.style.height = `${CONSTANTS.INITIAL_HEIGHT}px`;
list.style.transform = `scale(${CONSTANTS.OPEN_SCALE})`;
list.addEventListener('click', handleListClick);
renderListItems(list);
document.body.appendChild(list);
domCache.list = list;
return list;
}
function handleListClick(e) {
e.stopPropagation();
const addBtn = e.target.closest('.custom-item-input-container');
if (addBtn) { showAddItemInput(domCache.list); return; }
const li = e.target.closest('li');
if (li && !li.classList.contains('custom-item-input-container')) {
const text = li.dataset.content;
if (text && domCache.activeInput) {
domCache.activeInput.classList.add('custom-right-click-active');
const success = DomUtil.insertContent(domCache.activeInput, text);
DomUtil.triggerInputEvents(domCache.activeInput);
setTimeout(() => { if (domCache.activeInput) domCache.activeInput.classList.remove('custom-right-click-active'); }, 300);
hideList();
}
}
}
function handleDeleteClick(e, text) {
e.stopPropagation();
e.preventDefault();
if (text) {
const customItems = StorageUtil.getItem();
const index = customItems.findIndex(item => item === text);
if (index !== -1) {
const li = e.target.closest('li');
if (li) {
li.style.transition = 'all 0.15s ease-out';
li.style.transform = 'scale(0.9)';
li.style.opacity = '0.3';
setTimeout(() => {
customItems.splice(index, 1);
StorageUtil.setItem(customItems);
renderListItems(domCache.list);
}, 150);
}
}
}
}
function getListItemText(li) { return li.dataset.content || ''; }
function renderListItems(list) {
while (list.firstChild) DomUtil.removeElement(list.firstChild);
const fragment = DomUtil.createFragment();
const customItems = StorageUtil.getItem();
customItems.forEach(item => { fragment.appendChild(createItemElement(item)); });
fragment.appendChild(createAddButton());
list.appendChild(fragment);
if (CONSTANTS.AUTO_RESIZE_ON_CONTENT_CHANGE) adjustHeightToContent(list);
}
function createItemElement(text) {
const li = document.createElement('li');
li.dataset.content = text;
if (isImageFormat(text)) {
const imageUrl = extractImageUrl(text);
const completedUrl = DomUtil.completeImageUrl(imageUrl);
const img = document.createElement('img');
img.src = completedUrl;
img.alt = '图片预览';
img.className = 'menu-image-preview';
const indicator = document.createElement('span');
indicator.className = 'image-item-indicator';
indicator.textContent = '图';
li.appendChild(indicator);
img.onerror = function() {
this.alt = '图片加载失败';
this.style.display = 'none';
const errorText = document.createElement('span');
errorText.textContent = '图片';
errorText.style.color = '#666';
li.appendChild(errorText);
};
li.appendChild(img);
} else {
const textSpan = document.createElement('span');
textSpan.className = 'item-text';
textSpan.textContent = text;
li.appendChild(textSpan);
}
const deleteBtn = document.createElement('span');
deleteBtn.className = 'delete-item-btn';
deleteBtn.addEventListener('click', (e) => handleDeleteClick(e, text));
li.appendChild(deleteBtn);
return li;
}
function createAddButton() {
const inputContainer = document.createElement('li');
inputContainer.className = 'custom-item-input-container';
inputContainer.title = "添加新内容";
const plusChar = document.createElement('span');
plusChar.className = 'custom-item-plus-char';
plusChar.textContent = CONSTANTS.INPUT_PLUS_CHAR;
inputContainer.appendChild(plusChar);
return inputContainer;
}
function showAddItemInput(list) {
DomUtil.removeElements('.custom-item-input, .input-overlay');
const overlay = document.createElement('div');
overlay.className = 'input-overlay visible';
const input = document.createElement('textarea');
input.className = 'custom-item-input visible';
input.placeholder = `请输入文本或图片链接`;
domCache.input = input;
domCache.overlay = overlay;
document.body.appendChild(overlay);
document.body.appendChild(input);
input.focus();
const closeInput = (save = false) => {
if (save && input.value.trim()) {
const content = input.value.trim();
const customItems = StorageUtil.getItem();
if (isValidImageUrl(content) && !isImageFormat(content)) {
const formattedContent = ``;
if (!customItems.includes(formattedContent)) {
customItems.push(formattedContent);
StorageUtil.setItem(customItems);
}
} else if (!customItems.includes(content)) {
customItems.push(content);
StorageUtil.setItem(customItems);
}
renderListItems(list);
}
domCache.input = null;
domCache.overlay = null;
DomUtil.removeElement(input);
DomUtil.removeElement(overlay);
};
input.addEventListener('keydown', function(e) {
if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); closeInput(true); }
else if (e.key === 'Escape') closeInput(false);
});
overlay.addEventListener('click', () => closeInput(false));
input.addEventListener('blur', () => closeInput(true));
}
function showList(inputElement) {
const list = domCache.list || createList();
list.classList.remove('visible');
domCache.activeInput = inputElement;
document.querySelectorAll('.custom-right-click-active').forEach(el => el.classList.remove('custom-right-click-active'));
if (inputElement) inputElement.classList.add('custom-right-click-active');
let newX, newY;
if (inputElement) {
const rect = inputElement.getBoundingClientRect();
newX = rect.left + window.scrollX;
newY = rect.bottom + window.scrollY + 5;
} else {
newX = window.innerWidth / 2 - MIN_WIDTH / 2 + window.scrollX;
newY = window.innerHeight / 2 - CONSTANTS.INITIAL_HEIGHT / 2 + window.scrollY;
}
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
const listWidth = list.offsetWidth || MIN_WIDTH;
const listHeight = list.offsetHeight || CONSTANTS.INITIAL_HEIGHT;
if (newX + listWidth > viewportWidth + window.scrollX) newX = Math.max(0, viewportWidth + window.scrollX - listWidth - 10);
if (newY + listHeight > viewportHeight + window.scrollY) newY = Math.max(0, (inputElement ? inputElement.getBoundingClientRect().top : newY) + window.scrollY - listHeight - 5);
list.style.left = `${newX}px`;
list.style.top = `${newY}px`;
void list.offsetWidth;
requestAnimationFrame(() => list.classList.add('visible'));
}
function hideList() {
if (domCache.list) domCache.list.classList.remove('visible');
if (domCache.activeInput) {
domCache.activeInput.classList.remove('custom-right-click-active');
domCache.activeInput = null;
}
}
function isImageFormat(content) { return /^!\s*\[\s*(.*?)\s*\]\s*\(\s*(.*?)\s*\)\s*$/.test(content.trim()); }
function extractImageUrl(content) { const match = content.trim().match(/^!\s*\[\s*(.*?)\s*\]\s*\(\s*(.*?)\s*\)\s*$/); return match ? match[2] : null; }
function isValidImageUrl(url) { const trimmedUrl = url.trim(); return /^https?:\/\/.+\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(trimmedUrl); }
function calculateContentHeight(list) {
let totalHeight = 0;
let child = list.firstChild;
while (child) { if (child.nodeType === 1) totalHeight += child.offsetHeight + 8; child = child.nextSibling; }
return totalHeight + 20;
}
function adjustHeightToContent(list) {
const contentHeight = calculateContentHeight(list);
const newHeight = Math.max(CONSTANTS.MIN_HEIGHT, Math.min(contentHeight + CONSTANTS.CONTENT_EXTRA_SPACE, contentHeight + CONSTANTS.MAX_EXTRA_SPACE));
list.style.height = `${newHeight}px`;
}
function isInputElement(element) {
const tagName = element.tagName.toLowerCase();
return (tagName === 'input' && !['checkbox', 'radio', 'file', 'submit', 'reset', 'button'].includes(element.type)) || tagName === 'textarea' || element.isContentEditable;
}
function initEventListeners() {
document.addEventListener('contextmenu', function(e) {
if (isInputElement(e.target)) {
e.preventDefault();
const list = domCache.list;
if (list && list.classList.contains('visible')) hideList();
else showList(e.target);
} else hideList();
});
document.addEventListener('click', function(e) {
if (!e.target.closest('.custom-right-click-list') && !e.target.closest('.custom-item-input') && !e.target.closest('.input-overlay') && !isInputElement(e.target)) {
hideList();
}
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
if (domCache.input && domCache.overlay) {
DomUtil.removeElement(domCache.input);
DomUtil.removeElement(domCache.overlay);
domCache.input = null;
domCache.overlay = null;
} else hideList();
}
});
const handleScroll = DomUtil.debounce(function() {
if (domCache.list && domCache.list.classList.contains('visible') && domCache.activeInput) {
const rect = domCache.activeInput.getBoundingClientRect();
domCache.list.style.left = `${rect.left + window.scrollX}px`;
domCache.list.style.top = `${rect.bottom + window.scrollY + 5}px`;
}
}, 50);
window.addEventListener('scroll', handleScroll);
window.addEventListener('unload', function() {
window.removeEventListener('scroll', handleScroll);
if (domCache.list) domCache.list.removeEventListener('click', handleListClick);
});
}
initEventListeners();
})();
- 点击左上角的 文件 → 保存(或按
Ctrl+S),即可生效。
故障排除
若脚本安装后无法使用,请检查是否开启了 开发人员模式 。
三、使用方法
基础使用
- 点击任意输入框进入输入状态后按下右键,即可呼出菜单 。
- 点击菜单内的内容 。
添加新快捷内容
- 右键输入框呼出快捷菜单,点击菜单中的 “+”。
- 在弹出的文本框中输入内容:
- 文本:直接输入 。
- 图片:以 Markdown 格式输入(
![]()) 。
配置导入&导出
导出配置
- 点击浏览器右上角 油猴图标 。
- 在弹出菜单中选择 “导出快捷输入数据” 。
- 浏览器将自动下载名为
QuickInput_data.json的文件 。
导入配置
- 点击浏览器右上角 油猴图标,选择 “导入快捷输入数据”;
- 在文件选择窗口中,选择之前导出的
QuickInput_data.json文件; - 导入成功后,脚本会弹出提示(如“导入成功!共导入 114514 条数据”)。
样式调整
按照注释修改对应变量的内容即可 :
GRID_COLUMNS: 3, // 网格列数
FIXED_ITEM_SIZE: 60, // 项目尺寸(px)
MAX_WIDTH: 600, // 最大宽度(px)
MIN_HEIGHT: 120, // 最小高度(px)
INITIAL_HEIGHT: 150, // 初始高度(px)
CONTENT_EXTRA_SPACE: 60, // 内容额外空间(px)
MAX_EXTRA_SPACE: 20, // 最大额外空间(px)
INPUT_LINE_HEIGHT: 1.6, // 输入框行高
OPEN_SCALE: 1, // 打开时缩放比例
ALLOW_HORIZONTAL_RESIZE: false, // 允许水平调整
ALLOW_VERTICAL_RESIZE: true, // 允许垂直调整
AUTO_RESIZE_ON_CONTENT_CHANGE: false, // 内容变化时自动调整
INPUT_PLUS_CHAR: "+", // 添加按钮字符
INPUT_PLUS_SIZE: "24px", // 加号大小
INPUT_PLUS_COLOR: "#666", // 加号颜色
INPUT_BACKGROUND: "#f8f9fa", // 输入框背景色
INPUT_BORDER: "1px dashed #ccc", // 输入框边框
INPUT_BORDER_RADIUS: "4px", // 输入框圆角
INPUT_BOX_SHADOW: "0 2px 5px rgba(0,0,0,0.1)", // 输入框阴影
DELETE_BUTTON_SIZE: 16, // 删除按钮大小(px)
DELETE_BUTTON_X_SIZE: "9px", // 删除按钮X符号大小
DELETE_BUTTON_X_OFFSET: "0px", // X符号偏移
IMAGE_PLACEHOLDER_PREFIX: "![]", // 图片占位符前缀
IMAGE_PLACEHOLDER_SUFFIX: "", // 图片占位符后缀
STORAGE_KEY: "customQuickInputItems", // 存储键名
EXPORT_FILE_NAME: "QuickInput_data.json" // 导出文件名
四、注意事项
只能在支持 Markdown 格式的地方使用 。