Music Creation Page: - Vinyl 3D flip to view lyrics, tonearm animation, glow rotation effect - Circular SVG progress ring, speech bubble feedback, confirm dialog - Playlist modal, free creation input, lyrics formatting optimization - MiniMax API real music generation with SSE streaming progress Backend: - FastAPI proxy server.py for MiniMax API calls - Music + lyrics file persistence to Capybara music/ directory - GET /api/playlist endpoint for auto-building playlist from files UI/UX Refinements: - frontend-design skill compliance across all pages - Glassmorphism effects, modal interactions, scroll tap prevention - iPhone 12 Pro responsive layout (390x844) Flutter Development Preparation: - Installed flutter-expert skill with 6 reference docs - Added 5 Cursor Rules: official Flutter, clean architecture, UI performance, testing, Dart standards Assets: - 9 Capybara music MP3 files + lyrics TXT files - MiniMax API documentation Co-authored-by: Cursor <cursoragent@cursor.com>
399 lines
14 KiB
HTML
399 lines
14 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport"
|
||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||
<title>Airhub - 消息通知</title>
|
||
<link rel="stylesheet" href="styles.css">
|
||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=DM+Sans:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||
<style>
|
||
.page-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 16px 20px;
|
||
padding-top: calc(env(safe-area-inset-top, 20px) + 48px);
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
position: absolute;
|
||
top: 0;
|
||
z-index: 10;
|
||
}
|
||
|
||
.back-btn {
|
||
background: rgba(255, 255, 255, 0.25);
|
||
backdrop-filter: blur(8px);
|
||
border: 1px solid rgba(255, 255, 255, 0.4);
|
||
width: 44px;
|
||
height: 44px;
|
||
border-radius: 22px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #1F2937;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
}
|
||
|
||
.back-btn:active {
|
||
transform: scale(0.92);
|
||
}
|
||
|
||
.page-title {
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
color: #1F2937;
|
||
}
|
||
|
||
/* Gradient Mask Scroll Standard */
|
||
.content-scroll {
|
||
padding: calc(env(safe-area-inset-top, 20px) + 120px) 20px 40px;
|
||
overflow-y: auto;
|
||
flex: 1;
|
||
width: 100%;
|
||
height: 100%;
|
||
box-sizing: border-box;
|
||
position: relative;
|
||
z-index: 2;
|
||
scrollbar-width: none;
|
||
-webkit-mask-image: linear-gradient(to bottom, transparent 0px, transparent 100px, black 130px, black 100%);
|
||
mask-image: linear-gradient(to bottom, transparent 0px, transparent 100px, black 130px, black 100%);
|
||
}
|
||
|
||
.content-scroll::-webkit-scrollbar {
|
||
display: none;
|
||
}
|
||
|
||
/* Notification List Styles */
|
||
.notification-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 12px;
|
||
padding-bottom: 40px;
|
||
}
|
||
|
||
/* 通知卡片容器 */
|
||
.notification-item {
|
||
background: rgba(255, 255, 255, 0.7);
|
||
backdrop-filter: blur(10px);
|
||
border-radius: 16px;
|
||
border: 1px solid rgba(255, 255, 255, 0.4);
|
||
overflow: hidden;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.notification-item.open {
|
||
background: rgba(255, 255, 255, 0.85);
|
||
}
|
||
|
||
/* 通知卡片头部(可点击) */
|
||
.notification-header {
|
||
display: flex;
|
||
gap: 14px;
|
||
padding: 16px;
|
||
cursor: pointer;
|
||
transition: background 0.2s;
|
||
}
|
||
|
||
.notification-header:active {
|
||
background: rgba(255, 255, 255, 0.9);
|
||
}
|
||
|
||
.notif-icon-box {
|
||
width: 40px;
|
||
height: 40px;
|
||
border-radius: 20px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 20px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.notif-icon-box.system {
|
||
background: #EFF6FF;
|
||
color: #3B82F6;
|
||
}
|
||
|
||
.notif-icon-box.activity {
|
||
background: #FFF7ED;
|
||
color: #F97316;
|
||
}
|
||
|
||
.notif-content {
|
||
flex: 1;
|
||
}
|
||
|
||
.notif-header-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 4px;
|
||
}
|
||
|
||
.notif-title {
|
||
font-size: 15px;
|
||
font-weight: 600;
|
||
color: #1F2937;
|
||
}
|
||
|
||
.notif-time {
|
||
font-size: 12px;
|
||
color: #9CA3AF;
|
||
}
|
||
|
||
.notif-desc {
|
||
font-size: 13px;
|
||
color: #6B7280;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.notif-arrow {
|
||
color: #D1D5DB;
|
||
font-size: 18px;
|
||
transition: transform 0.3s ease;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.notification-item.open .notif-arrow {
|
||
transform: rotate(90deg);
|
||
}
|
||
|
||
.notif-dot {
|
||
width: 8px;
|
||
height: 8px;
|
||
background: #EF4444;
|
||
border-radius: 50%;
|
||
margin-top: 6px;
|
||
display: none;
|
||
}
|
||
|
||
.notification-item.unread .notif-dot {
|
||
display: block;
|
||
}
|
||
|
||
/* 展开的详情区域 */
|
||
.notification-detail {
|
||
max-height: 0;
|
||
overflow: hidden;
|
||
transition: max-height 0.35s ease, padding 0.35s ease;
|
||
background: rgba(249, 250, 251, 0.5);
|
||
border-top: 0 solid rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
.notification-item.open .notification-detail {
|
||
max-height: 600px;
|
||
border-top-width: 1px;
|
||
}
|
||
|
||
.detail-content {
|
||
padding: 0 20px;
|
||
font-size: 14px;
|
||
color: #374151;
|
||
line-height: 1.7;
|
||
}
|
||
|
||
.notification-item.open .detail-content {
|
||
padding: 20px;
|
||
}
|
||
|
||
.detail-content p {
|
||
margin-bottom: 14px;
|
||
}
|
||
|
||
.detail-content strong {
|
||
color: #111827;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.detail-content ul {
|
||
margin-bottom: 14px;
|
||
padding-left: 20px;
|
||
}
|
||
|
||
.detail-content li {
|
||
margin-bottom: 6px;
|
||
list-style-type: none;
|
||
position: relative;
|
||
}
|
||
|
||
.detail-content li::before {
|
||
content: "•";
|
||
color: #FFB088;
|
||
font-weight: bold;
|
||
display: inline-block;
|
||
width: 1em;
|
||
margin-left: -1em;
|
||
}
|
||
|
||
.detail-content img {
|
||
max-width: 100%;
|
||
border-radius: 12px;
|
||
margin: 8px 0 16px;
|
||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body>
|
||
<div class="app-container">
|
||
<!-- 动态渐变背景 -->
|
||
<div class="gradient-bg">
|
||
<div class="gradient-layer layer-1"></div>
|
||
<div class="gradient-layer layer-2"></div>
|
||
</div>
|
||
|
||
<!-- Header -->
|
||
<header class="page-header">
|
||
<button class="back-btn" onclick="history.back()">
|
||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M15 18l-6-6 6-6" />
|
||
</svg>
|
||
</button>
|
||
<span class="page-title">消息通知</span>
|
||
<div style="width: 44px;"></div>
|
||
</header>
|
||
|
||
<!-- Main Content -->
|
||
<main class="content-scroll">
|
||
<div class="notification-list">
|
||
|
||
<!-- 消息 1 (未读) -->
|
||
<div class="notification-item unread" id="notif-1">
|
||
<div class="notification-header" onclick="toggleNotif(1)">
|
||
<div class="notif-icon-box system">
|
||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||
stroke-width="2">
|
||
<path
|
||
d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z">
|
||
</path>
|
||
<line x1="12" y1="9" x2="12" y2="13"></line>
|
||
<line x1="12" y1="17" x2="12.01" y2="17"></line>
|
||
</svg>
|
||
</div>
|
||
<div class="notif-content">
|
||
<div class="notif-header-row">
|
||
<span class="notif-title">系统更新</span>
|
||
<span class="notif-time">10:30</span>
|
||
</div>
|
||
<div class="notif-desc">Airhub V1.2.0 版本更新已准备就绪</div>
|
||
</div>
|
||
<span class="notif-arrow">›</span>
|
||
<div class="notif-dot"></div>
|
||
</div>
|
||
<div class="notification-detail">
|
||
<div class="detail-content">
|
||
<p><strong>Airhub V1.2.0 版本更新说明:</strong></p>
|
||
<ul>
|
||
<li>新增<strong>"喂养指南"</strong>功能,现在您可以查看详细的电子宠物养成手册了。</li>
|
||
<li>优化了设备连接的稳定性,修复了部分机型搜索不到设备的问题。</li>
|
||
<li>提升了整体界面的流畅度,增加了更多微交互动画。</li>
|
||
</ul>
|
||
<p>建议您连接 Wi-Fi 后进行更新,以获得最佳体验。</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 消息 2 -->
|
||
<div class="notification-item" id="notif-2">
|
||
<div class="notification-header" onclick="toggleNotif(2)">
|
||
<div class="notif-icon-box activity">
|
||
<span style="font-size: 18px;">🎁</span>
|
||
</div>
|
||
<div class="notif-content">
|
||
<div class="notif-header-row">
|
||
<span class="notif-title">新春活动</span>
|
||
<span class="notif-time">昨天</span>
|
||
</div>
|
||
<div class="notif-desc">领取您的新春限定水豚皮肤"招财进宝"</div>
|
||
</div>
|
||
<span class="notif-arrow">›</span>
|
||
</div>
|
||
<div class="notification-detail">
|
||
<div class="detail-content">
|
||
<p>🎉 <strong>新春限定皮肤上线啦!</strong></p>
|
||
<p>为了庆祝即将到来的春节,我们特别推出了水豚的"招财进宝"限定皮肤。</p>
|
||
<img src="https://images.unsplash.com/photo-1549608276-5786777e6587?q=80&w=600&auto=format&fit=crop"
|
||
alt="Event Image">
|
||
<p><strong>活动亮点:</strong></p>
|
||
<ul>
|
||
<li>限定版红色唐装外观</li>
|
||
<li>专属的春节互动音效</li>
|
||
<li>限时免费领取的节庆道具</li>
|
||
</ul>
|
||
<p><strong>活动截止日期:</strong> 2月15日</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 消息 3 -->
|
||
<div class="notification-item" id="notif-3">
|
||
<div class="notification-header" onclick="toggleNotif(3)">
|
||
<div class="notif-icon-box system">
|
||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||
stroke-width="2">
|
||
<path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
|
||
<circle cx="8.5" cy="7" r="4"></circle>
|
||
<line x1="20" y1="8" x2="20" y2="14"></line>
|
||
<line x1="23" y1="11" x2="17" y2="11"></line>
|
||
</svg>
|
||
</div>
|
||
<div class="notif-content">
|
||
<div class="notif-header-row">
|
||
<span class="notif-title">新设备绑定</span>
|
||
<span class="notif-time">1月20日</span>
|
||
</div>
|
||
<div class="notif-desc">您的新设备"Airhub_5G"已成功绑定</div>
|
||
</div>
|
||
<span class="notif-arrow">›</span>
|
||
</div>
|
||
<div class="notification-detail">
|
||
<div class="detail-content">
|
||
<p>恭喜!您已成功绑定新设备 <strong>Airhub_5G</strong>。</p>
|
||
<p>接下来的几步可以帮助您快速上手:</p>
|
||
<ul>
|
||
<li>前往<strong>角色记忆</strong>页面,注入您喜欢的角色人格。</li>
|
||
<li>进入设置页面配置您的偏好设置。</li>
|
||
<li>查看帮助中心的入门指南,解锁更多互动玩法。</li>
|
||
</ul>
|
||
<p>祝您开启一段奇妙的 AI 陪伴旅程!</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</main>
|
||
</div>
|
||
|
||
<script>
|
||
function toggleNotif(id) {
|
||
const item = document.getElementById('notif-' + id);
|
||
const wasOpen = item.classList.contains('open');
|
||
|
||
// 关闭其他打开的项 (可选:保持手风琴效果)
|
||
document.querySelectorAll('.notification-item.open').forEach(el => {
|
||
if (el !== item) el.classList.remove('open');
|
||
});
|
||
|
||
// 切换当前项
|
||
item.classList.toggle('open');
|
||
|
||
// 标记已读
|
||
if (item.classList.contains('unread')) {
|
||
item.classList.remove('unread');
|
||
}
|
||
|
||
// 如果是展开操作,平滑滚动到该卡片顶部
|
||
if (!wasOpen) {
|
||
setTimeout(() => {
|
||
item.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||
}, 50);
|
||
}
|
||
}
|
||
</script>
|
||
</body>
|
||
|
||
</html> |