var wbBackend = false; var wbItems = []; var wbEditId = null; var LOCAL_WB_KEY = 'spanish_diary_wordbook'; function wbEsc(s) { var div = document.createElement('div'); div.textContent = s == null ? '' : String(s); return div.innerHTML; } function wbMsg(text) { document.getElementById('wb-msg').textContent = text || ''; } function loadLocalWords() { try { wbItems = JSON.parse(localStorage.getItem(LOCAL_WB_KEY) || '[]'); } catch (e) { wbItems = []; } renderWordbook(); } function saveLocalWords() { localStorage.setItem(LOCAL_WB_KEY, JSON.stringify(wbItems)); } function loadWords() { if (wbBackend) { apiGetVocabulary().then(function(items) { wbItems = items || []; renderWordbook(); }).catch(function(err) { wbMsg(err.message || '加载单词本失败'); }); } else { loadLocalWords(); } } function getFilteredWords() { var keyword = document.getElementById('search-word').value.trim().toLowerCase(); var category = document.getElementById('filter-category').value; var sort = document.getElementById('sort-word').value; var filtered = wbItems.filter(function(item) { var matchKeyword = !keyword || String(item.word || '').toLowerCase().indexOf(keyword) >= 0 || String(item.english || '').toLowerCase().indexOf(keyword) >= 0 || String(item.chinese || '').toLowerCase().indexOf(keyword) >= 0; var matchCategory = !category || String(item.category || '') === category; return matchKeyword && matchCategory; }); filtered.sort(function(a, b) { if (sort === 'word') return String(a.word || '').localeCompare(String(b.word || ''), 'es'); if (sort === 'category') { var c = String(a.category || '').localeCompare(String(b.category || ''), 'zh-CN'); if (c !== 0) return c; return String(a.word || '').localeCompare(String(b.word || ''), 'es'); } return String(b.created_at || '').localeCompare(String(a.created_at || '')); }); return filtered; } function renderWordbook() { var categories = {}; wbItems.forEach(function(item) { var cat = String(item.category || '其他').trim() || '其他'; categories[cat] = (categories[cat] || 0) + 1; }); var filter = document.getElementById('filter-category'); var current = filter.value; var categoryKeys = Object.keys(categories).sort(function(a, b) { return a.localeCompare(b, 'zh-CN'); }); filter.innerHTML = '' + categoryKeys.map(function(cat) { return ''; }).join(''); document.getElementById('wb-total').textContent = '共 ' + wbItems.length + ' 个单词'; document.getElementById('wb-category-count').textContent = categoryKeys.length + ' 个分类'; var filtered = getFilteredWords(); var container = document.getElementById('wb-list'); if (filtered.length === 0) { container.innerHTML = '
还没有收藏单词,或没有匹配结果
'; return; } container.innerHTML = filtered.map(function(item) { var cat = String(item.category || '其他').trim() || '其他'; return '
' + '
' + '' + wbEsc(item.word) + '' + '' + wbEsc(cat) + '' + '
' + '
' + '
ES' + wbEsc(item.word) + '
' + '
EN' + wbEsc(item.english || '-') + '
' + '
CN' + wbEsc(item.chinese || '-') + '
' + '
' + '
' + '' + '' + '
' + '
'; }).join(''); } function addWord() { var data = { word: document.getElementById('add-word').value.trim(), english: document.getElementById('add-english').value.trim(), chinese: document.getElementById('add-chinese').value.trim(), category: document.getElementById('add-category').value.trim() }; if (!data.word) { wbMsg('请输入西语单词'); return; } var finish = function() { document.getElementById('add-word').value = ''; document.getElementById('add-english').value = ''; document.getElementById('add-chinese').value = ''; document.getElementById('add-category').value = ''; loadWords(); }; if (wbBackend) { apiAddVocabulary(data).then(finish).catch(function(err) { wbMsg(err.message || '添加失败'); }); } else { data.id = 'local-' + Date.now(); data.created_at = new Date().toISOString(); wbItems.unshift(data); saveLocalWords(); finish(); } } function openEdit(id) { var item = wbItems.find(function(w) { return String(w.id) === String(id); }); if (!item) return; wbEditId = id; document.getElementById('edit-word').value = item.word || ''; document.getElementById('edit-english').value = item.english || ''; document.getElementById('edit-chinese').value = item.chinese || ''; document.getElementById('edit-category').value = item.category || ''; document.getElementById('edit-overlay').classList.add('show'); } function closeEdit() { wbEditId = null; document.getElementById('edit-overlay').classList.remove('show'); } function saveEdit() { if (!wbEditId) return; var data = { word: document.getElementById('edit-word').value.trim(), english: document.getElementById('edit-english').value.trim(), chinese: document.getElementById('edit-chinese').value.trim(), category: document.getElementById('edit-category').value.trim() }; if (!data.word) { wbMsg('请输入西语单词'); return; } var finish = function() { closeEdit(); loadWords(); }; if (wbBackend) { apiUpdateVocabulary(wbEditId, data).then(finish).catch(function(err) { wbMsg(err.message || '保存失败'); }); } else { var idx = wbItems.findIndex(function(w) { return String(w.id) === String(wbEditId); }); if (idx >= 0) { Object.assign(wbItems[idx], data); saveLocalWords(); } finish(); } } function deleteWord(id) { if (!confirm('确定从单词本中删除该单词吗?')) return; var finish = function() { loadWords(); }; if (wbBackend) { apiDeleteVocabulary(id).then(finish).catch(function(err) { wbMsg(err.message || '删除失败'); }); } else { wbItems = wbItems.filter(function(w) { return String(w.id) !== String(id); }); saveLocalWords(); finish(); } } document.getElementById('btn-add-word').addEventListener('click', addWord); document.getElementById('search-word').addEventListener('input', renderWordbook); document.getElementById('filter-category').addEventListener('change', renderWordbook); document.getElementById('sort-word').addEventListener('change', renderWordbook); document.getElementById('edit-cancel').addEventListener('click', closeEdit); document.getElementById('edit-save').addEventListener('click', saveEdit); document.getElementById('wb-list').addEventListener('click', function(e) { var card = e.target.closest('.word-card'); if (!card) return; var id = card.dataset.id; if (e.target.closest('.speak-word')) { var item = wbItems.find(function(w) { return String(w.id) === String(id); }); if (!item) return; var lang = e.target.closest('.speak-word').dataset.lang; if (lang === 'es') speakText(item.word, 'es'); else if (lang === 'en') speakText(item.english, 'en'); else speakText(item.chinese, 'zh'); return; } if (e.target.closest('.edit-word')) { openEdit(id); return; } if (e.target.closest('.delete-word')) { deleteWord(id); } }); apiGetMe().then(function() { wbBackend = true; loadWords(); }).catch(function(err) { if (err && err.status === 401) { location.href = 'login.html'; return; } wbBackend = false; loadWords(); });