/** * AKSRT Admin AI SEO — SEO generate + summary → excerpt */ (function () { 'use strict'; if (!window.aksrtAiSeo) return; var CFG = window.aksrtAiSeo; var REST = (CFG.restUrl || '/wp-json/aksrt/v1').replace(/\/$/, ''); var NONCE = CFG.nonce || ''; var I18N = CFG.i18n || {}; function notify($btn, msg, type) { var wrap = $btn.closest('.aksrt-seo-meta-box, td, .form-field, p, .aksrt-ai-summary-row') || $btn.parentNode; if (!wrap) return; var old = wrap.querySelector('.aksrt-ai-seo-msg'); if (old) old.remove(); var el = document.createElement('span'); el.className = 'aksrt-ai-seo-msg ' + (type === 'error' ? 'is-error' : 'is-ok'); el.textContent = msg; wrap.appendChild(el); setTimeout(function () { if (el.parentNode) el.parentNode.removeChild(el); }, 8000); } function fillPost(data) { var map = { title: 'aksrt_seo_title', keywords: 'aksrt_seo_keywords', description: 'aksrt_seo_description', }; Object.keys(map).forEach(function (key) { var field = data[key] || {}; if (!field.content) return; var input = document.getElementById(map[key]) || document.querySelector('[name="' + map[key] + '"]'); if (input) input.value = field.content; }); } function fillTerm(data) { var map = { title: '.aksrt-term-seo-title, #aksrt_seo_title', keywords: '.aksrt-term-seo-keywords, #aksrt_seo_keywords', description: '.aksrt-term-seo-description, #aksrt_seo_description', }; Object.keys(map).forEach(function (key) { var field = data[key] || {}; if (!field.content) return; var input = document.querySelector(map[key]); if (input) input.value = field.content; }); } function collectErrors(data) { var errors = []; ['title', 'keywords', 'description'].forEach(function (key) { if (data[key] && data[key].error) errors.push(data[key].error); }); return errors; } function getEditorTitle() { var titleInput = document.getElementById('title'); if (titleInput && titleInput.value) return titleInput.value.trim(); // Block editor try { if (window.wp && wp.data && wp.data.select) { var ed = wp.data.select('core/editor'); if (ed && ed.getEditedPostAttribute) { return String(ed.getEditedPostAttribute('title') || '').trim(); } } } catch (e) { /* ignore */ } return ''; } function getEditorContent() { var content = ''; var ta = document.getElementById('content'); if (ta && ta.value) content = ta.value; try { if (window.wp && wp.data && wp.data.select) { var ed = wp.data.select('core/editor'); if (ed && ed.getEditedPostContent) { var blockContent = ed.getEditedPostContent(); if (blockContent) content = blockContent; } } } catch (e) { /* ignore */ } // Strip tags for length check / API var div = document.createElement('div'); div.innerHTML = content || ''; return (div.textContent || div.innerText || content || '').trim(); } function setExcerptValue(summary) { if (!summary) return false; // Classic: #excerpt var classic = document.getElementById('excerpt'); if (classic) { classic.value = summary; classic.dispatchEvent(new Event('input', { bubbles: true })); classic.dispatchEvent(new Event('change', { bubbles: true })); return true; } // Block editor excerpt attribute try { if (window.wp && wp.data && wp.data.dispatch) { var d = wp.data.dispatch('core/editor'); if (d && d.editPost) { d.editPost({ excerpt: summary }); return true; } } } catch (e) { /* ignore */ } // Fallback name selector var named = document.querySelector('textarea[name="excerpt"]'); if (named) { named.value = summary; named.dispatchEvent(new Event('input', { bubbles: true })); return true; } return false; } function setLoading(btn, on, original) { if (on) { btn.classList.add('is-loading'); btn.textContent = I18N.generating || '生成中…'; } else { btn.classList.remove('is-loading'); btn.textContent = original; } } document.addEventListener('click', function (e) { // SEO generate var seoBtn = e.target.closest('.aksrt-ai-seo-generate'); if (seoBtn) { e.preventDefault(); if (seoBtn.classList.contains('is-loading') || seoBtn.disabled) return; var type = seoBtn.getAttribute('data-type') || 'post'; var id = parseInt(seoBtn.getAttribute('data-id') || '0', 10); if (!id) { notify(seoBtn, I18N.needSave || '请先保存后再生成 SEO', 'error'); return; } if (CFG.ai && CFG.ai.available === false) { notify(seoBtn, I18N.notAvailable || 'AI 未配置或未启用', 'error'); return; } var seoOriginal = seoBtn.textContent; setLoading(seoBtn, true, seoOriginal); fetch(REST + '/ai/seo-generate', { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': NONCE, }, body: JSON.stringify({ type: type, id: id }), }) .then(function (r) { return r.json().then(function (json) { return { ok: r.ok, json: json }; }); }) .then(function (res) { setLoading(seoBtn, false, seoOriginal); if (!res.ok || !res.json || res.json.success === false) { var msg = (res.json && (res.json.message || (res.json.data && res.json.data.message))) || I18N.failed || '生成失败'; notify(seoBtn, msg, 'error'); return; } var data = res.json.data || {}; if (type === 'term') fillTerm(data); else fillPost(data); var errors = collectErrors(data); if (errors.length) notify(seoBtn, errors.join(';'), 'error'); else notify(seoBtn, I18N.success || '已填入 SEO 字段,请检查后更新保存', 'ok'); }) .catch(function () { setLoading(seoBtn, false, seoOriginal); notify(seoBtn, I18N.failed || '生成失败', 'error'); }); return; } // Summary → excerpt var sumBtn = e.target.closest('.aksrt-ai-summary-generate'); if (!sumBtn) return; e.preventDefault(); if (sumBtn.classList.contains('is-loading') || sumBtn.disabled) return; if (CFG.ai && CFG.ai.available === false) { notify(sumBtn, I18N.notAvailable || 'AI 未配置或未启用', 'error'); return; } var content = getEditorContent(); if (!content) { notify(sumBtn, I18N.needContent || '请先填写正文内容', 'error'); return; } var sumOriginal = sumBtn.textContent; setLoading(sumBtn, true, sumOriginal); fetch(REST + '/ai/summary-suggest', { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': NONCE, }, body: JSON.stringify({ title: getEditorTitle(), content: content, max_length: 200, }), }) .then(function (r) { return r.json().then(function (json) { return { ok: r.ok, json: json }; }); }) .then(function (res) { setLoading(sumBtn, false, sumOriginal); if (!res.ok || !res.json || res.json.success === false) { var msg = (res.json && (res.json.message || (res.json.data && res.json.data.message))) || I18N.failed || '生成失败'; notify(sumBtn, msg, 'error'); return; } var summary = (res.json.data && res.json.data.summary) || ''; if (!setExcerptValue(summary)) { notify(sumBtn, I18N.noExcerptField || '未找到摘要字段,请展开「摘要」面板', 'error'); return; } notify(sumBtn, I18N.summarySuccess || '已填入摘要字段,请检查后更新保存', 'ok'); }) .catch(function () { setLoading(sumBtn, false, sumOriginal); notify(sumBtn, I18N.failed || '生成失败', 'error'); }); }); })();