- 重写 space/index.html:左右分栏,左侧导航栏 + 右侧卡片网格 - 自己空间:显示全部关注用户卡片(头像/用户名/简介/已关注标签)+ 设置入口 - 他人空间:简化侧栏(Ta的关注/粉丝),隐私关闭时显示空状态插图 - Model UserFollow 新增头像/简介联表字段 - Repository ListFollowing/ListFollowers SELECT 增加 avatar/bio - Controller ShowSpace 注入 FollowService,获取关注列表数据 - space.css 完全重写为卡片网格布局 + 响应式适配 - follow.css 清理旧 .follow-btn/.follow-links 无用样式
263 lines
12 KiB
HTML
263 lines
12 KiB
HTML
{{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">
|
|
|
|
<!-- ===== 自己的空间:卡片式关注列表 ===== -->
|
|
{{if .IsOwnSpace}}
|
|
<div class="space-card-layout">
|
|
<!-- 左侧导航 -->
|
|
<aside class="space-sidebar">
|
|
<h2 class="space-sidebar-title">我的关注</h2>
|
|
<nav class="space-sidebar-nav">
|
|
<a href="/space/{{.SpaceUser.ID}}/following" class="space-sidebar-link active">
|
|
<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>
|
|
全部关注
|
|
<span class="space-sidebar-count">{{.SpaceUser.FollowingCount}}</span>
|
|
</a>
|
|
<a href="/space/{{.SpaceUser.ID}}/followers" class="space-sidebar-link">
|
|
<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>
|
|
粉丝
|
|
<span class="space-sidebar-count">{{.SpaceUser.FollowersCount}}</span>
|
|
</a>
|
|
</nav>
|
|
{{if gt .SpaceUser.FollowingCount 0}}
|
|
<p class="space-sidebar-hint">显示全部 {{.SpaceUser.FollowingCount}} 个</p>
|
|
{{end}}
|
|
</aside>
|
|
|
|
<!-- 右侧内容区 -->
|
|
<main class="space-main">
|
|
<!-- 标题栏 -->
|
|
<div class="space-main-header">
|
|
<h1 class="space-main-title">全部关注</h1>
|
|
<a href="/settings/profile#privacy" class="space-settings-link">设置</a>
|
|
</div>
|
|
|
|
{{if .FollowingResult}}
|
|
{{if .FollowingResult.Accessible}}
|
|
|
|
{{if eq (len .FollowingResult.Items) 0}}
|
|
<div class="space-empty-state">
|
|
<p>暂未关注任何人,去发现有趣的创作者吧~</p>
|
|
</div>
|
|
{{else}}
|
|
<!-- 用户卡片网格 -->
|
|
<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">{{slice $item.FolloweeUsername 0 1}}</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>
|
|
<button class="space-follow-btn followed" data-uid="{{$item.FolloweeID}}" disabled>已关注</button>
|
|
</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">你关闭了展示关注列表~</p>
|
|
<a href="/settings/profile#privacy" class="space-private-setting-btn">去设置开启</a>
|
|
</div>
|
|
{{end}}
|
|
{{end}}
|
|
</main>
|
|
</div>
|
|
|
|
<!-- ===== 别人的空间:简化视图 ===== -->
|
|
{{else}}
|
|
<div class="space-card-layout">
|
|
<!-- 左侧导航(简化版) -->
|
|
<aside class="space-sidebar">
|
|
<h2 class="space-sidebar-title">Ta的关注</h2>
|
|
<nav class="space-sidebar-nav">
|
|
{{if .FollowingResult}}
|
|
<div class="space-sidebar-link active{{if not .FollowingResult.Accessible}} disabled{{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>
|
|
全部关注
|
|
<span class="space-sidebar-count">{{.SpaceUser.FollowingCount}}</span>
|
|
</div>
|
|
{{end}}
|
|
<a href="/space/{{.SpaceUser.ID}}/followers" class="space-sidebar-link">
|
|
<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>
|
|
Ta的粉丝
|
|
<span class="space-sidebar-count">{{.SpaceUser.FollowersCount}}</span>
|
|
</a>
|
|
</nav>
|
|
</aside>
|
|
|
|
<!-- 右侧内容区 -->
|
|
<main class="space-main">
|
|
<h1 class="space-main-title">全部关注</h1>
|
|
|
|
{{if .FollowingResult}}
|
|
{{if .FollowingResult.Accessible}}
|
|
|
|
{{if eq (len .FollowingResult.Items) 0}}
|
|
<div class="space-empty-state">
|
|
<p>Ta 暂未关注任何人</p>
|
|
</div>
|
|
{{else}}
|
|
<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">{{slice $item.FolloweeUsername 0 1}}</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>
|
|
<button class="space-follow-btn" data-uid="{{$item.FolloweeID}}">关注</button>
|
|
</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">Ta 关闭了展示关注列表~</p>
|
|
</div>
|
|
{{end}}
|
|
{{else}}
|
|
<div class="space-empty-state">
|
|
<p>暂无数据</p>
|
|
</div>
|
|
{{end}}
|
|
</main>
|
|
</div>
|
|
{{end}}
|
|
|
|
</div>
|
|
{{end}}
|
|
|
|
{{template "layout/footer.html" .}}
|
|
|
|
<script src="/static/js/common.js?v={{assetV "/static/js/common.js"}}"></script>
|
|
{{if not .IsOwnSpace}}
|
|
<!-- 别人空间:关注按钮交互 -->
|
|
<script>
|
|
(function() {
|
|
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');
|
|
}
|
|
|
|
// 批量获取关注状态
|
|
var uids = [];
|
|
cards.forEach(function(card) {
|
|
uids.push(card.getAttribute('data-uid'));
|
|
});
|
|
|
|
// 逐个查询状态
|
|
cards.forEach(function(card) {
|
|
var btn = card.querySelector('.space-follow-btn');
|
|
if (!btn) 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() {
|
|
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}}
|
|
</body>
|
|
</html>
|