support edit

This commit is contained in:
Julian Freeman
2026-03-11 14:01:47 -04:00
parent 527046339a
commit 22c511daf8
3 changed files with 106 additions and 51 deletions

View File

@@ -11,6 +11,7 @@ const newPresetName = document.getElementById('newPresetName');
const newPresetSheet = document.getElementById('newPresetSheet');
const newPresetFields = document.getElementById('newPresetFields');
const addPresetBtn = document.getElementById('addPreset');
const cancelEditBtn = document.getElementById('cancelEdit');
const presetList = document.getElementById('presetList');
const presetSelect = document.getElementById('presetSelect');
const runPresetBtn = document.getElementById('runPreset');
@@ -26,6 +27,7 @@ const DEFAULT_PRESETS = [
];
let currentPresets = [];
let editingPresetId = null;
toggleConfig.addEventListener('click', () => {
const isHidden = configContent.classList.toggle('hidden');
@@ -49,7 +51,7 @@ chrome.storage.local.get(['geminiApiKey', 'googleScriptUrl', 'geminiModel', 'use
renderPresets(currentPresets);
});
// Save settings
// Save global settings
saveConfigBtn.addEventListener('click', () => {
const apiKey = apiKeyInput.value.trim();
const scriptUrl = scriptUrlInput.value.trim();
@@ -72,25 +74,66 @@ addPresetBtn.addEventListener('click', async () => {
if (!name || !rawFields) return alert('请输入名称和字段');
// 核心逻辑:支持中英文逗号,并清理多余空格
const normalizedFields = rawFields
.split(/[,]/) // 使用正则匹配中英文逗号
.map(f => f.trim()) // 清理每一项前后的空格
.filter(f => f !== "") // 过滤掉空项
.join(', '); // 统一用英文逗号+空格连接
.split(/[,]/)
.map(f => f.trim())
.filter(f => f !== "")
.join(', ');
const { userPresets = DEFAULT_PRESETS } = await chrome.storage.local.get('userPresets');
const newPreset = { id: Date.now().toString(), name, sheetName, fields: normalizedFields };
currentPresets = [...userPresets, newPreset];
if (editingPresetId) {
// Update existing
currentPresets = userPresets.map(p =>
p.id === editingPresetId ? { ...p, name, sheetName, fields: normalizedFields } : p
);
stopEditing();
} else {
// Add new
const newPreset = { id: Date.now().toString(), name, sheetName, fields: normalizedFields };
currentPresets = [...userPresets, newPreset];
}
await chrome.storage.local.set({ userPresets: currentPresets });
newPresetName.value = '';
newPresetSheet.value = '';
newPresetFields.value = '';
clearPresetInputs();
renderPresets(currentPresets);
});
cancelEditBtn.addEventListener('click', stopEditing);
function startEditing(preset) {
editingPresetId = preset.id;
newPresetName.value = preset.name;
newPresetSheet.value = preset.sheetName || '';
newPresetFields.value = preset.fields;
addPresetBtn.textContent = '更新预设';
addPresetBtn.classList.replace('bg-indigo-50', 'bg-indigo-600');
addPresetBtn.classList.replace('text-indigo-700', 'text-white');
cancelEditBtn.classList.remove('hidden');
// Ensure config is expanded so user can see inputs
configContent.classList.remove('hidden');
configChevron.classList.add('rotate-180');
}
function stopEditing() {
editingPresetId = null;
clearPresetInputs();
addPresetBtn.textContent = '添加新预设';
addPresetBtn.classList.replace('bg-indigo-600', 'bg-indigo-50');
addPresetBtn.classList.replace('text-white', 'text-indigo-700');
cancelEditBtn.classList.add('hidden');
}
function clearPresetInputs() {
newPresetName.value = '';
newPresetSheet.value = '';
newPresetFields.value = '';
}
async function deletePreset(id) {
if (editingPresetId === id) stopEditing();
const { userPresets = DEFAULT_PRESETS } = await chrome.storage.local.get('userPresets');
currentPresets = userPresets.filter(p => p.id !== id);
await chrome.storage.local.set({ userPresets: currentPresets });
@@ -98,33 +141,32 @@ async function deletePreset(id) {
}
function renderPresets(presets) {
// Clear containers
presetList.innerHTML = '';
presetSelect.innerHTML = '';
presets.forEach(preset => {
// 1. Render in Settings List
// 1. Settings List Item
const item = document.createElement('div');
item.className = 'flex items-center justify-between bg-white p-3 mb-2 rounded-lg border border-gray-200 shadow-sm transition-all hover:border-indigo-200';
item.innerHTML = `
<div class="flex-1 overflow-hidden mr-3">
<div class="flex-1 overflow-hidden mr-2">
<div class="text-xs font-bold text-gray-800 truncate">${preset.name} ${preset.sheetName ? `<span class="text-indigo-500 ml-1">#${preset.sheetName}</span>` : ''}</div>
<div class="text-[11px] text-gray-400 truncate mt-1 leading-tight">${preset.fields}</div>
</div>
<button class="flex items-center justify-center w-7 h-7 rounded-full text-gray-300 hover:text-red-500 hover:bg-red-50 transition-all focus:outline-none border-none bg-transparent cursor-pointer" title="删除预设">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
<div class="flex gap-1">
<button class="edit-btn flex items-center justify-center w-7 h-7 rounded-full text-gray-300 hover:text-indigo-600 hover:bg-indigo-50 transition-all cursor-pointer border-none bg-transparent" title="编辑预设">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>
</button>
<button class="delete-btn flex items-center justify-center w-7 h-7 rounded-full text-gray-300 hover:text-red-500 hover:bg-red-50 transition-all cursor-pointer border-none bg-transparent" title="删除预设">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
</button>
</div>
`;
item.querySelector('button').onclick = (e) => {
e.stopPropagation();
deletePreset(preset.id);
};
item.querySelector('.edit-btn').onclick = () => startEditing(preset);
item.querySelector('.delete-btn').onclick = () => deletePreset(preset.id);
presetList.appendChild(item);
// 2. Render as Dropdown Option
// 2. Dropdown Option
const opt = document.createElement('option');
opt.value = preset.id;
opt.textContent = preset.name;
@@ -132,7 +174,7 @@ function renderPresets(presets) {
});
}
// Action Handlers
// Extraction Handler
runPresetBtn.addEventListener('click', () => {
const selectedId = presetSelect.value;
const preset = currentPresets.find(p => p.id === selectedId);
@@ -149,7 +191,7 @@ async function handleExtraction(type, presetObj) {
const selectedModel = geminiModel || 'gemini-1.5-flash';
updateStatus('提取中...', 'bg-blue-500 text-white');
resultsArea.textContent = `正在使用 ${selectedModel} 提取 ${presetObj.name || '自定义项'}...`;
resultsArea.textContent = `正在使用 ${selectedModel} 提取 ${presetObj.name}...`;
try {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });