Files
Victor_Jay 584d7fd146 fix: 修复 /space 关注按钮在默认标签页无法点击
- 将顶部关注按钮 JS 从 following/followers 标签页限定块中提取到全局脚本
- 按钮在所有标签页均可点击(之前仅在 following/followers 标签页有效)
- 本人点击关注时 toast 提示"不能关注自己",与赋能按钮行为一致
- 未登录用户点击关注跳转登录页
- 移除标签页限定块中的重复顶部按钮代码
2026-06-03 13:00:12 +08:00

758 lines
38 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{{template "layout/header.html" .}}
<body>
{{template "layout/nav.html" .}}
{{if .Error}}
<div class="space-error">
<div class="container">
<h1>{{.Error}}</h1>
<a href="/" class="btn btn-primary">返回首页</a>
</div>
</div>
{{else}}
<div class="space-page">
<!-- ====== 顶部信息栏(访客+本人共用) ====== -->
<div class="space-profile-header">
<div class="space-header-inner">
<!-- 左:头像 + 用户名 -->
<div class="space-header-user">
<a href="/space/{{.SpaceUser.ID}}" class="space-avatar-link">
{{if .SpaceUser.Avatar}}
<img src="{{.SpaceUser.Avatar}}" alt="{{.SpaceUser.Username}}" class="space-avatar-img">
{{else}}
<div class="space-avatar-placeholder"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></svg></div>
{{end}}
</a>
<div class="space-header-info">
<span class="space-username">{{.SpaceUser.Username}}</span>
{{if .SpaceUser.Bio}}
<p class="space-header-bio">{{.SpaceUser.Bio}}</p>
{{end}}
</div>
</div>
<!-- 右:操作按钮 -->
<div class="space-header-actions">
<button id="space-follow-btn" class="space-action-btn primary" data-uid="{{.SpaceUser.ID}}" data-current-uid="{{.CurrentUID}}">+ 关注</button>
{{if not .IsOwnSpace}}
<button class="space-action-btn">发消息</button>
<button class="space-action-btn icon-only" title="更多"></button>
{{end}}
</div>
</div>
</div>
<!-- ====== Tab 导航栏(区分本人/访客) ====== -->
{{if .IsOwnSpace}}
<!-- 本人视图左Tab + 右统计 -->
<div class="space-tab-bar owner">
<div class="space-tabs-left">
<a href="/space/{{.SpaceUser.ID}}?tab=articles"
class="space-tab{{if eq .ActiveTab "articles"}} active{{end}}">
<svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zM6 20V4h7v5h5v11H6z"/></svg>
文章
<span class="tab-count">{{.PostCount}}</span>
</a>
<a href="/space/{{.SpaceUser.ID}}?tab=collections"
class="space-tab{{if eq .ActiveTab "collections"}} active{{end}}">
<svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M17 3H7c-1.1 0-2 .9-2 2v16l7-3 7 3V5c0-1.1-.9-2-2-2z"/></svg>
收藏
<span class="tab-count">{{.TotalFavorites}}</span>
</a>
<a href="/space/{{.SpaceUser.ID}}?tab=settings"
class="space-tab{{if eq .ActiveTab "settings"}} active{{end}}">
<svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M19.14 12.94c.04-.31.06-.63.06-.94 0-.31-.02-.63-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94L14.4 2.81c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.04.31-.06.63-.06.94s.02.63.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/></svg>
设置
</a>
</div>
<div class="space-stats-right">
<div class="stat-item">
<span class="stat-label">关注</span>
<span class="stat-value">{{.SpaceUser.FollowingCount}}</span>
</div>
<div class="stat-item">
<span class="stat-label">粉丝</span>
<span class="stat-value">{{.SpaceUser.FollowersCount}}</span>
</div>
<div class="stat-item">
<span class="stat-label">获赞</span>
<span class="stat-value">{{formatCount .TotalLikes}}</span>
</div>
<div class="stat-item">
<span class="stat-label">阅读量</span>
<span class="stat-value">{{formatCount .TotalReads}}</span>
</div>
</div>
</div>
{{else}}
<!-- 访客视图:统计栏 -->
<div class="space-tab-bar visitor">
<div class="space-tabs-left">
<a href="/space/{{.SpaceUser.ID}}?tab=articles"
class="space-tab{{if eq .ActiveTab "articles"}} active{{end}}">
<svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zM6 20V4h7v5h5v11H6z"/></svg>
文章
<span class="tab-count">{{.PostCount}}</span>
</a>
<a href="/space/{{.SpaceUser.ID}}?tab=following"
class="space-tab{{if or (eq .ActiveTab "following") (eq .ActiveTab "followers")}} active{{end}}">
<span class="stat-label-inline">关注数</span>
<span class="tab-count">{{.SpaceUser.FollowingCount}}</span>
</a>
<a href="/space/{{.SpaceUser.ID}}?tab=followers" class="space-tab">
<span class="stat-label-inline">粉丝数</span>
<span class="tab-count">{{.SpaceUser.FollowersCount}}</span>
</a>
<div class="stat-item-inline">
<span class="stat-label-inline">获赞数</span>
<span class="stat-value-inline">{{formatCount .TotalLikes}}</span>
</div>
<div class="stat-item-inline">
<span class="stat-label-inline">阅读量</span>
<span class="stat-value-inline">{{formatCount .TotalReads}}</span>
</div>
</div>
</div>
{{end}}
<!-- ====== 主内容区(左右分栏) ====== -->
<div class="space-card-layout">
{{/* ========== 文章 Tab ==========*/}}
{{if eq .ActiveTab "articles"}}
<main class="space-main-full">
<h1 class="space-section-title">{{if .IsOwnSpace}}我的文章{{else}}Ta 的文章{{end}}</h1>
{{if .Posts}}
{{if gt (len .Posts) 0}}
<div class="space-post-list">
{{range $i, $post := .Posts}}
<article class="space-post-card">
<a href="/posts/{{$post.ID}}" class="space-post-title">{{$post.Title}}</a>
<p class="space-post-excerpt">{{if $post.Excerpt}}{{printf "%.120s" $post.Excerpt}}{{else}}{{printf "%.120s" $post.Body}}{{end}}</p>
<div class="space-post-meta">
<span class="post-meta-item">
<svg viewBox="0 0 24 24" width="14" height="14"><path fill="currentColor" d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></svg>
{{$post.LikesCount}}
</span>
<span class="post-meta-item">
<svg viewBox="0 0 24 24" width="14" height="14"><path fill="currentColor" d="M17 3H7c-1.1 0-2 .9-2 2v16l7-3 7 3V5c0-1.1-.9-2-2-2z"/></svg>
{{$post.FavoritesCount}}
</span>
<span class="post-meta-item">
<svg viewBox="0 0 24 24" width="14" height="14"><path fill="currentColor" d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H6l-2 2V4h16v12z"/></svg>
{{$post.CommentsCount}}
</span>
<span class="post-meta-time">{{$post.CreatedAt.Format "01-02 15:04"}}</span>
</div>
</article>
{{end}}
</div>
{{if gt .TotalPages 1}}
<div class="pagination">
{{if gt .Page 1}}
<a href="?tab=articles&page={{.PrevPage}}" class="page-link">上一页</a>
{{end}}
<span class="page-info">第 {{.Page}} / {{.TotalPages}} 页</span>
{{if le .Page .TotalPages}}
<a href="?tab=articles&page={{.NextPage}}" class="page-link">下一页</a>
{{end}}
</div>
{{end}}
{{else}}
<div class="space-empty-state">
<p>{{if .IsOwnSpace}}还没有发布过文章,去创作吧~{{else}}Ta 还没有发布文章{{end}}</p>
</div>
{{end}}
{{else}}
<div class="space-empty-state">
<p>暂无数据</p>
</div>
{{end}}
</main>
{{/* ========== 关注列表 Tab含本人+访客) ==========*/}}
{{end}}
{{if or (eq .ActiveTab "following") (eq .ActiveTab "followers")}}
<!-- 左侧导航 -->
<aside class="space-sidebar">
<h2 class="space-sidebar-title">{{if .IsOwnSpace}}我的关注{{else}}Ta的关注{{end}}</h2>
<nav class="space-sidebar-nav">
<a href="/space/{{.SpaceUser.ID}}?tab=following"
class="space-sidebar-link{{if eq .ActiveTab "following"}} active{{end}}">
<svg class="space-sidebar-icon" viewBox="0 0 24 24" width="18" height="18"><path fill="currentColor" d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></svg>
{{if .IsOwnSpace}}全部关注{{else}}全部关注{{end}}
<span class="space-sidebar-count">{{.SpaceUser.FollowingCount}}</span>
</a>
<a href="/space/{{.SpaceUser.ID}}?tab=followers"
class="space-sidebar-link{{if eq .ActiveTab "followers"}} active{{end}}">
<svg class="space-sidebar-icon" viewBox="0 0 24 24" width="18" height="18"><path fill="currentColor" d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/></svg>
{{if .IsOwnSpace}}粉丝{{else}}Ta的粉丝{{end}}
<span class="space-sidebar-count">{{.SpaceUser.FollowersCount}}</span>
</a>
</nav>
</aside>
<!-- 右侧内容区 -->
<main class="space-main">
<h1 class="space-main-title">{{if eq .ActiveTab "following"}}全部关注{{else}}{{if .IsOwnSpace}}粉丝{{else}}Ta的粉丝{{end}}{{end}}</h1>
{{/* ---- 关注列表 ---- */}}
{{if eq .ActiveTab "following"}}
{{if .FollowingResult}}
{{if .FollowingResult.Accessible}}
{{if eq (len .FollowingResult.Items) 0}}
<div class="space-empty-state">
<p>{{if .IsOwnSpace}}暂未关注任何人,去发现有趣的创作者吧~{{else}}Ta 暂未关注任何人{{end}}</p>
</div>
{{else}}
{{if .IsOwnSpace}}
<!-- 本人:带搜索的用户列表 -->
<div class="space-follow-search">
<input type="text" class="follow-search-input" placeholder="输入关键词">
<button class="follow-search-btn">
<svg viewBox="0 0 24 24" width="18" height="18"><path fill="currentColor" d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>
</button>
</div>
{{end}}
<div class="space-user-grid">
{{range $i, $item := .FollowingResult.Items}}
<div class="space-user-card" data-uid="{{$item.FolloweeID}}">
<a href="/space/{{$item.FolloweeID}}" class="space-user-avatar-wrap">
{{if $item.FolloweeAvatar}}
<img src="{{$item.FolloweeAvatar}}" alt="{{$item.FolloweeUsername}}" class="space-user-avatar-img">
{{else}}
<div class="space-user-avatar-placeholder"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></svg></div>
{{end}}
</a>
<div class="space-user-info">
<a href="/space/{{$item.FolloweeID}}" class="space-user-name">{{$item.FolloweeUsername}}</a>
{{if $item.FolloweeBio}}
<p class="space-user-bio">{{printf "%.50s" $item.FolloweeBio}}</p>
{{end}}
</div>
{{if $.IsOwnSpace}}
<button class="space-follow-btn followed" disabled>已关注</button>
{{else}}
<button class="space-follow-btn" data-uid="{{$item.FolloweeID}}">关注</button>
{{end}}
</div>
{{end}}
</div>
{{end}}
{{else}}
<!-- 隐私关闭 -->
<div class="space-private-empty">
<div class="space-private-illustration">
<svg viewBox="0 0 120 100" width="120" height="100">
<rect x="15" y="25" width="90" height="60" rx="6" fill="#f0f0f0" stroke="#e0e0e0" stroke-width="2"/>
<rect x="25" y="35" width="40" height="6" rx="3" fill="#e0e0e0"/>
<rect x="25" y="47" width="70" height="4" rx="2" fill="#eee"/>
<rect x="25" y="57" width="55" height="4" rx="2" fill="#eee"/>
<circle cx="95" cy="42" r="10" fill="#e8e8e8"/>
<path d="M91 42 L94 45 L99 39" stroke="#bbb" stroke-width="2" fill="none" stroke-linecap="round"/>
<circle cx="82" cy="18" r="8" fill="#fff" stroke="#ddd" stroke-width="1.5"/>
<line x1="86" y1="14" x2="92" y2="10" stroke="#ddd" stroke-width="1.5" stroke-linecap="round"/>
</svg>
</div>
<p class="space-private-text">{{if .IsOwnSpace}}你关闭了展示关注列表~{{else}}Ta 关闭了展示关注列表~{{end}}</p>
{{if .IsOwnSpace}}
<a href="/settings/profile#privacy" class="space-private-setting-btn">去设置开启</a>
{{end}}
</div>
{{end}}
{{else}}
<div class="space-empty-state"><p>暂无数据</p></div>
{{end}}
{{end}}
{{/* ---- 粉丝列表 ---- */}}
{{if eq .ActiveTab "followers"}}
{{if .FollowersResult}}
{{if .FollowersResult.Accessible}}
{{if eq (len .FollowersResult.Items) 0}}
<div class="space-empty-state">
<p>{{if .IsOwnSpace}}暂无粉丝{{else}}Ta 暂无粉丝{{end}}</p>
</div>
{{else}}
{{if .IsOwnSpace}}
<div class="space-follow-search">
<input type="text" class="follow-search-input" placeholder="输入关键词">
<button class="follow-search-btn">
<svg viewBox="0 0 24 24" width="18" height="18"><path fill="currentColor" d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>
</button>
</div>
{{end}}
<div class="space-user-grid">
{{range $i, $item := .FollowersResult.Items}}
<div class="space-user-card" data-uid="{{$item.FollowerID}}">
<a href="/space/{{$item.FollowerID}}" class="space-user-avatar-wrap">
{{if $item.FollowerAvatar}}
<img src="{{$item.FollowerAvatar}}" alt="{{$item.FollowerUsername}}" class="space-user-avatar-img">
{{else}}
<div class="space-user-avatar-placeholder"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></svg></div>
{{end}}
</a>
<div class="space-user-info">
<a href="/space/{{$item.FollowerID}}" class="space-user-name">{{$item.FollowerUsername}}</a>
{{if $item.FollowerBio}}
<p class="space-user-bio">{{printf "%.50s" $item.FollowerBio}}</p>
{{end}}
</div>
{{if not $.IsOwnSpace}}
<button class="space-follow-btn" data-uid="{{$item.FollowerID}}">关注</button>
{{end}}
</div>
{{end}}
</div>
{{end}}
{{else}}
<div class="space-private-empty">
<div class="space-private-illustration">
<svg viewBox="0 0 120 100" width="120" height="100">
<rect x="15" y="25" width="90" height="60" rx="6" fill="#f0f0f0" stroke="#e0e0e0" stroke-width="2"/>
<rect x="25" y="35" width="40" height="6" rx="3" fill="#e0e0e0"/>
<rect x="25" y="47" width="70" height="4" rx="2" fill="#eee"/>
<rect x="25" y="57" width="55" height="4" rx="2" fill="#eee"/>
<circle cx="95" cy="42" r="10" fill="#e8e8e8"/>
<path d="M91 42 L94 45 L99 39" stroke="#bbb" stroke-width="2" fill="none" stroke-linecap="round"/>
</svg>
</div>
<p class="space-private-text">{{if .IsOwnSpace}}你关闭了展示粉丝列表~{{else}}Ta 关闭了展示粉丝列表~{{end}}</p>
{{if .IsOwnSpace}}
<a href="/settings/profile#privacy" class="space-private-setting-btn">去设置开启</a>
{{end}}
</div>
{{end}}
{{else}}
<div class="space-empty-state"><p>暂无数据</p></div>
{{end}}
{{end}}
</main>
{{/* ========== 收藏夹 Tab仅本人 ==========*/}}
{{end}}
{{if eq .ActiveTab "collections"}}
<!-- 左侧收藏夹列表 -->
<aside class="space-sidebar collection-sidebar">
<h2 class="space-sidebar-title collapsible" id="folderSectionToggle">
我创建的收藏夹
<svg class="collapse-arrow" viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"/></svg>
</h2>
<nav class="space-sidebar-nav" id="folder-nav">
<a href="#" class="space-sidebar-link new-folder-btn" id="showNewFolderBtn">
<svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
新建收藏夹
</a>
<div id="new-folder-input" style="display:none;">
<input type="text" id="new-folder-name" placeholder="收藏夹名称" maxlength="50" class="new-folder-input">
<button id="createFolderBtn" class="new-folder-submit">确定</button>
</div>
{{if .FoldersResult}}
{{range $f := .FoldersResult.Folders}}
<a href="/space/{{$.SpaceUser.ID}}?tab=collections&folder={{$f.ID}}"
class="space-sidebar-link{{if eq $.ActiveFolderID $f.ID}} active{{end}}"
data-folder-id="{{$f.ID}}">
<svg class="space-sidebar-icon" viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M17 3H7c-1.1 0-2 .9-2 2v16l7-3 7 3V5c0-1.1-.9-2-2-2zm0 15l-5-2.18L7 18V5h10v13z"/></svg>
{{$f.Name}}
<span class="space-sidebar-count">{{$f.ItemCount}}</span>
</a>
{{end}}
{{end}}
</nav>
</aside>
<!-- 右侧收藏内容 -->
<main class="space-main">
{{if .FoldersResult}}
{{if gt (len .FoldersResult.Folders) 0}}
{{if .ActiveFolder}}
<!-- 收藏夹头信息 -->
<div class="collection-header">
<div class="collection-info-row">
<div>
<h1 class="collection-name">{{.ActiveFolder.Name}}</h1>
<p class="collection-meta">
{{if .ActiveFolder.IsPublic}}公开{{else}}私密{{end}}
· 文章数 {{.FolderItems.Total}}
</p>
</div>
<div class="collection-actions">
<button class="space-action-btn outline small">批量操作</button>
</div>
</div>
</div>
<!-- 文章卡片网格 -->
{{if .FolderItems}}
{{if gt (len .FolderItems.Items) 0}}
<div class="space-article-grid">
{{range $item := .FolderItems.Items}}
<article class="space-article-card">
<a href="/posts/{{$item.PostID}}" class="article-card-link">
<h3 class="article-card-title">{{if $item.PostTitle}}{{$item.PostTitle}}{{else}}无标题文章{{end}}</h3>
</a>
<div class="article-card-footer">
<span class="article-card-author">
<svg viewBox="0 0 24 24" width="12" height="12"><path fill="currentColor" d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></svg>
{{$.SpaceUser.Username}}
</span>
<span class="article-card-time">收藏于{{$item.CreatedAt.Format "01-02 15:04"}}</span>
</div>
</article>
{{end}}
</div>
{{else}}
<div class="space-empty-state">
<p>这个收藏夹还是空的</p>
</div>
{{end}}
{{else}}
<div class="space-empty-state"><p>暂无数据</p></div>
{{end}}
{{else}}
<div class="space-empty-state">
<p>还没有创建收藏夹,点击左侧「新建收藏夹」开始吧~</p>
</div>
{{end}}
{{else}}
<div class="space-empty-state"><p>加载失败</p></div>
{{end}}
{{end}}
</main>
{{/* ========== 设置 Tab仅本人 ==========*/}}
{{end}}
{{if eq .ActiveTab "settings"}}
<main class="space-main-full settings-main">
<h1 class="space-section-title">隐私设置</h1>
<div class="privacy-settings-grid">
<!-- 公开我的收藏 -->
<div class="privacy-row">
<label class="privacy-label">公开我的收藏</label>
<label class="toggle-switch">
<input type="checkbox" id="privacy-collections"{{if .SpaceUser.PublicCollections}} checked{{end}}>
<span class="toggle-slider"></span>
</label>
</div>
<!-- 公开我的生日、个人标签 -->
<div class="privacy-row">
<label class="privacy-label">公开我的生日、个人标签</label>
<label class="toggle-switch">
<input type="checkbox" id="privacy-bio"{{if .SpaceUser.PublicBio}} checked{{end}}>
<span class="toggle-slider"></span>
</label>
</div>
<!-- 公开我的追番追剧 -->
<div class="privacy-row">
<label class="privacy-label">公开我的追番追剧</label>
<label class="toggle-switch">
<input type="checkbox" id="privacy-tracks"{{if .SpaceUser.PublicTracks}} checked{{end}}>
<span class="toggle-slider"></span>
</label>
</div>
<!-- 公开最近投市的视频 -->
<div class="privacy-row">
<label class="privacy-label">公开最近投稿的文章</label>
<label class="toggle-switch">
<input type="checkbox" id="privacy-posts"{{if .SpaceUser.PublicPosts}} checked{{end}}>
<span class="toggle-slider"></span>
</label>
</div>
<!-- 公开最近点赞的视频 -->
<div class="privacy-row">
<label class="privacy-label">公开最近点赞的文章</label>
<label class="toggle-switch">
<input type="checkbox" id="privacy-likes"{{if .SpaceUser.PublicLikes}} checked{{end}}>
<span class="toggle-slider"></span>
</label>
</div>
<!-- 公开我的关注列表 -->
<div class="privacy-row">
<label class="privacy-label">公开我的关注列表</label>
<label class="toggle-switch">
<input type="checkbox" id="privacy-follow-list"{{if .SpaceUser.FollowListPublic}} checked{{end}}>
<span class="toggle-slider"></span>
</label>
</div>
<!-- 公开我的粉丝列表 -->
<div class="privacy-row">
<label class="privacy-label">公开我的粉丝列表</label>
<label class="toggle-switch">
<input type="checkbox" id="privacy-follower-list"{{if .SpaceUser.FollowerListPublic}} checked{{end}}>
<span class="toggle-slider"></span>
</label>
</div>
<!-- 公开学校信息 -->
<div class="privacy-row">
<label class="privacy-label">公开学校信息</label>
<label class="toggle-switch">
<input type="checkbox" id="privacy-school"{{if .SpaceUser.PublicSchool}} checked{{end}}>
<span class="toggle-slider"></span>
</label>
</div>
<!-- 公开最近玩过的游戏 -->
<div class="privacy-row">
<label class="privacy-label">公开最近玩过的游戏</label>
<label class="toggle-switch">
<input type="checkbox" id="privacy-games"{{if .SpaceUser.PublicGames}} checked{{end}}>
<span class="toggle-slider"></span>
</label>
</div>
<!-- 公开拥有的粉丝装扮(仅APP) -->
<div class="privacy-row">
<label class="privacy-label">公开拥有的粉丝装扮(仅APP)</label>
<label class="toggle-switch">
<input type="checkbox" id="privacy-costumes">
<span class="toggle-slider"></span>
</label>
</div>
<!-- 公开我的追漫(仅APP) -->
<div class="privacy-row">
<label class="privacy-label">公开我的追漫(仅APP)</label>
<label class="toggle-switch">
<input type="checkbox" id="privacy-anime"{{if .SpaceUser.PublicAnime}} checked{{end}}>
<span class="toggle-slider"></span>
</label>
</div>
<!-- 公开隐藏的粉丝勋章 -->
<div class="privacy-row">
<label class="privacy-label">公开隐藏的粉丝勋章</label>
<label class="toggle-switch">
<input type="checkbox" id="privacy-medals">
<span class="toggle-slider"></span>
</label>
</div>
<!-- 投稿视频列表中展现直播播放 -->
<div class="privacy-row">
<label class="privacy-label">投稿视频列表中展现直播回放</label>
<label class="toggle-switch">
<input type="checkbox" id="privacy-live-replay">
<span class="toggle-slider"></span>
</label>
</div>
<!-- 投稿视频列表中展现课堂视频 -->
<div class="privacy-row">
<label class="privacy-label">投稿视频列表中展现课堂视频</label>
<label class="toggle-switch">
<input type="checkbox" id="privacy-classroom">
<span class="toggle-slider"></span>
</label>
</div>
<!-- 投稿视频列表中展现月充电专属视频 -->
<div class="privacy-row">
<label class="privacy-label">投稿视频列表中展现月充电专属视频</label>
<label class="toggle-switch">
<input type="checkbox" id="privacy-monthly-video" checked>
<span class="toggle-slider"></span>
</label>
</div>
</div>
</main>
{{end}}
</div><!-- /.space-card-layout -->
</div><!-- /.space-page -->
{{end}}
{{template "layout/footer.html" .}}
<!-- 关注按钮交互 -->
<!-- 顶部关注按钮(所有标签页通用) -->
<script nonce="{{.CSPNonce}}">
(function() {
var topFollowBtn = document.getElementById('space-follow-btn');
if (!topFollowBtn) return;
var topUid = topFollowBtn.getAttribute('data-uid');
var currentUID = parseInt(topFollowBtn.getAttribute('data-current-uid')) || 0;
if (currentUID && parseInt(topUid) !== currentUID) {
fetch('/api/users/' + topUid + '/follow-status')
.then(function(res) { return res.json(); })
.then(function(data) {
if (data && data.success && data.data) {
var s = data.data;
topFollowBtn.textContent = (s.i_follow ? (s.they_follow ? '已互粉' : '已关注') : (s.they_follow ? '回关' : '+ 关注'));
if (s.i_follow) topFollowBtn.classList.add('followed');
}
});
}
topFollowBtn.addEventListener('click', function() {
if (currentUID && parseInt(topUid) === currentUID) {
showToast('不能关注自己', 'warning');
return;
}
if (!currentUID) {
window.location.href = '/auth/login?redirect=/space/' + topUid;
return;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', '/api/users/' + topUid + '/follow', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
var resp = JSON.parse(xhr.responseText);
if (resp.data && resp.data.status) {
var st = resp.data.status;
topFollowBtn.textContent = (st.i_follow ? (st.they_follow ? '已互粉' : '已关注') : (st.they_follow ? '回关' : '+ 关注'));
topFollowBtn.classList.toggle('followed', st.i_follow);
}
} catch(e){}
}
};
xhr.send();
});
})();
</script>
{{if or (eq .ActiveTab "following") (eq .ActiveTab "followers")}}
<script nonce="{{.CSPNonce}}">
(function() {
var currentUID = {{.CurrentUID}} || 0;
var cards = document.querySelectorAll('.space-user-card');
if (!cards.length) return;
// 关注按钮状态文字映射
var labels = {
none: '关注',
following: '已关注',
followBack: '回关',
mutual: '已互粉'
};
function buttonState(status) {
if (status.i_follow && status.they_follow) return 'mutual';
if (status.i_follow) return 'following';
if (status.they_follow) return 'followBack';
return 'none';
}
function updateBtn(btn, status) {
var state = buttonState(status);
btn.textContent = labels[state];
btn.className = 'space-follow-btn';
if (state === 'following' || state === 'mutual') btn.classList.add('followed');
}
// 批量获取并更新每个卡片关注状态(仅非自己)
cards.forEach(function(card) {
var btn = card.querySelector('.space-follow-btn');
if (!btn || btn.disabled) return;
var targetUid = card.getAttribute('data-uid');
fetch('/api/users/' + targetUid + '/follow-status')
.then(function(res) { return res.json(); })
.then(function(data) {
if (data && data.success && data.data) { updateBtn(btn, data.data); }
});
btn.addEventListener('click', function() {
if (currentUID && parseInt(targetUid) === currentUID) {
showToast('不能关注自己');
return;
}
btn.classList.add('waiting');
var xhr = new XMLHttpRequest();
xhr.open('POST', '/api/users/' + targetUid + '/follow', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
btn.classList.remove('waiting');
if (xhr.status === 200) {
try { var resp = JSON.parse(xhr.responseText); if (resp.data && resp.data.status) updateBtn(btn, resp.data.status); } catch(e) {}
}
}
};
xhr.send();
});
});
})();
</script>
{{end}}
<!-- 收藏夹交互脚本 -->
{{if eq .ActiveTab "collections"}}
<script nonce="{{.CSPNonce}}">
function toggleFolderSection(el) {
el.parentElement.querySelector('#folder-nav').classList.toggle('collapsed');
el.classList.toggle('collapsed');
}
function showNewFolderInput() {
document.getElementById('new-folder-input').style.display = '';
document.getElementById('new-folder-name').focus();
}
function createFolder() {
var name = document.getElementById('new-folder-name').value.trim();
if (!name) return;
fetch('/api/folders', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({name: name, is_public: false})
}).then(function(r) { return r.json(); }).then(function(d) {
if (d.success) { location.reload(); } else { showToast(d.message || '创建失败', 'error'); }
});
}
// 事件绑定(替代内联 onclick满足 CSP 无 unsafe-inline
document.addEventListener('DOMContentLoaded', function() {
var toggle = document.getElementById('folderSectionToggle');
if (toggle) toggle.addEventListener('click', function() { toggleFolderSection(this); });
var showBtn = document.getElementById('showNewFolderBtn');
if (showBtn) showBtn.addEventListener('click', function(e) { e.preventDefault(); showNewFolderInput(); });
var createBtn = document.getElementById('createFolderBtn');
if (createBtn) createBtn.addEventListener('click', function() { createFolder(); });
});
// 隐私开关变更保存
document.querySelectorAll('.privacy-settings-grid .toggle-switch input').forEach(function(cb) {
cb.addEventListener('change', function() {
// TODO: 调用 API 保存隐私设置
});
});
</script>
{{end}}
<!-- 设置页交互脚本 -->
{{if eq .ActiveTab "settings"}}
<script nonce="{{.CSPNonce}}">
// 隐私开关变更时自动保存到后端
document.querySelectorAll('#privacy-follow-list, #privacy-follower-list').forEach(function(cb) {
cb.addEventListener('change', function() {
var field = this.id.replace('privacy-', '').replace(/-/g, '_');
var value = this.checked;
fetch('/api/space/privacy', {
method: 'PUT',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({field: field, value: value})
}).then(function(r){return r.json()}).then(function(d){
if(!d.success) { this.checked=!value; showToast(d.message||'保存失败', 'error'); }
}.bind(this));
});
});
</script>
{{end}}
</body>
</html>