Files
pear-admin-flask/applications/view/public/about.py
T
bwstudio 0ffc103e46 feat(plugins): 4 个业务插件代码 + 前台公开页面改造
plugins/navManager:导航 CRUD + 导航分类 CRUD(独立 blueprint)
plugins/friendManager:友情链接 CRUD
plugins/aboutManager:关于本站 CRUD
plugins/siteStats:访问统计主页 + JSON 接口 + /site/* GET 埋点 + nav 卡片点击埋点

applications/view/public/nav.py:导航聚合页 / 分类详情 / JSON 接口,支持 visit_count 注入
applications/view/public/about.py:关于本站公开页
applications/view/public/friend.py:友情链接公开页

templates/public/base.html:响应式首页(搜索框 / 分类抽屉 / 5 主题切换 / footer 隐私小字)
templates/public/index.html / category.html:卡片右下角访问次数
templates/public/about.html / friend.html:关于 + 友链前台页

docs/plugins-development.md:插件开发完整指南(生命周期 + 4 个示例 + FAQ + framework 迁移)

scripts/:探针与端到端验证脚本(probe_*/verify_*/test_*)
2026-09-06 18:18:06 +08:00

50 lines
1.4 KiB
Python

"""
前台公开"关于本站"页面。
不需要登录,匿名可访问。Markdown 在模板里渲染。
"""
import re
import markdown as _markdown
from flask import Blueprint, render_template
from applications.models import About
bp = Blueprint('public_about', __name__, url_prefix='/site')
def _get_about() -> About:
"""复用 model 的种子逻辑,避免空表时炸"""
a = About.query.get(1)
if a is None:
from applications.extensions import db
a = About(id=1, site_name='旺珂 · 导航')
db.session.add(a)
db.session.commit()
return a
@bp.get('/about')
def about():
a = _get_about()
html = _render_md(a.content_md)
return render_template('public/about.html', about=a, content_html=html)
_URL_RE = re.compile(r'(https?://[^\s)<>"\\]+|[\w.+-]+@[\w-]+\.[\w.-]+)')
def _render_md(text: str) -> str:
"""Markdown → HTML;自动把裸链接/邮箱变可点;同时禁掉 script/iframe。"""
if not text or not text.strip():
return ''
html = _markdown.markdown(
text,
extensions=['fenced_code', 'tables', 'nl2br', 'sane_lists'],
output_format='html5',
)
# 防御:清掉 <script>/<iframe>
html = re.sub(r'<\s*script[^>]*>.*?<\s*/\s*script\s*>', '', html, flags=re.I | re.S)
html = re.sub(r'<\s*iframe[^>]*>.*?<\s*/\s*iframe\s*>', '', html, flags=re.I | re.S)
return html