rtc_prd/profile.html
seaislee1209 066eb8f820 feat: music-creation page + MiniMax API integration + Flutter dev setup
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>
2026-02-06 18:23:19 +08:00

361 lines
11 KiB
HTML
Raw Permalink 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.

<!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>