This repository has been archived on 2026-06-21. You can view files and clone it, but cannot push or open issues or pull requests.
Files
MetaLab/templates/MetaLab-2026/static/css/common.css
Victor_Jay fdb636f98f feat: 实现积分与等级系统 + 签到功能 + 下拉菜单优化
- User 模型增加 exp 字段,等级规则 Lv0-Lv6
- 新增签到记录(UserCheckIn)与任务记录(UserTask)模型,唯一索引防重
- 自动签到:AuthMiddleware 验证会话后,基于 Asia/Shanghai 自然日自动签到 +5 经验
- 手动签到:下拉菜单"签到"按钮兜底,已签到显示"今日已签到"并禁用
- 首次任务经验:上传头像/设置用户名/设置个性签名各 +10,审核通过与直接更新均触发
- 经验值变动后自动比对等级,升级时通过通知系统发送"恭喜提升至 LvX"
- 下拉菜单重构:顶部头像+用户名+LvX 等级标签,菜单项增加左侧图标,优化布局样式
- 新增 API:POST /api/level/checkin、GET /api/level/info
2026-05-31 20:58:14 +08:00

505 lines
9.8 KiB
CSS
Raw 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.

/* ============================================================
MetaLab Common Styles — 全站共享样式Reset / 变量 / 导航 / 页脚)
每个页面加载此文件后,按需加载页面专属 CSS
============================================================ */
:root {
--color-bg: #f8f9fa;
--color-surface: #fff;
--color-primary: #2c3e50;
--color-secondary: #7f8c8d;
--color-accent: #3498db;
--color-danger: #e74c3c;
--color-border: #e0e0e0;
--color-text: #333;
--color-text-light: #666;
--shadow: 0 4px 12px rgba(0,0,0,.08);
--radius: 8px;
--transition: all .3s ease;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
}
/* ---------- Reset ---------- */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
height: 100%;
}
body {
background: var(--color-bg);
color: var(--color-text);
line-height: 1.6;
overflow-x: hidden;
display: flex;
flex-direction: column;
min-height: 100vh;
}
/* 主内容区撑满剩余空间,实现 sticky footer */
body > .container {
flex: 1;
}
a {
text-decoration: none;
color: inherit;
}
/* ---------- Layout ---------- */
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.icon {
width: 1em;
height: 1em;
vertical-align: -.125em;
display: inline-block;
flex-shrink: 0;
}
/* ---------- Header / Nav ---------- */
header {
background: var(--color-surface);
box-shadow: var(--shadow);
position: sticky;
top: 0;
z-index: 1000;
}
.nav-container {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1200px;
margin: 0 auto;
padding: .6rem 2rem;
}
.logo {
font-size: 1.4rem;
font-weight: 700;
color: var(--color-primary);
flex-shrink: 0;
}
.logo span {
color: var(--color-accent);
}
.nav-links {
display: flex;
align-items: center;
list-style: none;
gap: 1.5rem;
}
.nav-links li {
display: flex;
align-items: center;
}
.nav-links a {
display: flex;
align-items: center;
font-weight: 500;
padding: .5rem 0;
position: relative;
transition: var(--transition);
}
.nav-links a:hover,
.nav-links a.nav-active {
color: var(--color-accent);
}
.nav-links a::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 2px;
background: var(--color-accent);
transition: width .3s ease;
}
.nav-links a:hover::after,
.nav-links a.nav-active::after {
width: 100%;
}
.nav-login {
color: var(--color-accent) !important;
font-weight: 600 !important;
}
/* ---------- Nav Contribute ---------- */
.nav-contribute {
display: flex;
align-items: center;
gap: .25rem;
color: var(--color-accent) !important;
font-weight: 600 !important;
}
.nav-contribute .icon {
width: 16px;
height: 16px;
}
/* ---------- Nav Envelope ---------- */
.nav-envelope {
position: relative;
display: flex;
align-items: center;
justify-content: center;
padding: 4px;
border-radius: 50%;
transition: background .15s ease;
}
.nav-links .nav-envelope::after,
.nav-links .nav-envelope:hover::after {
display: none;
}
.nav-envelope:hover {
background: rgba(52, 152, 219, .08);
}
.nav-envelope-icon {
width: 20px;
height: 20px;
display: block;
}
.nav-envelope-badge {
position: absolute;
top: 0;
right: -2px;
min-width: 16px;
height: 16px;
padding: 0 4px;
font-size: .65rem;
font-weight: 700;
color: #fff;
background: var(--color-danger);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
line-height: 1;
}
/* ---------- Nav Avatar Dropdown ---------- */
.nav-avatar-wrapper {
position: relative;
}
.nav-avatar-link {
display: flex !important;
align-items: center;
padding: 2px !important;
}
.nav-links .nav-avatar-link::after,
.nav-links .nav-avatar-link:hover::after {
display: none;
}
.nav-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
object-fit: cover;
border: 2px solid var(--color-border);
transition: border-color .2s ease;
}
.nav-avatar-default {
display: flex;
align-items: center;
justify-content: center;
background: var(--color-accent);
color: #fff;
font-size: .85rem;
font-weight: 600;
object-fit: unset;
}
.nav-avatar-wrapper:hover .nav-avatar {
border-color: var(--color-accent);
}
.nav-dropdown {
position: absolute;
top: calc(100% + 8px);
right: 0;
min-width: 160px;
background: var(--color-surface);
border-radius: var(--radius);
box-shadow: 0 4px 16px rgba(0,0,0,.12);
opacity: 0;
visibility: hidden;
transform: translateY(-4px);
transition: opacity .2s ease, visibility .2s ease, transform .2s ease;
overflow: hidden;
}
.nav-avatar-wrapper:hover .nav-dropdown {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.nav-dropdown-header {
display: flex;
align-items: center;
gap: .75rem;
padding: 1rem;
border-bottom: 1px solid var(--color-border);
}
.nav-dropdown-avatar {
width: 48px;
height: 48px;
border-radius: 50%;
overflow: hidden;
flex-shrink: 0;
background: var(--color-accent);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 1.1rem;
font-weight: 600;
}
.nav-dropdown-avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}
.nav-dropdown-meta {
min-width: 0;
overflow: hidden;
}
.nav-dropdown-username {
font-weight: 600;
font-size: .95rem;
color: var(--color-text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.nav-dropdown-level {
display: inline-block;
margin-top: .2rem;
padding: .1rem .5rem;
border-radius: 4px;
background: linear-gradient(135deg, #ff6b6b, #feca57);
color: #fff;
font-size: .75rem;
font-weight: 700;
line-height: 1.4;
}
.nav-dropdown-item {
display: flex !important;
align-items: center;
gap: .6rem;
padding: .65rem 1rem !important;
font-size: .9rem;
color: var(--color-text-light) !important;
transition: background .15s ease, color .15s ease;
}
.nav-dropdown-item::after {
display: none !important;
}
.nav-dropdown-item:hover {
background: var(--color-bg);
color: var(--color-accent) !important;
}
.nav-dropdown-item.nav-logout:hover {
color: var(--color-danger) !important;
}
.nav-dropdown-icon {
width: 18px;
height: 18px;
flex-shrink: 0;
opacity: .7;
}
.nav-dropdown-item:hover .nav-dropdown-icon {
opacity: 1;
}
.nav-dropdown-item.disabled {
opacity: .5;
cursor: not-allowed;
pointer-events: none;
}
.nav-dropdown-item.disabled:hover {
background: transparent;
color: var(--color-text-light) !important;
}
.mobile-menu-btn {
display: none;
background: none;
border: none;
font-size: 1.5rem;
color: var(--color-primary);
cursor: pointer;
}
/* ---------- Maintenance Banner ---------- */
.maintenance-banner {
text-align: center;
padding: .6rem 1rem;
background: #fef3cd;
border-bottom: 1px solid #f0d48a;
color: #856404;
font-size: .9rem;
font-weight: 500;
}
.maintenance-banner-icon {
font-size: 1rem;
margin-right: .4rem;
}
/* ---------- Contact / Footer ---------- */
.contact-bar {
text-align: center;
padding: .6rem 0;
background: #e8f0f8;
border-top: 1px solid var(--color-border);
font-size: .95rem;
color: var(--color-text-light);
}
.contact-bar a {
color: var(--color-accent);
font-weight: 600;
transition: var(--transition);
}
.contact-bar a:hover {
color: #2980b9;
text-decoration: underline;
}
footer {
background: var(--color-primary);
color: #bdc3c7;
padding: .8rem 0;
flex-shrink: 0;
}
.footer-content {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.copyright {
font-size: .9rem;
color: #95a5a6;
width: 100%;
}
/* ---------- Scroll-to-top ---------- */
.scroll-top-btn {
position: fixed;
bottom: 1.5rem;
right: 1.5rem;
width: 44px;
height: 44px;
border-radius: 50%;
background: var(--color-accent);
color: #fff;
border: none;
box-shadow: 0 4px 12px rgba(52,152,219,.35);
cursor: pointer;
font-size: 1.1rem;
display: flex;
align-items: center;
justify-content: center;
z-index: 999;
opacity: 0;
visibility: hidden;
transform: translateY(10px);
transition: opacity .3s ease, visibility .3s ease, transform .3s ease;
}
.scroll-top-btn.visible {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.scroll-top-btn:hover {
background: #2980b9;
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(52,152,219,.45);
}
/* ---------- Responsive (共享:导航) ---------- */
@media (max-width: 768px) {
.nav-container {
padding: .6rem 1rem;
}
.nav-links {
display: none;
position: absolute;
top: 100%;
left: 0;
width: 100%;
background: var(--color-surface);
flex-direction: column;
padding: 1rem;
box-shadow: 0 10px 15px rgba(0,0,0,.1);
}
.nav-links.active {
display: flex;
}
.nav-links li {
justify-content: center;
}
.nav-avatar-wrapper {
justify-content: center;
}
.nav-dropdown {
position: static;
opacity: 1;
visibility: visible;
transform: none;
box-shadow: none;
border-top: 1px solid var(--color-border);
border-radius: 0;
margin-top: .5rem;
}
.mobile-menu-btn {
display: block;
}
}