fix: 修复SEO工具页面模板继承错误,改为独立完整HTML页面
- 将seo_tools.html从继承admin/master.html改为独立完整HTML - 从master.html中移除SEO工具菜单项,避免url_for错误 - 修复本地UndefinedError: 'admin_view' is undefined错误
This commit is contained in:
@@ -79,12 +79,6 @@
|
|||||||
<div class="nav-section">
|
<div class="nav-section">
|
||||||
<div class="nav-section-title">系统</div>
|
<div class="nav-section-title">系统</div>
|
||||||
<ul class="nav-menu">
|
<ul class="nav-menu">
|
||||||
<li class="nav-item">
|
|
||||||
<a href="{{ url_for('seo_tools') }}" class="nav-link">
|
|
||||||
<span class="material-symbols-outlined nav-icon">search</span>
|
|
||||||
<span class="nav-text">SEO工具</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="{{ url_for('batch_import') }}" class="nav-link">
|
<a href="{{ url_for('batch_import') }}" class="nav-link">
|
||||||
<span class="material-symbols-outlined nav-icon">upload_file</span>
|
<span class="material-symbols-outlined nav-icon">upload_file</span>
|
||||||
|
|||||||
@@ -1,17 +1,158 @@
|
|||||||
{% extends 'admin/master.html' %}
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>SEO工具管理 - ZJPB - 自己品吧</title>
|
||||||
|
|
||||||
{% block head_css %}
|
<!-- Google Fonts -->
|
||||||
<!-- Font Awesome for icons -->
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
{% endblock %}
|
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Noto+Sans:wght@400;500;700&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
{% block body %}
|
<!-- Google Material Symbols -->
|
||||||
<div class="container-fluid">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-12">
|
<!-- Font Awesome for icons -->
|
||||||
<h1 class="mb-4">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||||
<i class="fa fa-search"></i> SEO工具管理
|
|
||||||
</h1>
|
<!-- Bootstrap CSS -->
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom Admin Theme -->
|
||||||
|
<link href="{{ url_for('static', filename='css/admin-sidebar.css') }}" rel="stylesheet">
|
||||||
|
<link href="{{ url_for('static', filename='css/admin-actions.css') }}" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body class="admin-sidebar-layout">
|
||||||
|
<!-- 左侧菜单栏 -->
|
||||||
|
<aside class="admin-sidebar">
|
||||||
|
<!-- Logo -->
|
||||||
|
<div class="sidebar-logo">
|
||||||
|
<span class="material-symbols-outlined logo-icon">blur_on</span>
|
||||||
|
<span class="logo-text">ZJPB - 自己品吧</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 主菜单 -->
|
||||||
|
<nav class="sidebar-nav">
|
||||||
|
<div class="nav-section">
|
||||||
|
<div class="nav-section-title">主菜单</div>
|
||||||
|
<ul class="nav-menu">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ url_for('admin.index') }}" class="nav-link">
|
||||||
|
<span class="material-symbols-outlined nav-icon">dashboard</span>
|
||||||
|
<span class="nav-text">控制台</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ url_for('site.index_view') }}" class="nav-link">
|
||||||
|
<span class="material-symbols-outlined nav-icon">public</span>
|
||||||
|
<span class="nav-text">网站管理</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ url_for('tag.index_view') }}" class="nav-link">
|
||||||
|
<span class="material-symbols-outlined nav-icon">label</span>
|
||||||
|
<span class="nav-text">标签管理</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ url_for('news.index_view') }}" class="nav-link">
|
||||||
|
<span class="material-symbols-outlined nav-icon">newspaper</span>
|
||||||
|
<span class="nav-text">新闻管理</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ url_for('admin_users.index_view') }}" class="nav-link">
|
||||||
|
<span class="material-symbols-outlined nav-icon">admin_panel_settings</span>
|
||||||
|
<span class="nav-text">管理员</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 系统菜单 -->
|
||||||
|
<div class="nav-section">
|
||||||
|
<div class="nav-section-title">系统</div>
|
||||||
|
<ul class="nav-menu">
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a href="{{ url_for('seo_tools') }}" class="nav-link">
|
||||||
|
<span class="material-symbols-outlined nav-icon">search</span>
|
||||||
|
<span class="nav-text">SEO工具</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ url_for('batch_import') }}" class="nav-link">
|
||||||
|
<span class="material-symbols-outlined nav-icon">upload_file</span>
|
||||||
|
<span class="nav-text">批量导入</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ url_for('change_password') }}" class="nav-link">
|
||||||
|
<span class="material-symbols-outlined nav-icon">lock_reset</span>
|
||||||
|
<span class="nav-text">修改密码</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ url_for('index') }}" class="nav-link" target="_blank">
|
||||||
|
<span class="material-symbols-outlined nav-icon">open_in_new</span>
|
||||||
|
<span class="nav-text">查看网站</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ url_for('admin_logout') }}" class="nav-link">
|
||||||
|
<span class="material-symbols-outlined nav-icon">logout</span>
|
||||||
|
<span class="nav-text">退出登录</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- 用户信息 -->
|
||||||
|
<div class="sidebar-user">
|
||||||
|
<div class="user-avatar">
|
||||||
|
<span class="material-symbols-outlined">account_circle</span>
|
||||||
|
</div>
|
||||||
|
<div class="user-info">
|
||||||
|
<div class="user-name">{{ current_user.username }}</div>
|
||||||
|
<div class="user-email">{{ current_user.email or 'admin@zjpb.com' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<!-- 右侧主内容区 -->
|
||||||
|
<div class="admin-main">
|
||||||
|
<!-- 顶部导航栏 -->
|
||||||
|
<header class="admin-header">
|
||||||
|
<div class="header-breadcrumb">
|
||||||
|
<a href="{{ url_for('admin.index') }}" class="breadcrumb-link">控制台</a>
|
||||||
|
<span class="breadcrumb-separator">/</span>
|
||||||
|
<span class="breadcrumb-current">SEO工具管理</span>
|
||||||
|
</div>
|
||||||
|
<div class="header-actions">
|
||||||
|
<div class="search-box">
|
||||||
|
<span class="material-symbols-outlined search-icon">search</span>
|
||||||
|
<input type="text" placeholder="全局搜索..." class="search-input">
|
||||||
|
</div>
|
||||||
|
<button class="header-btn">
|
||||||
|
<span class="material-symbols-outlined">notifications</span>
|
||||||
|
</button>
|
||||||
|
<button class="header-btn">
|
||||||
|
<span class="material-symbols-outlined">settings</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- 页面内容 -->
|
||||||
|
<main class="admin-content">
|
||||||
|
<div class="page-header">
|
||||||
|
<div>
|
||||||
|
<h1 class="page-title">
|
||||||
|
<i class="fa fa-search"></i> SEO工具管理
|
||||||
|
</h1>
|
||||||
|
<p class="page-description">管理sitemap、通知搜索引擎更新</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Sitemap状态卡片 -->
|
<!-- Sitemap状态卡片 -->
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
@@ -130,287 +271,304 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
<!-- Bootstrap JS -->
|
||||||
.card {
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-lg {
|
<style>
|
||||||
padding: 12px 24px;
|
.page-title {
|
||||||
font-size: 16px;
|
font-size: 24px;
|
||||||
}
|
font-weight: 600;
|
||||||
|
margin-bottom: 8px;
|
||||||
#resultArea {
|
|
||||||
animation: slideDown 0.3s ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slideDown {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(-10px);
|
|
||||||
}
|
}
|
||||||
to {
|
|
||||||
opacity: 1;
|
.page-description {
|
||||||
transform: translateY(0);
|
color: #666;
|
||||||
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.result-item {
|
.card {
|
||||||
padding: 12px;
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
border-left: 4px solid #ddd;
|
margin-bottom: 20px;
|
||||||
margin-bottom: 10px;
|
border-radius: 8px;
|
||||||
background: #f8f9fa;
|
border: 1px solid #e0e0e0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.result-item.success {
|
.btn-lg {
|
||||||
border-left-color: #28a745;
|
padding: 12px 24px;
|
||||||
background: #d4edda;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.result-item.error {
|
#resultArea {
|
||||||
border-left-color: #dc3545;
|
animation: slideDown 0.3s ease-out;
|
||||||
background: #f8d7da;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.result-item.warning {
|
@keyframes slideDown {
|
||||||
border-left-color: #ffc107;
|
from {
|
||||||
background: #fff3cd;
|
opacity: 0;
|
||||||
}
|
transform: translateY(-10px);
|
||||||
</style>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// 复制到剪贴板
|
|
||||||
function copyToClipboard(text) {
|
|
||||||
navigator.clipboard.writeText(text).then(() => {
|
|
||||||
alert('已复制到剪贴板!');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 禁用按钮
|
|
||||||
function disableButtons() {
|
|
||||||
document.querySelectorAll('#generateSitemapBtn, #notifyEnginesBtn, #doAllBtn').forEach(btn => {
|
|
||||||
btn.disabled = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 启用按钮
|
|
||||||
function enableButtons() {
|
|
||||||
document.querySelectorAll('#generateSitemapBtn, #notifyEnginesBtn, #doAllBtn').forEach(btn => {
|
|
||||||
btn.disabled = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示结果
|
|
||||||
function showResult(html) {
|
|
||||||
const resultArea = document.getElementById('resultArea');
|
|
||||||
const resultContent = document.getElementById('resultContent');
|
|
||||||
resultContent.innerHTML = html;
|
|
||||||
resultArea.style.display = 'block';
|
|
||||||
resultArea.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成静态sitemap
|
|
||||||
document.getElementById('generateSitemapBtn').addEventListener('click', async function() {
|
|
||||||
disableButtons();
|
|
||||||
const originalText = this.innerHTML;
|
|
||||||
this.innerHTML = '<i class="fa fa-spinner fa-spin"></i> 生成中...';
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch('/api/generate-static-sitemap', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
if (data.success) {
|
|
||||||
showResult(`
|
|
||||||
<div class="result-item success">
|
|
||||||
<h5><i class="fa fa-check-circle"></i> 生成成功</h5>
|
|
||||||
<p>${data.message}</p>
|
|
||||||
<table class="table table-sm mt-2">
|
|
||||||
<tr><th>URL数量:</th><td>${data.total_urls}</td></tr>
|
|
||||||
<tr><th>文件路径:</th><td><code>${data.file_path}</code></td></tr>
|
|
||||||
<tr><th>生成时间:</th><td>${data.timestamp}</td></tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
`);
|
|
||||||
// 刷新页面以更新sitemap状态
|
|
||||||
setTimeout(() => location.reload(), 2000);
|
|
||||||
} else {
|
|
||||||
showResult(`
|
|
||||||
<div class="result-item error">
|
|
||||||
<h5><i class="fa fa-times-circle"></i> 生成失败</h5>
|
|
||||||
<p>${data.message}</p>
|
|
||||||
</div>
|
|
||||||
`);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
to {
|
||||||
showResult(`
|
opacity: 1;
|
||||||
<div class="result-item error">
|
transform: translateY(0);
|
||||||
<h5><i class="fa fa-times-circle"></i> 请求失败</h5>
|
|
||||||
<p>网络错误: ${error.message}</p>
|
|
||||||
</div>
|
|
||||||
`);
|
|
||||||
} finally {
|
|
||||||
this.innerHTML = originalText;
|
|
||||||
enableButtons();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 通知搜索引擎
|
|
||||||
document.getElementById('notifyEnginesBtn').addEventListener('click', async function() {
|
|
||||||
disableButtons();
|
|
||||||
const originalText = this.innerHTML;
|
|
||||||
this.innerHTML = '<i class="fa fa-spinner fa-spin"></i> 通知中...';
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch('/api/notify-search-engines', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
if (data.success) {
|
|
||||||
let resultsHtml = `
|
|
||||||
<div class="result-item success">
|
|
||||||
<h5><i class="fa fa-check-circle"></i> ${data.message}</h5>
|
|
||||||
<p>Sitemap URL: <code>${data.sitemap_url}</code></p>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
data.results.forEach(result => {
|
|
||||||
const statusClass = result.status === 'success' ? 'success' : 'error';
|
|
||||||
const icon = result.status === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle';
|
|
||||||
resultsHtml += `
|
|
||||||
<div class="result-item ${statusClass}">
|
|
||||||
<h6><i class="fa ${icon}"></i> ${result.engine}</h6>
|
|
||||||
<p>${result.message}</p>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
});
|
|
||||||
|
|
||||||
showResult(resultsHtml);
|
|
||||||
} else {
|
|
||||||
showResult(`
|
|
||||||
<div class="result-item error">
|
|
||||||
<h5><i class="fa fa-times-circle"></i> 通知失败</h5>
|
|
||||||
<p>${data.message}</p>
|
|
||||||
</div>
|
|
||||||
`);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
showResult(`
|
|
||||||
<div class="result-item error">
|
|
||||||
<h5><i class="fa fa-times-circle"></i> 请求失败</h5>
|
|
||||||
<p>网络错误: ${error.message}</p>
|
|
||||||
</div>
|
|
||||||
`);
|
|
||||||
} finally {
|
|
||||||
this.innerHTML = originalText;
|
|
||||||
enableButtons();
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// 一键生成并通知
|
.result-item {
|
||||||
document.getElementById('doAllBtn').addEventListener('click', async function() {
|
padding: 12px;
|
||||||
disableButtons();
|
border-left: 4px solid #ddd;
|
||||||
const originalText = this.innerHTML;
|
margin-bottom: 10px;
|
||||||
this.innerHTML = '<i class="fa fa-spinner fa-spin"></i> 处理中...';
|
background: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
let allResultsHtml = '';
|
.result-item.success {
|
||||||
|
border-left-color: #28a745;
|
||||||
|
background: #d4edda;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
.result-item.error {
|
||||||
// Step 1: 生成sitemap
|
border-left-color: #dc3545;
|
||||||
const sitemapResponse = await fetch('/api/generate-static-sitemap', {
|
background: #f8d7da;
|
||||||
method: 'POST',
|
}
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
.result-item.warning {
|
||||||
}
|
border-left-color: #ffc107;
|
||||||
|
background: #fff3cd;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 复制到剪贴板
|
||||||
|
function copyToClipboard(text) {
|
||||||
|
navigator.clipboard.writeText(text).then(() => {
|
||||||
|
alert('已复制到剪贴板!');
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const sitemapData = await sitemapResponse.json();
|
// 禁用按钮
|
||||||
|
function disableButtons() {
|
||||||
|
document.querySelectorAll('#generateSitemapBtn, #notifyEnginesBtn, #doAllBtn').forEach(btn => {
|
||||||
|
btn.disabled = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (sitemapData.success) {
|
// 启用按钮
|
||||||
allResultsHtml += `
|
function enableButtons() {
|
||||||
<div class="result-item success">
|
document.querySelectorAll('#generateSitemapBtn, #notifyEnginesBtn, #doAllBtn').forEach(btn => {
|
||||||
<h5><i class="fa fa-check-circle"></i> 步骤1:生成sitemap成功</h5>
|
btn.disabled = false;
|
||||||
<p>${sitemapData.message}</p>
|
});
|
||||||
</div>
|
}
|
||||||
`;
|
|
||||||
|
|
||||||
// Step 2: 通知搜索引擎
|
// 显示结果
|
||||||
const notifyResponse = await fetch('/api/notify-search-engines', {
|
function showResult(html) {
|
||||||
|
const resultArea = document.getElementById('resultArea');
|
||||||
|
const resultContent = document.getElementById('resultContent');
|
||||||
|
resultContent.innerHTML = html;
|
||||||
|
resultArea.style.display = 'block';
|
||||||
|
resultArea.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成静态sitemap
|
||||||
|
document.getElementById('generateSitemapBtn').addEventListener('click', async function() {
|
||||||
|
disableButtons();
|
||||||
|
const originalText = this.innerHTML;
|
||||||
|
this.innerHTML = '<i class="fa fa-spinner fa-spin"></i> 生成中...';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/generate-static-sitemap', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const notifyData = await notifyResponse.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (notifyData.success) {
|
if (data.success) {
|
||||||
allResultsHtml += `
|
showResult(`
|
||||||
<div class="result-item success">
|
<div class="result-item success">
|
||||||
<h5><i class="fa fa-check-circle"></i> 步骤2:${notifyData.message}</h5>
|
<h5><i class="fa fa-check-circle"></i> 生成成功</h5>
|
||||||
|
<p>${data.message}</p>
|
||||||
|
<table class="table table-sm mt-2">
|
||||||
|
<tr><th>URL数量:</th><td>${data.total_urls}</td></tr>
|
||||||
|
<tr><th>文件路径:</th><td><code>${data.file_path}</code></td></tr>
|
||||||
|
<tr><th>生成时间:</th><td>${data.timestamp}</td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
// 刷新页面以更新sitemap状态
|
||||||
|
setTimeout(() => location.reload(), 2000);
|
||||||
|
} else {
|
||||||
|
showResult(`
|
||||||
|
<div class="result-item error">
|
||||||
|
<h5><i class="fa fa-times-circle"></i> 生成失败</h5>
|
||||||
|
<p>${data.message}</p>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
showResult(`
|
||||||
|
<div class="result-item error">
|
||||||
|
<h5><i class="fa fa-times-circle"></i> 请求失败</h5>
|
||||||
|
<p>网络错误: ${error.message}</p>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
} finally {
|
||||||
|
this.innerHTML = originalText;
|
||||||
|
enableButtons();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 通知搜索引擎
|
||||||
|
document.getElementById('notifyEnginesBtn').addEventListener('click', async function() {
|
||||||
|
disableButtons();
|
||||||
|
const originalText = this.innerHTML;
|
||||||
|
this.innerHTML = '<i class="fa fa-spinner fa-spin"></i> 通知中...';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/notify-search-engines', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (data.success) {
|
||||||
|
let resultsHtml = `
|
||||||
|
<div class="result-item success">
|
||||||
|
<h5><i class="fa fa-check-circle"></i> ${data.message}</h5>
|
||||||
|
<p>Sitemap URL: <code>${data.sitemap_url}</code></p>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
notifyData.results.forEach(result => {
|
data.results.forEach(result => {
|
||||||
const statusClass = result.status === 'success' ? 'success' : 'warning';
|
const statusClass = result.status === 'success' ? 'success' : 'error';
|
||||||
const icon = result.status === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle';
|
const icon = result.status === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle';
|
||||||
allResultsHtml += `
|
resultsHtml += `
|
||||||
<div class="result-item ${statusClass}">
|
<div class="result-item ${statusClass}">
|
||||||
<h6><i class="fa ${icon}"></i> ${result.engine}</h6>
|
<h6><i class="fa ${icon}"></i> ${result.engine}</h6>
|
||||||
<p>${result.message}</p>
|
<p>${result.message}</p>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
showResult(resultsHtml);
|
||||||
|
} else {
|
||||||
|
showResult(`
|
||||||
|
<div class="result-item error">
|
||||||
|
<h5><i class="fa fa-times-circle"></i> 通知失败</h5>
|
||||||
|
<p>${data.message}</p>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
showResult(`
|
||||||
|
<div class="result-item error">
|
||||||
|
<h5><i class="fa fa-times-circle"></i> 请求失败</h5>
|
||||||
|
<p>网络错误: ${error.message}</p>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
} finally {
|
||||||
|
this.innerHTML = originalText;
|
||||||
|
enableButtons();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 一键生成并通知
|
||||||
|
document.getElementById('doAllBtn').addEventListener('click', async function() {
|
||||||
|
disableButtons();
|
||||||
|
const originalText = this.innerHTML;
|
||||||
|
this.innerHTML = '<i class="fa fa-spinner fa-spin"></i> 处理中...';
|
||||||
|
|
||||||
|
let allResultsHtml = '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Step 1: 生成sitemap
|
||||||
|
const sitemapResponse = await fetch('/api/generate-static-sitemap', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const sitemapData = await sitemapResponse.json();
|
||||||
|
|
||||||
|
if (sitemapData.success) {
|
||||||
|
allResultsHtml += `
|
||||||
|
<div class="result-item success">
|
||||||
|
<h5><i class="fa fa-check-circle"></i> 步骤1:生成sitemap成功</h5>
|
||||||
|
<p>${sitemapData.message}</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Step 2: 通知搜索引擎
|
||||||
|
const notifyResponse = await fetch('/api/notify-search-engines', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const notifyData = await notifyResponse.json();
|
||||||
|
|
||||||
|
if (notifyData.success) {
|
||||||
|
allResultsHtml += `
|
||||||
|
<div class="result-item success">
|
||||||
|
<h5><i class="fa fa-check-circle"></i> 步骤2:${notifyData.message}</h5>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
notifyData.results.forEach(result => {
|
||||||
|
const statusClass = result.status === 'success' ? 'success' : 'warning';
|
||||||
|
const icon = result.status === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle';
|
||||||
|
allResultsHtml += `
|
||||||
|
<div class="result-item ${statusClass}">
|
||||||
|
<h6><i class="fa ${icon}"></i> ${result.engine}</h6>
|
||||||
|
<p>${result.message}</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
allResultsHtml += `
|
||||||
|
<div class="result-item error">
|
||||||
|
<h5><i class="fa fa-times-circle"></i> 步骤2:通知搜索引擎失败</h5>
|
||||||
|
<p>${notifyData.message}</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
allResultsHtml += `
|
allResultsHtml += `
|
||||||
<div class="result-item error">
|
<div class="result-item error">
|
||||||
<h5><i class="fa fa-times-circle"></i> 步骤2:通知搜索引擎失败</h5>
|
<h5><i class="fa fa-times-circle"></i> 步骤1:生成sitemap失败</h5>
|
||||||
<p>${notifyData.message}</p>
|
<p>${sitemapData.message}</p>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
allResultsHtml += `
|
showResult(allResultsHtml);
|
||||||
|
|
||||||
|
// 如果全部成功,2秒后刷新页面
|
||||||
|
if (sitemapData.success) {
|
||||||
|
setTimeout(() => location.reload(), 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
showResult(`
|
||||||
<div class="result-item error">
|
<div class="result-item error">
|
||||||
<h5><i class="fa fa-times-circle"></i> 步骤1:生成sitemap失败</h5>
|
<h5><i class="fa fa-times-circle"></i> 操作失败</h5>
|
||||||
<p>${sitemapData.message}</p>
|
<p>网络错误: ${error.message}</p>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`);
|
||||||
|
} finally {
|
||||||
|
this.innerHTML = originalText;
|
||||||
|
enableButtons();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
showResult(allResultsHtml);
|
</script>
|
||||||
|
</body>
|
||||||
// 如果全部成功,2秒后刷新页面
|
</html>
|
||||||
if (sitemapData.success) {
|
|
||||||
setTimeout(() => location.reload(), 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
showResult(`
|
|
||||||
<div class="result-item error">
|
|
||||||
<h5><i class="fa fa-times-circle"></i> 操作失败</h5>
|
|
||||||
<p>网络错误: ${error.message}</p>
|
|
||||||
</div>
|
|
||||||
`);
|
|
||||||
} finally {
|
|
||||||
this.innerHTML = originalText;
|
|
||||||
enableButtons();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user