""" 前台导航页视图(无需登录)。 URL 路径(挂在根路径下,便于匿名访问): - GET /site 公开导航聚合首页(按分类展示所有启用的导航) - GET /site/category/ 分类详情:展示指定分类下所有启用的导航 - GET /site/api/navs JSON 接口(供前端动态加载) 注意: - 这些视图**不加** @authorize,避免 login_required 强制登录。 - 使用 url_prefix='/site' 避免与后台 / 路由冲突(后台 / 是登录后的工作台)。 """ from collections import OrderedDict from flask import Blueprint, render_template, request, jsonify from applications.models import Nav bp = Blueprint('public_nav', __name__, url_prefix='/site') @bp.get('/') def index(): """ 公开首页:按 category 分组聚合,渲染模板 """ groups = _grouped_navs() total = sum(len(items) for items in groups.values()) return render_template( 'public/index.html', groups=groups, total=total, site_name='BWStudio · 导航', ) @bp.get('/category/') def category_detail(name: str): """ 分类详情页:列出指定分类下所有启用的导航 """ items = ( Nav.query .filter(Nav.category == name, Nav.status == 1) .order_by(Nav.sort.asc(), Nav.id.asc()) .all() ) return render_template( 'public/category.html', category=name, items=items, site_name='BWStudio · 导航', ) @bp.get('/api/navs') def api_navs(): """ JSON 接口:返回按分类聚合的导航数据 可用于首页卡片动态加载、第三方嵌入等 """ return jsonify({ 'success': True, 'msg': '请求成功', 'data': _grouped_navs(), }) def _grouped_navs() -> "OrderedDict[str, list]": """按 category 分组,组内按 sort asc 排序""" items = ( Nav.query .filter(Nav.status == 1) .order_by(Nav.category.asc(), Nav.sort.asc(), Nav.id.asc()) .all() ) groups = OrderedDict() for item in items: groups.setdefault(item.category, []).append(item.to_dict()) return groups