- 编辑器投稿页布局优化:标题与编辑器高度动态适配,工具栏与内容区视觉对齐 - 稿件展示页布局优化:MD 渲染区与评论区视觉分离,代码块主题微调 - CSRF 中间件:图像上传端点豁免,解决 Vditor 拖拽/粘贴上传 403 - Post 状态映射、GetGinUser、SaveUploadedFile 提取至 common 包,遵循审计建议 - 新增个人空间功能:/space(需登录)重定向到 /space/:uid,/space/:uid 公开访问 - 空间页模板:参考 B 站布局,展示头像、用户名、个性签名、UID、加入时间及稿件列表 - 导航栏:用户名链接指向 /space,新增「设置」入口 - 分层实现:SpaceController → SpaceService → PostRepo.FindByUserID,严格 ISP 接口隔离
314 lines
6.1 KiB
CSS
314 lines
6.1 KiB
CSS
/* ============================================================
|
||
MetaLab Space Styles — 用户空间页面
|
||
参考 Bilibili 空间布局,轻量版
|
||
============================================================ */
|
||
|
||
/* ---------- Error State ---------- */
|
||
.space-error {
|
||
text-align: center;
|
||
padding: 80px 20px;
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.space-error h1 {
|
||
font-size: 1.5rem;
|
||
color: var(--color-secondary);
|
||
margin-bottom: 1.5rem;
|
||
}
|
||
|
||
.space-error .btn {
|
||
display: inline-block;
|
||
padding: .6rem 1.8rem;
|
||
background: var(--color-accent);
|
||
color: #fff;
|
||
border-radius: var(--radius);
|
||
font-weight: 600;
|
||
transition: var(--transition);
|
||
}
|
||
|
||
.space-error .btn:hover {
|
||
background: #2980b9;
|
||
transform: translateY(-1px);
|
||
}
|
||
|
||
/* ---------- Page Layout ---------- */
|
||
.space-page {
|
||
flex: 1;
|
||
}
|
||
|
||
/* ============================================================
|
||
Header — 用户信息横幅(B站风格)
|
||
============================================================ */
|
||
.space-header {
|
||
background: linear-gradient(135deg, #e8f0f8 0%, #f0f4f8 100%);
|
||
border-bottom: 1px solid var(--color-border);
|
||
padding: 2rem 0;
|
||
}
|
||
|
||
.space-header-inner {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 1.5rem;
|
||
}
|
||
|
||
/* Avatar */
|
||
.space-avatar {
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.space-avatar img {
|
||
width: 80px;
|
||
height: 80px;
|
||
border-radius: 50%;
|
||
object-fit: cover;
|
||
border: 3px solid #fff;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,.1);
|
||
}
|
||
|
||
.space-avatar-placeholder {
|
||
width: 80px;
|
||
height: 80px;
|
||
border-radius: 50%;
|
||
background: var(--color-accent);
|
||
color: #fff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 2rem;
|
||
font-weight: 700;
|
||
border: 3px solid #fff;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,.1);
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
/* Info */
|
||
.space-info {
|
||
min-width: 0;
|
||
}
|
||
|
||
.space-username {
|
||
font-size: 1.5rem;
|
||
font-weight: 700;
|
||
color: var(--color-primary);
|
||
line-height: 1.3;
|
||
margin-bottom: .25rem;
|
||
}
|
||
|
||
.space-bio {
|
||
font-size: .9rem;
|
||
color: var(--color-text-light);
|
||
line-height: 1.5;
|
||
margin-bottom: .5rem;
|
||
word-break: break-word;
|
||
}
|
||
|
||
.space-meta {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: .3rem;
|
||
font-size: .8rem;
|
||
color: var(--color-secondary);
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.space-divider {
|
||
color: var(--color-border);
|
||
}
|
||
|
||
/* ============================================================
|
||
Stats Bar
|
||
============================================================ */
|
||
.space-stats {
|
||
display: flex;
|
||
gap: 2rem;
|
||
padding: 1rem 0;
|
||
border-bottom: 1px solid var(--color-border);
|
||
margin-bottom: 1.5rem;
|
||
}
|
||
|
||
.space-stat-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: .15rem;
|
||
}
|
||
|
||
.space-stat-num {
|
||
font-size: 1.4rem;
|
||
font-weight: 700;
|
||
color: var(--color-primary);
|
||
}
|
||
|
||
.space-stat-label {
|
||
font-size: .8rem;
|
||
color: var(--color-secondary);
|
||
}
|
||
|
||
/* ============================================================
|
||
Content Section — 稿件列表
|
||
============================================================ */
|
||
.space-content {
|
||
padding-bottom: 3rem;
|
||
}
|
||
|
||
.space-section {
|
||
margin-top: .5rem;
|
||
}
|
||
|
||
.space-section-title {
|
||
font-size: 1.1rem;
|
||
font-weight: 600;
|
||
color: var(--color-primary);
|
||
margin-bottom: 1rem;
|
||
padding-bottom: .5rem;
|
||
border-bottom: 2px solid var(--color-accent);
|
||
display: inline-block;
|
||
}
|
||
|
||
/* ---------- Post Card ---------- */
|
||
.space-posts-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: .75rem;
|
||
}
|
||
|
||
.space-post-card {
|
||
display: flex;
|
||
align-items: center;
|
||
background: var(--color-surface);
|
||
border: 1px solid var(--color-border);
|
||
border-radius: var(--radius);
|
||
padding: 1rem 1.25rem;
|
||
transition: box-shadow .2s ease, border-color .2s ease;
|
||
}
|
||
|
||
.space-post-card:hover {
|
||
box-shadow: 0 2px 12px rgba(0,0,0,.06);
|
||
border-color: #ccc;
|
||
}
|
||
|
||
.space-post-main {
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
.space-post-title {
|
||
font-size: 1rem;
|
||
font-weight: 600;
|
||
margin-bottom: .3rem;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.space-post-title a {
|
||
color: var(--color-primary);
|
||
transition: var(--transition);
|
||
}
|
||
|
||
.space-post-title a:hover {
|
||
color: var(--color-accent);
|
||
}
|
||
|
||
.space-post-excerpt {
|
||
font-size: .85rem;
|
||
color: var(--color-text-light);
|
||
line-height: 1.5;
|
||
margin-bottom: .5rem;
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.space-post-meta {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: .75rem;
|
||
font-size: .75rem;
|
||
color: var(--color-secondary);
|
||
}
|
||
|
||
.space-post-status {
|
||
color: var(--color-accent);
|
||
font-weight: 500;
|
||
}
|
||
|
||
/* ---------- Empty State ---------- */
|
||
.empty-state {
|
||
text-align: center;
|
||
padding: 3rem 1rem;
|
||
color: var(--color-secondary);
|
||
font-size: .95rem;
|
||
}
|
||
|
||
/* ---------- Pagination ---------- */
|
||
.pagination {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
gap: 1rem;
|
||
margin-top: 2rem;
|
||
font-size: .9rem;
|
||
}
|
||
|
||
.page-link {
|
||
padding: .4rem 1rem;
|
||
border: 1px solid var(--color-border);
|
||
border-radius: var(--radius);
|
||
color: var(--color-accent);
|
||
transition: var(--transition);
|
||
}
|
||
|
||
.page-link:hover {
|
||
border-color: var(--color-accent);
|
||
background: rgba(52, 152, 219, .05);
|
||
}
|
||
|
||
.page-info {
|
||
color: var(--color-secondary);
|
||
}
|
||
|
||
/* ============================================================
|
||
Responsive
|
||
============================================================ */
|
||
@media (max-width: 768px) {
|
||
.space-header {
|
||
padding: 1.5rem 0;
|
||
}
|
||
|
||
.space-header-inner {
|
||
flex-direction: column;
|
||
text-align: center;
|
||
gap: .75rem;
|
||
}
|
||
|
||
.space-avatar img,
|
||
.space-avatar-placeholder {
|
||
width: 64px;
|
||
height: 64px;
|
||
font-size: 1.5rem;
|
||
}
|
||
|
||
.space-username {
|
||
font-size: 1.25rem;
|
||
}
|
||
|
||
.space-meta {
|
||
justify-content: center;
|
||
}
|
||
|
||
.space-stats {
|
||
justify-content: center;
|
||
}
|
||
|
||
.space-post-card {
|
||
padding: .85rem 1rem;
|
||
}
|
||
|
||
.space-post-title {
|
||
font-size: .95rem;
|
||
}
|
||
}
|