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>
361 lines
11 KiB
HTML
361 lines
11 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>
|
||
/* 复用 device-control 布局 */
|
||
.profile-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;
|
||
}
|
||
|
||
.profile-title {
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
color: #1F2937;
|
||
}
|
||
|
||
/* 头部按钮 - 通知铃铛 */
|
||
.icon-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;
|
||
transition: all 0.2s;
|
||
position: relative;
|
||
}
|
||
|
||
.icon-btn:active {
|
||
transform: scale(0.92);
|
||
background: rgba(255, 255, 255, 0.4);
|
||
}
|
||
|
||
.notification-dot {
|
||
position: absolute;
|
||
top: 10px;
|
||
right: 10px;
|
||
width: 8px;
|
||
height: 8px;
|
||
background: #EF4444;
|
||
border-radius: 50%;
|
||
border: 2px solid white;
|
||
}
|
||
|
||
/* 主内容区 */
|
||
.profile-content {
|
||
padding: calc(env(safe-area-inset-top, 20px) + 100px) 20px 140px;
|
||
overflow-y: auto;
|
||
height: 100%;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
/* 用户信息卡片 */
|
||
.user-card {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16px;
|
||
padding: 20px;
|
||
background: rgba(255, 255, 255, 0.8);
|
||
backdrop-filter: blur(20px);
|
||
border-radius: 20px;
|
||
margin-bottom: 20px;
|
||
box-shadow: 0 4px 20px rgba(139, 94, 60, 0.08);
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
}
|
||
|
||
.user-card:active {
|
||
transform: scale(0.98);
|
||
background: rgba(255, 255, 255, 0.95);
|
||
}
|
||
|
||
.user-avatar {
|
||
width: 64px;
|
||
height: 64px;
|
||
border-radius: 32px;
|
||
background: linear-gradient(135deg, #ECCFA8, #C99672);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.user-avatar img {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
}
|
||
|
||
.user-info {
|
||
flex: 1;
|
||
}
|
||
|
||
.user-name {
|
||
font-size: 20px;
|
||
font-weight: 600;
|
||
color: #1F2937;
|
||
margin-bottom: 4px;
|
||
}
|
||
|
||
.user-id {
|
||
font-size: 13px;
|
||
color: #9CA3AF;
|
||
}
|
||
|
||
.arrow-icon {
|
||
color: #D1D5DB;
|
||
font-size: 20px;
|
||
}
|
||
|
||
/* 菜单列表 */
|
||
.menu-list {
|
||
background: rgba(255, 255, 255, 0.8);
|
||
backdrop-filter: blur(20px);
|
||
border-radius: 20px;
|
||
overflow: hidden;
|
||
box-shadow: 0 4px 20px rgba(139, 94, 60, 0.08);
|
||
}
|
||
|
||
.menu-list-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 18px 20px;
|
||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||
cursor: pointer;
|
||
transition: background 0.2s;
|
||
}
|
||
|
||
.menu-list-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.menu-list-item:active {
|
||
background: rgba(255, 255, 255, 0.5);
|
||
}
|
||
|
||
.menu-icon {
|
||
width: 24px;
|
||
height: 24px;
|
||
margin-right: 16px;
|
||
font-size: 20px;
|
||
}
|
||
|
||
.menu-text {
|
||
flex: 1;
|
||
font-size: 16px;
|
||
color: #1F2937;
|
||
}
|
||
|
||
.menu-arrow {
|
||
color: #D1D5DB;
|
||
font-size: 18px;
|
||
}
|
||
|
||
.menu-badge {
|
||
background: #EF4444;
|
||
color: white;
|
||
font-size: 10px;
|
||
padding: 2px 6px;
|
||
border-radius: 10px;
|
||
margin-right: 8px;
|
||
}
|
||
|
||
/* 底部导航 - 复用 device-control 样式 */
|
||
.dc-footer {
|
||
position: absolute;
|
||
bottom: 40px;
|
||
bottom: calc(env(safe-area-inset-bottom, 20px) + 30px);
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: center;
|
||
padding: 0 20px;
|
||
box-sizing: border-box;
|
||
z-index: 50;
|
||
}
|
||
|
||
.menu-bar {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
background: rgba(255, 255, 255, 0.6);
|
||
backdrop-filter: blur(20px);
|
||
border: 1px solid rgba(255, 255, 255, 0.8);
|
||
padding: 6px 8px;
|
||
border-radius: 32px;
|
||
width: 100%;
|
||
max-width: 320px;
|
||
box-shadow: 0 10px 30px rgba(139, 92, 246, 0.15);
|
||
}
|
||
|
||
.menu-item {
|
||
width: 56px;
|
||
height: 56px;
|
||
border-radius: 28px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: all 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);
|
||
position: relative;
|
||
}
|
||
|
||
.menu-item img {
|
||
width: 28px;
|
||
height: 28px;
|
||
object-fit: contain;
|
||
opacity: 0.7;
|
||
transition: all 0.3s;
|
||
filter: grayscale(100%) opacity(0.6);
|
||
}
|
||
|
||
.menu-item.active {
|
||
background: linear-gradient(90deg, #E6B98D 0%, #E8C9A8 35%, #D4A373 70%, #B07D5A 100%);
|
||
box-shadow: 0 4px 15px rgba(212, 163, 115, 0.4);
|
||
transform: translateY(-2px) scale(1.05);
|
||
}
|
||
|
||
.menu-item.active img {
|
||
opacity: 1;
|
||
transform: scale(1.1);
|
||
filter: brightness(0) invert(1);
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body>
|
||
<div class="app-container">
|
||
<!-- 动态渐变背景 -->
|
||
<div class="gradient-bg">
|
||
<div class="gradient-layer layer-1"></div>
|
||
</div>
|
||
|
||
<!-- Header -->
|
||
<header class="profile-header">
|
||
<div style="width: 44px;"></div>
|
||
<span class="profile-title">我的</span>
|
||
<button class="icon-btn" title="通知" onclick="location.href='notifications.html'">
|
||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path>
|
||
<path d="M13.73 21a2 2 0 0 1-3.46 0"></path>
|
||
</svg>
|
||
<span class="notification-dot"></span>
|
||
</button>
|
||
</header>
|
||
|
||
<!-- Main Content -->
|
||
<main class="profile-content">
|
||
<!-- 用户信息卡片 -->
|
||
<div class="user-card" onclick="location.href='profile-info.html'">
|
||
<div class="user-avatar">
|
||
<img src="Capybara.png" alt="Avatar">
|
||
</div>
|
||
<div class="user-info">
|
||
<div class="user-name">土豆</div>
|
||
<div class="user-id">ID: 138****3069</div>
|
||
</div>
|
||
<span class="arrow-icon">›</span>
|
||
</div>
|
||
|
||
<!-- 功能菜单 -->
|
||
<div class="menu-list">
|
||
<div class="menu-list-item" onclick="location.href='agent-manage.html'">
|
||
<span class="menu-icon">🧠</span>
|
||
<span class="menu-text">角色记忆</span>
|
||
<span class="menu-arrow">›</span>
|
||
</div>
|
||
<div class="menu-list-item" onclick="location.href='products.html'">
|
||
<span class="menu-icon">📦</span>
|
||
<span class="menu-text">我的设备</span>
|
||
<span class="menu-arrow">›</span>
|
||
</div>
|
||
<div class="menu-list-item" onclick="location.href='settings.html'">
|
||
<span class="menu-icon">⚙️</span>
|
||
<span class="menu-text">设置</span>
|
||
<span class="menu-badge">NEW</span>
|
||
<span class="menu-arrow">›</span>
|
||
</div>
|
||
<div class="menu-list-item" onclick="openFeedback()">
|
||
<span class="menu-icon">💬</span>
|
||
<span class="menu-text">意见反馈</span>
|
||
<span class="menu-arrow">›</span>
|
||
</div>
|
||
<div class="menu-list-item" onclick="location.href='help.html'">
|
||
<span class="menu-icon">❓</span>
|
||
<span class="menu-text">帮助中心</span>
|
||
<span class="menu-arrow">›</span>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- 底部导航 -->
|
||
<footer class="dc-footer">
|
||
<nav class="menu-bar">
|
||
<div class="menu-item" onclick="location.href='device-control.html'">
|
||
<img src="icons/icon-home-capybara.svg" alt="Home">
|
||
</div>
|
||
<div class="menu-item" onclick="location.href='device-control.html?tab=story'">
|
||
<img src="icons/icon-story-pixel.svg" alt="Story">
|
||
</div>
|
||
<div class="menu-item" onclick="location.href='music-creation.html'">
|
||
<img src="icons/icon-music-pixel.svg" alt="Music">
|
||
</div>
|
||
<div class="menu-item active">
|
||
<img src="icons/icon-user-pixel.svg" alt="User">
|
||
</div>
|
||
</nav>
|
||
</footer>
|
||
</div>
|
||
|
||
<!-- 反馈弹窗 -->
|
||
<div class="modal-overlay" id="feedback-modal">
|
||
<div class="glass-modal">
|
||
<div class="modal-title">意见反馈</div>
|
||
<textarea class="modal-input" id="feedback-input" placeholder="请输入您的意见或建议..."
|
||
style="min-height: 100px; resize: none;"></textarea>
|
||
<div class="modal-actions">
|
||
<button class="modal-btn cancel" onclick="closeFeedback()">取消</button>
|
||
<button class="modal-btn confirm" onclick="submitFeedback()">提交</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
function openFeedback() {
|
||
document.getElementById('feedback-modal').classList.add('active');
|
||
}
|
||
|
||
function closeFeedback() {
|
||
document.getElementById('feedback-modal').classList.remove('active');
|
||
}
|
||
|
||
function submitFeedback() {
|
||
const feedback = document.getElementById('feedback-input').value;
|
||
if (feedback.trim()) {
|
||
alert('感谢您的反馈!');
|
||
closeFeedback();
|
||
document.getElementById('feedback-input').value = '';
|
||
}
|
||
}
|
||
</script>
|
||
</body>
|
||
|
||
</html> |