671 lines
51 KiB
HTML
671 lines
51 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="{{ 'zh-CN' if lang == 'zh' else 'en' }}">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>{{ seo.title if seo else (post.title ~ ' - ' ~ l('论坛', 'Forum')) }}</title>
|
||
<link rel="icon" type="image/svg+xml" href="{{ url_for('static', filename='img/site-logo-mark.svg') }}">
|
||
{% if seo %}
|
||
<meta name="description" content="{{ seo.description }}">
|
||
<meta name="keywords" content="{{ seo.keywords }}">
|
||
<meta name="robots" content="{{ seo.robots }}">
|
||
<meta name="theme-color" content="#0F172A">
|
||
<link rel="canonical" href="{{ seo.canonical_url }}">
|
||
{% if seo.prev_canonical_url %}
|
||
<link rel="prev" href="{{ seo.prev_canonical_url }}">
|
||
{% endif %}
|
||
{% if seo.next_canonical_url %}
|
||
<link rel="next" href="{{ seo.next_canonical_url }}">
|
||
{% endif %}
|
||
{% for hreflang, href in seo.alternate_links.items() %}
|
||
<link rel="alternate" hreflang="{{ hreflang }}" href="{{ href }}">
|
||
{% endfor %}
|
||
{% if seo.feed_url %}
|
||
<link rel="alternate" type="application/rss+xml" title="{{ l('论坛 RSS 订阅', 'Forum RSS Feed') }}" href="{{ seo.feed_url }}">
|
||
{% endif %}
|
||
<meta property="og:type" content="{{ seo.og_type }}">
|
||
<meta property="og:url" content="{{ seo.og_url }}">
|
||
<meta property="og:title" content="{{ seo.og_title }}">
|
||
<meta property="og:description" content="{{ seo.og_description }}">
|
||
<meta property="og:image" content="{{ seo.og_image }}">
|
||
<meta property="article:published_time" content="{{ seo.article_published_time }}">
|
||
<meta property="article:modified_time" content="{{ seo.article_modified_time }}">
|
||
<meta property="article:section" content="{{ seo.article_section }}">
|
||
<meta name="twitter:card" content="{{ seo.twitter_card }}">
|
||
<meta name="twitter:title" content="{{ seo.twitter_title }}">
|
||
<meta name="twitter:description" content="{{ seo.twitter_description }}">
|
||
<meta name="twitter:image" content="{{ seo.og_image }}">
|
||
{% if seo_schema %}
|
||
<script type="application/ld+json">{{ seo_schema | tojson }}</script>
|
||
{% endif %}
|
||
{% endif %}
|
||
<link rel="stylesheet" href="/static/css/style.css">
|
||
<link rel="stylesheet" href="/static/css/forum.css">
|
||
</head>
|
||
<body class="forum-page" data-post-id="{{ post.id }}" data-cta-variant="{{ cta_variant or 'control' }}">
|
||
{% set sb = sidebar if sidebar is defined else {'total_users': 0, 'total_posts': 0, 'total_comments': 0, 'category_counts': []} %}
|
||
{% set related = related_cards if related_cards is defined else [] %}
|
||
{% set plan_recos = plan_recommendations if plan_recommendations is defined else [] %}
|
||
{% set resource_links = detail_resource_links if detail_resource_links is defined else [] %}
|
||
{% set post_faq = detail_faq_items if detail_faq_items is defined else [] %}
|
||
{% set pricing_prefill_obj = pricing_prefill if pricing_prefill is defined and pricing_prefill else {} %}
|
||
{% set pricing_target_url = pricing_prefill_obj.url if pricing_prefill_obj and pricing_prefill_obj.url else (url_for('index', lang='en') if lang == 'en' else url_for('index')) %}
|
||
{% set cta_primary_label = cta_copy.primary_button if cta_copy and cta_copy.primary_button else l('去比价页筛选方案', 'Compare Plans') %}
|
||
{% set cta_secondary_member_label = cta_copy.secondary_button_member if cta_copy and cta_copy.secondary_button_member else l('发布需求主题', 'Post Requirement Topic') %}
|
||
{% set cta_secondary_guest_label = cta_copy.secondary_button_guest if cta_copy and cta_copy.secondary_button_guest else l('登录后发布需求', 'Login to Post Requirement') %}
|
||
<header class="forum-header">
|
||
<div class="forum-header-inner">
|
||
<div class="forum-header-left">
|
||
<a href="{{ url_for('forum_index') }}" class="forum-logo">
|
||
<img src="{{ url_for('static', filename='img/site-logo-mark.svg') }}" alt="{{ l('云价眼 Logo', 'VPS Price Logo') }}">
|
||
<span>{{ l('云价眼论坛', 'VPS Price Forum') }}</span>
|
||
</a>
|
||
<nav class="forum-primary-nav">
|
||
<a href="{{ url_for('forum_index') }}" class="active">{{ l('最新', 'Latest') }}</a>
|
||
<a href="{{ url_for('index') }}">{{ l('价格表', 'Pricing') }}</a>
|
||
{% if current_user and not current_user.is_banned %}
|
||
<a href="{{ url_for('forum_post_new') }}">{{ l('发布主题', 'New Topic') }}</a>
|
||
{% endif %}
|
||
</nav>
|
||
</div>
|
||
<div class="forum-header-right">
|
||
<span class="lang-switch">
|
||
<a href="{{ lang_url('zh') }}" class="{{ 'active' if lang == 'zh' else '' }}" title="切换到中文">中文</a>
|
||
<span class="lang-sep">|</span>
|
||
<a href="{{ lang_url('en') }}" class="{{ 'active' if lang == 'en' else '' }}" title="Switch to English">English</a>
|
||
</span>
|
||
{% if current_user %}
|
||
<span class="forum-user-chip">{{ current_user.username }}{% if current_user.is_banned %}{{ l('(封禁)', ' (Banned)') }}{% endif %}</span>
|
||
<a href="{{ url_for('user_profile') }}" class="forum-link">{{ l('个人中心', 'Profile') }}</a>
|
||
<a href="{{ url_for('user_notifications') }}" class="forum-link nav-link-with-badge">{{ l('通知', 'Notifications') }}{% if notifications_unread_count %}<span class="nav-badge">{{ notifications_unread_count }}</span>{% endif %}</a>
|
||
<a href="{{ url_for('user_logout') }}" class="forum-link">{{ l('退出', 'Logout') }}</a>
|
||
{% else %}
|
||
<a href="{{ url_for('user_login', next=request.path) }}" class="forum-link">{{ l('登录', 'Login') }}</a>
|
||
<a href="{{ url_for('user_register', next=request.path) }}" class="forum-link">{{ l('注册', 'Register') }}</a>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="forum-shell">
|
||
<div class="post-read-progress" aria-hidden="true">
|
||
<span class="post-read-progress-bar" id="post-read-progress-bar"></span>
|
||
</div>
|
||
<nav class="forum-breadcrumb" aria-label="{{ l('面包屑导航', 'Breadcrumb') }}">
|
||
<a href="{{ url_for('index') }}">{{ l('首页', 'Home') }}</a>
|
||
<span>/</span>
|
||
<a href="{{ url_for('forum_index') }}">{{ l('论坛', 'Forum') }}</a>
|
||
{% if post.category %}
|
||
<span>/</span>
|
||
<a href="{{ url_for('forum_index', category=post.category) }}">{{ post.category }}</a>
|
||
{% endif %}
|
||
<span>/</span>
|
||
<span>{{ post.title }}</span>
|
||
</nav>
|
||
<section class="forum-layout">
|
||
<div class="topic-stream">
|
||
<article class="topic-post-card topic-detail-card">
|
||
<header class="topic-post-head">
|
||
<span class="topic-category">{{ post.category or l('综合讨论', 'General') }}</span>
|
||
{% if post.is_pinned %}<span class="topic-flag flag-pinned">{{ l('置顶', 'Pinned') }}</span>{% endif %}
|
||
{% if post.is_featured %}<span class="topic-flag flag-featured">{{ l('精华', 'Featured') }}</span>{% endif %}
|
||
{% if post.is_locked %}<span class="topic-flag flag-locked">{{ l('锁帖', 'Locked') }}</span>{% endif %}
|
||
{% if post.created_at %}
|
||
<time datetime="{{ post.created_at.strftime('%Y-%m-%dT%H:%M:%SZ') }}">{{ post.created_at.strftime('%Y-%m-%d %H:%M') }}</time>
|
||
{% endif %}
|
||
</header>
|
||
<h1>{{ post.title }}</h1>
|
||
<div class="topic-post-author">{{ l('作者:', 'Author: ') }}{{ post.author_rel.username if post.author_rel else l('已注销用户', 'Deleted user') }}</div>
|
||
<div class="topic-detail-meta-row">
|
||
{% if post.updated_at and post.created_at and post.updated_at != post.created_at %}
|
||
<span>{{ l('最近更新', 'Last updated') }} {{ post.updated_at.strftime('%Y-%m-%d %H:%M') }}</span>
|
||
{% endif %}
|
||
<span>{{ l('收藏', 'Bookmarks') }} {{ bookmark_count or 0 }}</span>
|
||
<span>{{ l('评论', 'Comments') }} {{ comments_count or comments|length }}</span>
|
||
<span>{{ l('阅读时长', 'Read time') }} {{ read_minutes }} {{ l('分钟', 'min') }}</span>
|
||
</div>
|
||
<nav class="post-mobile-quickjump" aria-label="{{ l('正文快捷入口', 'Quick Reading Entry') }}">
|
||
<a href="#post-content-start" class="forum-btn-muted" data-track-event="post_detail_jump_content" data-track-label="{{ 'quickjump_content_' ~ cta_track_suffix }}">{{ l('开始阅读', 'Start Reading') }}</a>
|
||
<a href="#post-outline-panel" class="forum-btn-muted" data-track-event="post_detail_jump_outline" data-track-label="{{ 'quickjump_outline_' ~ cta_track_suffix }}">{{ l('查看目录', 'Open Outline') }}</a>
|
||
</nav>
|
||
|
||
<section class="post-trust-action-hub" aria-label="{{ l('作者信誉与阅读行动', 'Author Trust and Reading Actions') }}">
|
||
<article class="post-author-cred">
|
||
<div class="post-author-badge" aria-hidden="true">
|
||
{% if post.author_rel and post.author_rel.username %}
|
||
{{ post.author_rel.username[0]|upper }}
|
||
{% else %}
|
||
?
|
||
{% endif %}
|
||
</div>
|
||
<div class="post-author-copy">
|
||
<h2>{{ l('作者信誉', 'Author Trust') }}</h2>
|
||
<p>{{ l('基于该主题的公开互动数据,帮助你快速判断参考价值。', 'Use topic interaction signals to quickly judge trust and relevance.') }}</p>
|
||
</div>
|
||
<dl class="post-author-stats">
|
||
<div>
|
||
<dt>{{ l('浏览', 'Views') }}</dt>
|
||
<dd>{{ post.view_count or 0 }}</dd>
|
||
</div>
|
||
<div>
|
||
<dt>{{ l('互动', 'Engagement') }}</dt>
|
||
<dd>{{ (comments_count or comments|length) + (like_count or 0) + (bookmark_count or 0) }}</dd>
|
||
</div>
|
||
</dl>
|
||
</article>
|
||
<article class="post-reading-rail">
|
||
<div class="post-reading-rail-head">
|
||
<h2>{{ l('阅读导航', 'Reading Navigation') }}</h2>
|
||
<strong id="post-current-section" data-default-label="{{ l('正文', 'Content') }}">{{ l('正文', 'Content') }}</strong>
|
||
</div>
|
||
<div class="post-reading-inline">
|
||
<span class="post-reading-inline-text" id="post-read-progress-text">0%</span>
|
||
<span class="post-reading-inline-bar" aria-hidden="true">
|
||
<span class="post-reading-inline-fill" id="post-read-progress-inline-fill"></span>
|
||
</span>
|
||
</div>
|
||
<div class="post-reading-rail-actions">
|
||
<a href="#post-outline-panel" class="forum-link" data-track-event="post_detail_jump_outline" data-track-label="{{ 'hub_jump_outline_' ~ cta_track_suffix }}">{{ l('打开目录', 'Open Outline') }}</a>
|
||
<a href="#comments-panel" class="forum-link" data-track-event="post_detail_jump_comments" data-track-label="{{ 'hub_jump_comments_' ~ cta_track_suffix }}">{{ l('跳至评论', 'Jump to Comments') }}</a>
|
||
</div>
|
||
</article>
|
||
<article class="post-related-quick">
|
||
<h2>{{ l('延伸话题', 'Related Threads') }}</h2>
|
||
{% if related %}
|
||
<ul class="post-related-quick-list">
|
||
{% for item in related[:2] %}
|
||
{% set rp = item.post %}
|
||
{% set related_tone = (loop.index0 % 4) + 1 %}
|
||
<li class="post-related-quick-card tone-{{ related_tone }}">
|
||
<span class="post-related-kicker">{{ rp.category or l('综合讨论', 'General') }}</span>
|
||
<a href="{{ url_for('forum_post_detail', post_id=rp.id) }}" class="post-related-quick-link" data-track-event="post_detail_related_click" data-track-label="{{ 'hub_' ~ rp.title }}">{{ rp.title }}</a>
|
||
<div class="post-related-quick-meta">
|
||
<span>{{ l('回复', 'Replies') }} {{ item.reply_count }}</span>
|
||
<span>{{ l('浏览', 'Views') }} {{ item.view_count }}</span>
|
||
</div>
|
||
</li>
|
||
{% endfor %}
|
||
</ul>
|
||
{% else %}
|
||
<p>{{ l('暂无延伸话题,建议先看评论区争议点。', 'No related threads yet. Check comments for key disagreements.') }}</p>
|
||
{% endif %}
|
||
</article>
|
||
</section>
|
||
|
||
<section class="post-decision-strip" aria-label="{{ l('采购决策速览', 'Procurement Snapshot') }}">
|
||
<div class="post-decision-copy">
|
||
<h2>{{ l('采购决策速览', 'Procurement Snapshot') }}</h2>
|
||
<p>{{ l('本帖已沉淀讨论结论与可执行方案,建议先快速浏览要点,再进入比价页筛选。', 'This topic already contains discussion outcomes and executable options. Review the highlights first, then shortlist plans on the comparison page.') }}</p>
|
||
</div>
|
||
<ul class="post-trust-list">
|
||
<li>{{ l('官方链接可直达', 'Official links available') }}</li>
|
||
<li>{{ l('结合社区经验筛选', 'Filtered with community insights') }}</li>
|
||
<li>{{ l('支持二次发帖补充需求', 'Post follow-up requirements') }}</li>
|
||
</ul>
|
||
<div class="post-decision-actions">
|
||
<a href="{{ pricing_target_url }}" class="forum-btn-primary {{ 'cta-emphasis' if cta_variant == 'intent' else '' }}" data-track-event="post_detail_cta_pricing" data-track-label="{{ 'decision_compare_plans_' ~ cta_track_suffix }}">{{ cta_primary_label }}</a>
|
||
{% if requirement_draft %}
|
||
{% if current_user and not current_user.is_banned %}
|
||
<a href="{{ requirement_draft.new_topic_url }}" class="forum-btn-muted" data-track-event="post_detail_requirement_template_click" data-track-label="{{ 'decision_template_new_topic_' ~ cta_track_suffix }}">{{ requirement_draft.action_text_member }}</a>
|
||
{% elif current_user and current_user.is_banned %}
|
||
<span class="topic-empty">{{ l('账号封禁中,暂不可发帖', 'Account banned. Posting is disabled.') }}</span>
|
||
{% else %}
|
||
<a href="{{ url_for('user_login', next=requirement_draft.new_topic_url) }}" class="forum-btn-muted" data-track-event="post_detail_requirement_template_click" data-track-label="{{ 'decision_template_login_' ~ cta_track_suffix }}">{{ requirement_draft.action_text_guest }}</a>
|
||
{% endif %}
|
||
{% else %}
|
||
{% if current_user and not current_user.is_banned %}
|
||
<a href="{{ url_for('forum_post_new') }}" class="forum-btn-muted" data-track-event="post_detail_cta_new_topic" data-track-label="{{ 'decision_new_topic_' ~ cta_track_suffix }}">{{ cta_secondary_member_label }}</a>
|
||
{% elif current_user and current_user.is_banned %}
|
||
<span class="topic-empty">{{ l('账号封禁中,暂不可发帖', 'Account banned. Posting is disabled.') }}</span>
|
||
{% else %}
|
||
<a href="{{ url_for('user_login', next='/forum/post/new') }}" class="forum-btn-muted" data-track-event="post_detail_cta_new_topic" data-track-label="{{ 'decision_login_new_topic_' ~ cta_track_suffix }}">{{ cta_secondary_guest_label }}</a>
|
||
{% endif %}
|
||
{% endif %}
|
||
{% if plan_recos %}
|
||
<a href="#post-inline-plans" class="forum-link" data-track-event="post_detail_inline_plan_view_all" data-track-label="{{ 'decision_jump_inline_plans_' ~ cta_track_suffix }}">{{ l('查看关联方案', 'Jump to Related Plans') }}</a>
|
||
{% else %}
|
||
<a href="{{ pricing_target_url }}" class="forum-link" data-track-event="post_detail_inline_plan_view_all" data-track-label="{{ 'decision_view_all_plans_' ~ cta_track_suffix }}">{{ l('查看全部方案', 'View All Plans') }}</a>
|
||
{% endif %}
|
||
</div>
|
||
{% if pricing_prefill_obj and pricing_prefill_obj.hint_text %}
|
||
<p class="post-decision-prefill">{{ pricing_prefill_obj.hint_text }}</p>
|
||
{% endif %}
|
||
<div class="post-decision-metrics" aria-label="{{ l('行动速览', 'Action Snapshot') }}">
|
||
<article>
|
||
<span>{{ l('推荐方案', 'Recommended Plans') }}</span>
|
||
<strong>{{ plan_recos|length }}</strong>
|
||
</article>
|
||
<article>
|
||
<span>{{ l('评论互动', 'Comment Signals') }}</span>
|
||
<strong>{{ comments_count or comments|length }}</strong>
|
||
</article>
|
||
<article>
|
||
<span>{{ l('决策阅读', 'Decision Read') }}</span>
|
||
<strong>{{ read_minutes }} {{ l('分钟', 'min') }}</strong>
|
||
</article>
|
||
</div>
|
||
</section>
|
||
|
||
<div class="topic-metric-grid">
|
||
<div><span>{{ l('浏览', 'Views') }}</span><strong>{{ post.view_count or 0 }}</strong></div>
|
||
<div><span>{{ l('评论', 'Comments') }}</span><strong>{{ comments_count or comments|length }}</strong></div>
|
||
<div><span>{{ l('点赞', 'Likes') }}</span><strong>{{ like_count or 0 }}</strong></div>
|
||
<div><span>{{ l('预计阅读', 'Read Time') }}</span><strong>{{ read_minutes }} {{ l('分钟', 'min') }}</strong></div>
|
||
</div>
|
||
<section class="post-proof-band" aria-label="{{ l('社区信号', 'Community Signals') }}">
|
||
<article class="post-proof-item">
|
||
<strong>{{ sb.total_users or 0 }}</strong>
|
||
<span>{{ l('活跃用户', 'Active Members') }}</span>
|
||
</article>
|
||
<article class="post-proof-item">
|
||
<strong>{{ sb.total_posts or 0 }}</strong>
|
||
<span>{{ l('社区主题', 'Topics') }}</span>
|
||
</article>
|
||
<article class="post-proof-item">
|
||
<strong>{{ sb.total_comments or 0 }}</strong>
|
||
<span>{{ l('累计评论', 'Comments') }}</span>
|
||
</article>
|
||
</section>
|
||
|
||
<div class="topic-action-bar">
|
||
{% if current_user and can_interact %}
|
||
<form method="post" action="{{ url_for('forum_post_like_toggle', post_id=post.id) }}">
|
||
<button type="submit" class="forum-btn-muted {{ 'active' if liked_by_me else '' }}">{{ l('已点赞', 'Liked') if liked_by_me else l('点赞', 'Like') }}</button>
|
||
</form>
|
||
<form method="post" action="{{ url_for('forum_post_bookmark_toggle', post_id=post.id) }}">
|
||
<button type="submit" class="forum-btn-muted {{ 'active' if bookmarked_by_me else '' }}">{{ l('已收藏', 'Bookmarked') if bookmarked_by_me else l('收藏', 'Bookmark') }}</button>
|
||
</form>
|
||
{% elif current_user and not can_interact %}
|
||
<span class="topic-empty">{{ l('账号被封禁,暂不可互动', 'Your account is banned. Interaction is disabled.') }}</span>
|
||
{% else %}
|
||
<a href="{{ url_for('user_login', next=request.path) }}" class="forum-btn-muted">{{ l('登录后点赞/收藏', 'Login to like/bookmark') }}</a>
|
||
{% endif %}
|
||
<button type="button" class="forum-btn-muted js-copy-link" data-track-event="post_detail_copy_link" data-track-label="copy_permalink" data-copy-success="{{ l('链接已复制', 'Link copied') }}" data-copy-failed="{{ l('复制失败,请手动复制地址栏链接', 'Copy failed. Please copy the URL manually.') }}">{{ l('复制链接', 'Copy Link') }}</button>
|
||
<span class="copy-link-feedback" id="copy-link-feedback" aria-live="polite"></span>
|
||
{% if current_user and current_user.id == post.user_id and can_interact %}
|
||
<a href="{{ url_for('forum_post_edit', post_id=post.id) }}" class="forum-btn-muted">{{ l('编辑帖子', 'Edit Topic') }}</a>
|
||
<form method="post" action="{{ url_for('forum_post_delete', post_id=post.id) }}" onsubmit="return confirm('{{ l('确定删除该帖子?删除后不可恢复。', 'Delete this topic permanently?') }}');">
|
||
<button type="submit" class="forum-btn-danger">{{ l('删除帖子', 'Delete Topic') }}</button>
|
||
</form>
|
||
{% elif current_user and current_user.id == post.user_id and not can_interact %}
|
||
<span class="topic-empty">{{ l('账号封禁中,无法编辑或删除帖子', 'Account banned. Editing/deleting is disabled.') }}</span>
|
||
{% elif current_user and can_interact %}
|
||
<form method="post" action="{{ url_for('forum_report_create') }}" class="report-form-inline">
|
||
<input type="hidden" name="target_type" value="post">
|
||
<input type="hidden" name="target_id" value="{{ post.id }}">
|
||
<select name="reason" required>
|
||
{% for reason in forum_report_reasons %}
|
||
<option value="{{ reason }}">{{ reason }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
<button type="submit" class="forum-btn-muted">{{ l('举报帖子', 'Report Topic') }}</button>
|
||
</form>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<div class="post-reading-layout">
|
||
<div id="post-content-start" class="topic-post-content md-content">{{ post.content|markdown_html }}</div>
|
||
<section id="post-outline-panel" class="post-outline-panel post-outline-floating" aria-label="{{ l('帖子目录', 'Topic Outline') }}" hidden>
|
||
<div class="post-outline-head">
|
||
<h2>{{ l('快速导航', 'Quick Navigation') }}</h2>
|
||
<a href="#comments-panel" class="forum-link" data-track-event="post_detail_jump_comments" data-track-label="outline_jump_comments">{{ l('跳至评论', 'Jump to comments') }}</a>
|
||
</div>
|
||
<ol id="post-outline-list" class="post-outline-list"></ol>
|
||
</section>
|
||
</div>
|
||
{% if resource_links %}
|
||
<section class="post-resource-links" aria-label="{{ l('延伸阅读与采购路径', 'Extended Reading and Buying Paths') }}">
|
||
<h2>{{ l('延伸阅读与采购路径', 'Extended Reading and Buying Paths') }}</h2>
|
||
<ul class="resource-link-list">
|
||
{% for item in resource_links %}
|
||
<li>
|
||
<a href="{{ item.url }}" data-track-event="post_detail_resource_click" data-track-label="{{ item.track_label }}">{{ item.title }}</a>
|
||
<p>{{ item.description }}</p>
|
||
</li>
|
||
{% endfor %}
|
||
</ul>
|
||
</section>
|
||
{% endif %}
|
||
|
||
{% if post_faq %}
|
||
<section class="post-faq-panel" aria-label="{{ l('帖子导读 FAQ', 'Topic FAQ') }}">
|
||
<h2>{{ l('帖子导读 FAQ', 'Topic FAQ') }}</h2>
|
||
<dl>
|
||
{% for item in post_faq %}
|
||
<dt>{{ item.question }}</dt>
|
||
<dd>{{ item.answer }}</dd>
|
||
{% endfor %}
|
||
</dl>
|
||
</section>
|
||
{% endif %}
|
||
|
||
{% if plan_recos %}
|
||
<section id="post-inline-plans" class="post-inline-plan-panel" aria-label="{{ l('本帖关联方案速览', 'Plans Mentioned in This Topic') }}">
|
||
<div class="post-inline-plan-head">
|
||
<h2>{{ l('本帖关联方案速览', 'Plans Mentioned in This Topic') }}</h2>
|
||
<a href="{{ pricing_target_url }}" class="forum-link" data-track-event="post_detail_inline_plan_view_all" data-track-label="inline_view_all_plans">{{ l('查看全部方案', 'View all plans') }}</a>
|
||
</div>
|
||
<ul class="post-inline-plan-list">
|
||
{% for plan in plan_recos[:3] %}
|
||
{% set inline_plan_href = plan.official_url or pricing_target_url %}
|
||
<li>
|
||
<div class="post-inline-plan-main">
|
||
<a href="{{ inline_plan_href }}" {% if plan.official_url %}target="_blank" rel="noopener nofollow"{% endif %} data-track-event="post_detail_inline_plan_click" data-track-label="{{ plan.provider ~ ' ' ~ plan.name }}">{{ plan.provider }} · {{ plan.name }}</a>
|
||
<p>{{ plan.region }}</p>
|
||
</div>
|
||
<strong>{{ plan.price_label }}</strong>
|
||
</li>
|
||
{% endfor %}
|
||
</ul>
|
||
</section>
|
||
{% endif %}
|
||
|
||
{% if requirement_draft %}
|
||
<section class="post-requirement-brief" aria-label="{{ l('需求模板快捷入口', 'Requirement Template Shortcut') }}">
|
||
<div class="post-requirement-copy">
|
||
<h2>{{ l('需求模板快捷入口', 'Requirement Template Shortcut') }}</h2>
|
||
<p>{{ requirement_draft.intro_text }}</p>
|
||
<div class="post-requirement-preview">
|
||
<span>{{ l('预填标题', 'Prefilled title') }}</span>
|
||
<strong>{{ requirement_draft.preview_title }}</strong>
|
||
</div>
|
||
<ul class="post-requirement-tips">
|
||
{% for tip in requirement_draft.tips %}
|
||
<li>{{ tip }}</li>
|
||
{% endfor %}
|
||
</ul>
|
||
</div>
|
||
<div class="post-requirement-actions">
|
||
{% if current_user and not current_user.is_banned %}
|
||
<a href="{{ requirement_draft.new_topic_url }}" class="forum-btn-primary" data-track-event="post_detail_requirement_template_click" data-track-label="{{ 'template_new_topic_' ~ cta_track_suffix }}">{{ requirement_draft.action_text_member }}</a>
|
||
{% elif current_user and current_user.is_banned %}
|
||
<span class="topic-empty">{{ l('账号封禁中,暂不可发帖', 'Account banned. Posting is disabled.') }}</span>
|
||
{% else %}
|
||
<a href="{{ url_for('user_login', next=requirement_draft.new_topic_url) }}" class="forum-btn-primary" data-track-event="post_detail_requirement_template_click" data-track-label="{{ 'template_login_new_topic_' ~ cta_track_suffix }}">{{ requirement_draft.action_text_guest }}</a>
|
||
{% endif %}
|
||
<a href="{{ pricing_target_url }}" class="forum-btn-muted" data-track-event="post_detail_cta_pricing" data-track-label="{{ 'template_compare_plans_' ~ cta_track_suffix }}">{{ l('对照价格页筛选', 'Compare on Pricing Page') }}</a>
|
||
</div>
|
||
</section>
|
||
{% endif %}
|
||
|
||
<div class="post-commercial-cta post-commercial-cta-{{ cta_variant or 'control' }}">
|
||
<div class="post-commercial-copy">
|
||
<h3>{{ cta_copy.headline }}</h3>
|
||
<p>{{ cta_copy.description }}</p>
|
||
</div>
|
||
<div class="post-commercial-actions">
|
||
<a href="{{ pricing_target_url }}" class="forum-btn-primary {{ 'cta-emphasis' if cta_variant == 'intent' else '' }}" data-track-event="post_detail_cta_pricing" data-track-label="{{ 'main_compare_plans_' ~ cta_track_suffix }}">{{ cta_primary_label }}</a>
|
||
{% if requirement_draft %}
|
||
{% if current_user and not current_user.is_banned %}
|
||
<a href="{{ requirement_draft.new_topic_url }}" class="forum-btn-muted" data-track-event="post_detail_requirement_template_click" data-track-label="{{ 'main_template_new_topic_' ~ cta_track_suffix }}">{{ requirement_draft.action_text_member }}</a>
|
||
{% elif current_user and current_user.is_banned %}
|
||
<span class="topic-empty">{{ l('账号封禁中,暂不可发帖', 'Account banned. Posting is disabled.') }}</span>
|
||
{% else %}
|
||
<a href="{{ url_for('user_login', next=requirement_draft.new_topic_url) }}" class="forum-btn-muted" data-track-event="post_detail_requirement_template_click" data-track-label="{{ 'main_template_login_' ~ cta_track_suffix }}">{{ requirement_draft.action_text_guest }}</a>
|
||
{% endif %}
|
||
{% else %}
|
||
{% if current_user and not current_user.is_banned %}
|
||
<a href="{{ url_for('forum_post_new') }}" class="forum-btn-muted" data-track-event="post_detail_cta_new_topic" data-track-label="{{ 'main_post_requirement_' ~ cta_track_suffix }}">{{ cta_secondary_member_label }}</a>
|
||
{% elif current_user and current_user.is_banned %}
|
||
<span class="topic-empty">{{ l('账号封禁中,暂不可发帖', 'Account banned. Posting is disabled.') }}</span>
|
||
{% else %}
|
||
<a href="{{ url_for('user_login', next='/forum/post/new') }}" class="forum-btn-muted" data-track-event="post_detail_cta_new_topic" data-track-label="{{ 'main_login_post_requirement_' ~ cta_track_suffix }}">{{ cta_secondary_guest_label }}</a>
|
||
{% endif %}
|
||
{% endif %}
|
||
<a href="#comments-panel" class="forum-btn-muted" data-track-event="post_detail_jump_comments" data-track-label="{{ 'main_jump_comments_' ~ cta_track_suffix }}">{{ l('查看评论', 'Jump to Comments') }}</a>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
|
||
<section id="comments-panel" class="topic-post-card">
|
||
<h2>{{ l('评论', 'Comments') }}({{ comments_count or comments|length }})</h2>
|
||
{% if message %}
|
||
<p class="form-success">{{ message }}</p>
|
||
{% endif %}
|
||
{% if error %}
|
||
<p class="form-error">{{ error }}</p>
|
||
{% endif %}
|
||
|
||
{% if post.is_locked %}
|
||
<p class="topic-empty">{{ l('该帖子已锁定,暂不允许新增评论。', 'This topic is locked. New comments are disabled.') }}</p>
|
||
{% elif current_user and can_interact %}
|
||
<form method="post" action="{{ url_for('forum_post_comment', post_id=post.id) }}" class="comment-form">
|
||
<div class="form-group">
|
||
<label for="content">{{ l('写下你的评论', 'Write your comment') }}</label>
|
||
<textarea id="content" name="content" required rows="4" minlength="2"></textarea>
|
||
<small class="form-help">{{ l('支持 Markdown 代码块。', 'Markdown code blocks are supported.') }}</small>
|
||
</div>
|
||
<button type="submit" class="forum-btn-primary">{{ l('发布评论', 'Post Comment') }}</button>
|
||
</form>
|
||
{% elif current_user and not can_interact %}
|
||
<p class="topic-empty">{{ l('账号被封禁,暂不可评论。', 'Your account is banned. Commenting is disabled.') }}</p>
|
||
{% else %}
|
||
<p class="topic-empty">{{ l('请先', 'Please') }} <a href="{{ url_for('user_login', next=request.path) }}">{{ l('登录', 'log in') }}</a> {{ l('后评论。', 'to comment.') }}</p>
|
||
{% endif %}
|
||
|
||
{% if comments %}
|
||
<ul class="comment-stream">
|
||
{% for c in comments %}
|
||
<li id="comment-{{ c.id }}" class="comment-row">
|
||
<div class="comment-avatar">{{ (c.author_rel.username[0] if c.author_rel and c.author_rel.username else '?')|upper }}</div>
|
||
<div class="comment-body">
|
||
<div class="comment-head">
|
||
<span class="comment-author">{{ c.author_rel.username if c.author_rel else l('已注销用户', 'Deleted user') }}</span>
|
||
{% if c.created_at %}
|
||
<time datetime="{{ c.created_at.strftime('%Y-%m-%dT%H:%M:%SZ') }}">{{ c.created_at.strftime('%Y-%m-%d %H:%M') }}</time>
|
||
{% endif %}
|
||
</div>
|
||
<div class="comment-content md-content">{{ c.content|markdown_html }}</div>
|
||
<div class="comment-actions">
|
||
{% if current_user and current_user.id == c.user_id and can_interact %}
|
||
<a href="{{ url_for('forum_comment_edit', comment_id=c.id) }}">{{ l('编辑', 'Edit') }}</a>
|
||
<form method="post" action="{{ url_for('forum_comment_delete', comment_id=c.id) }}" onsubmit="return confirm('{{ l('确定删除这条评论?', 'Delete this comment?') }}');">
|
||
<button type="submit" class="btn-link-delete">{{ l('删除', 'Delete') }}</button>
|
||
</form>
|
||
{% elif current_user and current_user.id == c.user_id and not can_interact %}
|
||
<span class="muted-text">{{ l('账号封禁中', 'Account banned') }}</span>
|
||
{% elif current_user and can_interact %}
|
||
<form method="post" action="{{ url_for('forum_report_create') }}" class="report-form-inline">
|
||
<input type="hidden" name="target_type" value="comment">
|
||
<input type="hidden" name="target_id" value="{{ c.id }}">
|
||
<select name="reason" required>
|
||
{% for reason in forum_report_reasons %}
|
||
<option value="{{ reason }}">{{ reason }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
<button type="submit" class="btn-link-delete">{{ l('举报', 'Report') }}</button>
|
||
</form>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
</li>
|
||
{% endfor %}
|
||
</ul>
|
||
{% else %}
|
||
<p class="topic-empty">{{ l('还没有评论,欢迎抢沙发。', 'No comments yet. Be the first to reply.') }}</p>
|
||
{% endif %}
|
||
|
||
{% if comments_total_pages is defined and comments_total_pages > 1 %}
|
||
<nav class="forum-pagination forum-pagination-inline" aria-label="{{ l('评论分页', 'Comment Pagination') }}">
|
||
{% if comment_prev_url %}
|
||
<a class="page-link" href="{{ comment_prev_url }}">{{ l('上一页', 'Prev') }}</a>
|
||
{% else %}
|
||
<span class="page-link disabled">{{ l('上一页', 'Prev') }}</span>
|
||
{% endif %}
|
||
{% for item in comment_page_links %}
|
||
{% if item.is_gap %}
|
||
<span class="page-link disabled">{{ item.label }}</span>
|
||
{% else %}
|
||
<a class="page-link {{ 'active' if item.active else '' }}" href="{{ item.url }}">{{ item.page }}</a>
|
||
{% endif %}
|
||
{% endfor %}
|
||
{% if comment_next_url %}
|
||
<a class="page-link" href="{{ comment_next_url }}">{{ l('下一页', 'Next') }}</a>
|
||
{% else %}
|
||
<span class="page-link disabled">{{ l('下一页', 'Next') }}</span>
|
||
{% endif %}
|
||
</nav>
|
||
{% endif %}
|
||
</section>
|
||
</div>
|
||
|
||
<aside class="forum-sidebar">
|
||
<div class="side-card side-profile-card">
|
||
<div class="side-profile-head">
|
||
<div class="side-avatar">
|
||
{% if post.author_rel and post.author_rel.username %}
|
||
{{ post.author_rel.username[0]|upper }}
|
||
{% else %}
|
||
?
|
||
{% endif %}
|
||
</div>
|
||
<div class="side-profile-meta">
|
||
<strong>{{ post.author_rel.username if post.author_rel else l('已注销用户', 'Deleted user') }}</strong>
|
||
<span>{{ l('主题作者', 'Topic author') }} · {{ post.category or l('综合讨论', 'General') }}</span>
|
||
</div>
|
||
</div>
|
||
<ul class="side-list">
|
||
<li><span>{{ l('发帖时间', 'Posted') }}</span><strong>{{ post.created_at.strftime('%Y-%m-%d') if post.created_at else '—' }}</strong></li>
|
||
<li><span>{{ l('阅读时长', 'Read time') }}</span><strong>{{ read_minutes }} {{ l('分钟', 'min') }}</strong></li>
|
||
<li><span>{{ l('评论数', 'Comments') }}</span><strong>{{ comments_count or comments|length }}</strong></li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="side-card side-notice-card">
|
||
<h3>{{ l('阅读建议', 'Reading Tips') }}</h3>
|
||
<ul class="side-notice-list">
|
||
<li>{{ l('先看目录和 FAQ,再进评论区看争议点。', 'Review outline and FAQ first, then inspect comments for tradeoffs.') }}</li>
|
||
<li>{{ l('比价前先确认预算和线路约束。', 'Confirm budget and route constraints before shortlisting.') }}</li>
|
||
<li>{{ l('需求不清晰时,建议用模板补充发帖。', 'If requirements are unclear, publish a follow-up with template prefill.') }}</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="side-card side-cta side-cta-sticky">
|
||
<h3>{{ l('下一步行动', 'Next Action') }}</h3>
|
||
<p>{{ cta_copy.description }}</p>
|
||
<div class="side-cta-kpi">
|
||
<div><span>{{ l('本帖浏览', 'Views') }}</span><strong>{{ post.view_count or 0 }}</strong></div>
|
||
<div><span>{{ l('互动总量', 'Engagement') }}</span><strong>{{ (comments_count or comments|length) + (like_count or 0) + (bookmark_count or 0) }}</strong></div>
|
||
</div>
|
||
<div class="form-actions">
|
||
<a href="{{ pricing_target_url }}" class="forum-btn-primary {{ 'cta-emphasis' if cta_variant == 'intent' else '' }}" data-track-event="post_detail_sidebar_compare" data-track-label="{{ 'sidebar_shortlist_' ~ cta_track_suffix }}">{{ cta_primary_label }}</a>
|
||
{% if requirement_draft %}
|
||
{% if current_user and not current_user.is_banned %}
|
||
<a href="{{ requirement_draft.new_topic_url }}" class="forum-btn-muted" data-track-event="post_detail_requirement_template_click" data-track-label="{{ 'sidebar_template_new_topic_' ~ cta_track_suffix }}">{{ requirement_draft.action_text_member }}</a>
|
||
{% elif current_user and current_user.is_banned %}
|
||
<span class="topic-empty">{{ l('账号封禁中,暂不可发帖', 'Account banned. Posting is disabled.') }}</span>
|
||
{% else %}
|
||
<a href="{{ url_for('user_login', next=requirement_draft.new_topic_url) }}" class="forum-btn-muted" data-track-event="post_detail_requirement_template_click" data-track-label="{{ 'sidebar_template_login_' ~ cta_track_suffix }}">{{ requirement_draft.action_text_guest }}</a>
|
||
{% endif %}
|
||
{% else %}
|
||
{% if current_user and not current_user.is_banned %}
|
||
<a href="{{ url_for('forum_post_new') }}" class="forum-btn-muted" data-track-event="post_detail_cta_new_topic" data-track-label="{{ 'sidebar_new_topic_' ~ cta_track_suffix }}">{{ l('发布新主题', 'New Topic') }}</a>
|
||
{% elif current_user and current_user.is_banned %}
|
||
<span class="topic-empty">{{ l('账号封禁中,暂不可发帖', 'Account banned. Posting is disabled.') }}</span>
|
||
{% else %}
|
||
<a href="{{ url_for('user_login', next='/forum/post/new') }}" class="forum-btn-muted" data-track-event="post_detail_cta_new_topic" data-track-label="{{ 'sidebar_login_new_topic_' ~ cta_track_suffix }}">{{ l('登录后发帖', 'Login to Post') }}</a>
|
||
{% endif %}
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
<div class="side-card">
|
||
<h3>{{ l('社区统计', 'Community Stats') }}</h3>
|
||
<div class="side-stats">
|
||
<div><span>{{ l('用户', 'Users') }}</span><strong>{{ sb.total_users }}</strong></div>
|
||
<div><span>{{ l('帖子', 'Posts') }}</span><strong>{{ sb.total_posts }}</strong></div>
|
||
<div><span>{{ l('评论', 'Comments') }}</span><strong>{{ sb.total_comments }}</strong></div>
|
||
</div>
|
||
</div>
|
||
<div class="side-card">
|
||
<h3>{{ l('分类标签云', 'Category Tags') }}</h3>
|
||
{% if sb.category_counts %}
|
||
<div class="side-tag-cloud">
|
||
{% for name, count in sb.category_counts %}
|
||
<a href="{{ url_for('forum_index', category=name) }}" class="side-tag">{{ name }}<strong>{{ count }}</strong></a>
|
||
{% endfor %}
|
||
</div>
|
||
{% else %}
|
||
<p class="side-empty">{{ l('暂无分类数据', 'No category data') }}</p>
|
||
{% endif %}
|
||
</div>
|
||
<div class="side-card">
|
||
<h3>{{ l('相关推荐', 'Related Topics') }}</h3>
|
||
{% if related %}
|
||
<ul class="related-post-list">
|
||
{% for item in related %}
|
||
{% set rp = item.post %}
|
||
{% set related_tone = (loop.index0 % 4) + 1 %}
|
||
<li class="related-post-card tone-{{ related_tone }}">
|
||
<span class="related-post-kicker">{{ rp.category or l('综合讨论', 'General') }}</span>
|
||
<a href="{{ url_for('forum_post_detail', post_id=rp.id) }}" data-track-event="post_detail_related_click" data-track-label="{{ rp.title }}">{{ rp.title }}</a>
|
||
<div class="related-post-meta">
|
||
<span>{{ l('回复', 'Replies') }} {{ item.reply_count }}</span>
|
||
<span>{{ l('浏览', 'Views') }} {{ item.view_count }}</span>
|
||
{% if rp.created_at %}
|
||
<span>{{ rp.created_at.strftime('%m-%d') }}</span>
|
||
{% endif %}
|
||
</div>
|
||
</li>
|
||
{% endfor %}
|
||
</ul>
|
||
{% else %}
|
||
<p class="side-empty">{{ l('暂无相关推荐', 'No related topics yet') }}</p>
|
||
{% endif %}
|
||
</div>
|
||
<div class="side-card">
|
||
<h3>{{ l('推荐方案', 'Recommended Plans') }}</h3>
|
||
<p class="plan-reco-context">{{ plan_reco_context if plan_reco_context is defined else l('按价格与规格综合排序推荐', 'Recommended by a combined price/spec ranking') }}</p>
|
||
{% if plan_recos %}
|
||
<ul class="plan-reco-list">
|
||
{% for plan in plan_recos %}
|
||
<li>
|
||
{% set plan_href = plan.official_url or pricing_target_url %}
|
||
<a href="{{ plan_href }}" {% if plan.official_url %}target="_blank" rel="noopener nofollow"{% endif %} data-track-event="post_detail_plan_click" data-track-label="{{ plan.provider ~ ' ' ~ plan.name }}">{{ plan.provider }} · {{ plan.name }}</a>
|
||
<div class="plan-reco-meta">
|
||
<span>{{ plan.region }}</span>
|
||
<strong>{{ plan.price_label }}</strong>
|
||
</div>
|
||
</li>
|
||
{% endfor %}
|
||
</ul>
|
||
{% else %}
|
||
<p class="side-empty">{{ l('暂无可推荐方案', 'No plan recommendations yet') }}</p>
|
||
{% endif %}
|
||
<div class="form-actions">
|
||
<a href="{{ pricing_target_url }}" class="forum-btn-muted" data-track-event="post_detail_sidebar_compare" data-track-label="sidebar_view_all_plans">{{ l('查看全部方案', 'View All Plans') }}</a>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
</section>
|
||
<section class="post-mobile-conversion-bar" data-mobile-conversion-bar aria-label="{{ l('移动端快捷转化操作', 'Mobile Conversion Actions') }}">
|
||
<div class="post-mobile-conversion-main">
|
||
<strong>{{ cta_copy.headline }}</strong>
|
||
<span>{{ l('基于本帖结论快速行动', 'Take action from this topic now') }}</span>
|
||
</div>
|
||
<div class="post-mobile-conversion-actions">
|
||
<a href="{{ pricing_target_url }}" class="forum-btn-primary {{ 'cta-emphasis' if cta_variant == 'intent' else '' }}" data-track-event="post_detail_cta_pricing" data-track-label="{{ 'mobile_compare_plans_' ~ cta_track_suffix }}">{{ cta_primary_label }}</a>
|
||
{% if requirement_draft %}
|
||
{% if current_user and not current_user.is_banned %}
|
||
<a href="{{ requirement_draft.new_topic_url }}" class="forum-btn-muted" data-track-event="post_detail_requirement_template_click" data-track-label="{{ 'mobile_template_new_topic_' ~ cta_track_suffix }}">{{ l('一键发需求', 'Prefill Need') }}</a>
|
||
{% elif current_user and current_user.is_banned %}
|
||
<span class="topic-empty">{{ l('账号封禁中', 'Account banned') }}</span>
|
||
{% else %}
|
||
<a href="{{ url_for('user_login', next=requirement_draft.new_topic_url) }}" class="forum-btn-muted" data-track-event="post_detail_requirement_template_click" data-track-label="{{ 'mobile_template_login_' ~ cta_track_suffix }}">{{ l('登录后发需求', 'Login to Prefill') }}</a>
|
||
{% endif %}
|
||
{% else %}
|
||
{% if current_user and not current_user.is_banned %}
|
||
<a href="{{ url_for('forum_post_new') }}" class="forum-btn-muted" data-track-event="post_detail_cta_new_topic" data-track-label="{{ 'mobile_new_topic_' ~ cta_track_suffix }}">{{ l('发布需求', 'Post Need') }}</a>
|
||
{% elif current_user and current_user.is_banned %}
|
||
<span class="topic-empty">{{ l('账号封禁中', 'Account banned') }}</span>
|
||
{% else %}
|
||
<a href="{{ url_for('user_login', next='/forum/post/new') }}" class="forum-btn-muted" data-track-event="post_detail_cta_new_topic" data-track-label="{{ 'mobile_login_new_topic_' ~ cta_track_suffix }}">{{ l('登录后发帖', 'Login to Post') }}</a>
|
||
{% endif %}
|
||
{% endif %}
|
||
<a href="#comments-panel" class="forum-link" data-track-event="post_detail_jump_comments" data-track-label="{{ 'mobile_jump_comments_' ~ cta_track_suffix }}">{{ l('看评论', 'Comments') }}</a>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
<script src="{{ url_for('static', filename='js/forum-post-detail.js') }}" defer></script>
|
||
</body>
|
||
</html>
|