feat: v2.4.0 - SEO全面优化
新增功能: 1. 自动化SEO基础设施 - Sitemap.xml 动态生成 (/sitemap.xml) - Robots.txt 动态配置 (/robots.txt) 2. Schema.org 结构化数据 - 工具详情页添加 SoftwareApplication 结构化数据 - 面包屑导航添加 BreadcrumbList 结构化数据 - Open Graph 标签支持社交媒体分享 3. 智能内链系统 - 自动识别工具名称并添加内部链接 - auto_link 过滤器支持内容互联 4. 标签专题页SEO优化 - Tag模型新增字段: seo_title, seo_description, seo_keywords - 支持自定义标签页SEO信息 - 提供迁移脚本: migrate_tag_seo_fields.py 5. 面包屑导航 - 可视化导航: 首页 > 标签 > 工具名 - 支持Schema.org和视觉显示 6. 页面级SEO改进 - 工具详情页: canonical链接, 动态meta标签 - 标签页: 专属SEO信息支持 - 首页: 完整meta标签配置 技术改进: - 迁移脚本支持幂等性检查 - Windows控制台编码兼容性优化 - 数据库字段注释标注版本 部署文档: DEPLOY_v2.4.0.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
102
app.py
102
app.py
@@ -29,6 +29,33 @@ def create_app(config_name='default'):
|
||||
return ''
|
||||
return markdown.markdown(text, extensions=['nl2br', 'fenced_code'])
|
||||
|
||||
# v2.4新增: 自动内链过滤器
|
||||
@app.template_filter('auto_link')
|
||||
def auto_link_filter(text, current_site_id=None):
|
||||
"""自动为内容中的工具名称添加链接"""
|
||||
if not text:
|
||||
return ''
|
||||
|
||||
# 获取所有启用的网站(排除当前网站)
|
||||
sites = Site.query.filter_by(is_active=True).all()
|
||||
if current_site_id:
|
||||
sites = [s for s in sites if s.id != current_site_id]
|
||||
|
||||
# 按名称长度降序排序,优先匹配长名称
|
||||
sites = sorted(sites, key=lambda s: len(s.name), reverse=True)
|
||||
|
||||
# 记录已经添加链接的位置,避免重复
|
||||
linked_sites = set()
|
||||
|
||||
for site in sites:
|
||||
if site.name in text and site.name not in linked_sites:
|
||||
# 只链接第一次出现的位置
|
||||
link = f'<a href="/site/{site.code}" title="{site.short_desc or site.name}" style="color: var(--primary-blue); text-decoration: underline; text-decoration-style: dotted;">{site.name}</a>'
|
||||
text = text.replace(site.name, link, 1)
|
||||
linked_sites.add(site.name)
|
||||
|
||||
return text
|
||||
|
||||
# 初始化登录管理
|
||||
login_manager = LoginManager()
|
||||
login_manager.init_app(app)
|
||||
@@ -709,6 +736,76 @@ def create_app(config_name='default'):
|
||||
'message': f'批量获取失败: {str(e)}'
|
||||
}), 500
|
||||
|
||||
# ========== SEO路由 (v2.4新增) ==========
|
||||
@app.route('/sitemap.xml')
|
||||
def sitemap():
|
||||
"""动态生成sitemap.xml"""
|
||||
from flask import make_response
|
||||
|
||||
# 获取所有启用的网站
|
||||
sites = Site.query.filter_by(is_active=True).order_by(Site.updated_at.desc()).all()
|
||||
|
||||
# 获取所有标签
|
||||
tags = Tag.query.all()
|
||||
|
||||
# 构建XML内容
|
||||
xml_content = '''<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'''
|
||||
|
||||
# 首页
|
||||
xml_content += '''
|
||||
<url>
|
||||
<loc>{}</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>'''.format(request.url_root.rstrip('/'))
|
||||
|
||||
# 工具详情页
|
||||
for site in sites:
|
||||
xml_content += '''
|
||||
<url>
|
||||
<loc>{}</loc>
|
||||
<lastmod>{}</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>'''.format(
|
||||
request.url_root.rstrip('/') + url_for('site_detail', code=site.code),
|
||||
site.updated_at.strftime('%Y-%m-%d') if site.updated_at else datetime.now().strftime('%Y-%m-%d')
|
||||
)
|
||||
|
||||
# 标签页
|
||||
for tag in tags:
|
||||
xml_content += '''
|
||||
<url>
|
||||
<loc>{}</loc>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.6</priority>
|
||||
</url>'''.format(request.url_root.rstrip('/') + '/?tag=' + tag.slug)
|
||||
|
||||
xml_content += '''
|
||||
</urlset>'''
|
||||
|
||||
response = make_response(xml_content)
|
||||
response.headers['Content-Type'] = 'application/xml; charset=utf-8'
|
||||
return response
|
||||
|
||||
@app.route('/robots.txt')
|
||||
def robots():
|
||||
"""动态生成robots.txt"""
|
||||
from flask import make_response
|
||||
|
||||
robots_content = '''User-agent: *
|
||||
Allow: /
|
||||
Disallow: /admin/
|
||||
Disallow: /api/
|
||||
|
||||
Sitemap: {}sitemap.xml
|
||||
'''.format(request.url_root)
|
||||
|
||||
response = make_response(robots_content)
|
||||
response.headers['Content-Type'] = 'text/plain; charset=utf-8'
|
||||
return response
|
||||
|
||||
@app.route('/api/refresh-site-news/<site_code>', methods=['POST'])
|
||||
def refresh_site_news(site_code):
|
||||
"""手动刷新指定网站的新闻(前台用户可访问)- v2.3新增"""
|
||||
@@ -1211,11 +1308,14 @@ def create_app(config_name='default'):
|
||||
'name': '标签名称',
|
||||
'slug': 'URL别名',
|
||||
'description': '标签描述',
|
||||
'seo_title': 'SEO标题 (v2.4)',
|
||||
'seo_description': 'SEO描述 (v2.4)',
|
||||
'seo_keywords': 'SEO关键词 (v2.4)',
|
||||
'icon': '图标',
|
||||
'sort_order': '排序权重',
|
||||
'created_at': '创建时间'
|
||||
}
|
||||
form_columns = ['name', 'slug', 'description', 'icon', 'sort_order']
|
||||
form_columns = ['name', 'slug', 'description', 'seo_title', 'seo_description', 'seo_keywords', 'icon', 'sort_order']
|
||||
|
||||
# 管理员视图
|
||||
class AdminAdmin(SecureModelView):
|
||||
|
||||
Reference in New Issue
Block a user