Files
wordpress-theme-aksrt/assets/js/admin-ai-seo.js
T
kate522 b36186da65 feat(ai): 打通 SEO 闭环与投稿写作辅助
对齐 Zibll 的 AI 生成 SEO 流程:统一 WP AI Client/主题 Provider 双后端、文章/分类 SEO 框与生成回填、投稿摘要/标签建议,并收敛扩展页为连接配置。
2026-07-12 15:36:04 +08:00

131 lines
4.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* AKSRT Admin AI SEO — generate button for post/term SEO fields
*/
(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') || $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;
}
document.addEventListener('click', function (e) {
var btn = e.target.closest('.aksrt-ai-seo-generate');
if (!btn) return;
e.preventDefault();
if (btn.classList.contains('is-loading') || btn.disabled) return;
var type = btn.getAttribute('data-type') || 'post';
var id = parseInt(btn.getAttribute('data-id') || '0', 10);
if (!id) {
notify(btn, I18N.needSave || '请先保存后再生成 SEO', 'error');
return;
}
if (CFG.ai && CFG.ai.available === false) {
notify(btn, I18N.notAvailable || 'AI 未配置或未启用', 'error');
return;
}
var original = btn.textContent;
btn.classList.add('is-loading');
btn.textContent = I18N.generating || '生成中…';
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) {
btn.classList.remove('is-loading');
btn.textContent = original;
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(btn, msg, 'error');
return;
}
var data = res.json.data || {};
if (type === 'term') fillTerm(data);
else fillPost(data);
var errors = collectErrors(data);
if (errors.length) {
notify(btn, errors.join(';'), 'error');
} else {
notify(btn, I18N.success || '已填入 SEO 字段,请检查后更新保存', 'ok');
}
})
.catch(function () {
btn.classList.remove('is-loading');
btn.textContent = original;
notify(btn, I18N.failed || '生成失败', 'error');
});
});
})();