feat(mini-program): UI 优化和功能增强

- 更新全局样式(App.vue),优化玻璃态效果和颜色系统
- 添加星空背景动画效果
- 添加全局音乐播放器组件
- 优化 RecordView 记录页样式
- 修复 epicScript.js 中 selectScript 函数的参数格式
- 与原型设计和 Web 端 API 保持一致

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 17:42:11 +08:00
parent e2d47b03c4
commit 88e35d2889
5 changed files with 332 additions and 12 deletions
+133
View File
@@ -0,0 +1,133 @@
<template>
<view class="music-player" :style="{ bottom: bottomPosition }">
<view
class="music-toggle"
:class="{ playing: isPlaying }"
@click="toggleMusic"
>
<view class="music-disc" :class="{ spinning: isPlaying }"></view>
<text class="music-icon">🎵</text>
</view>
</view>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
const isPlaying = ref(false)
const bottomPosition = ref('180rpx')
const audioContext = null
let audioInstance = null
// 背景音乐 URL - 使用原型中的音乐
const MUSIC_URL = 'https://v3b.fal.media/files/b/0a8c9a0b/rStj8V-2tCe6bVYpCCcLN_output.mp3'
const initAudio = () => {
if (!audioInstance) {
audioInstance = uni.createInnerAudioContext()
audioInstance.src = MUSIC_URL
audioInstance.loop = true
audioInstance.autoplay = false
audioInstance.onError((err) => {
console.error('音乐播放失败:', err)
isPlaying.value = false
})
audioInstance.onEnded(() => {
isPlaying.value = false
})
}
}
const toggleMusic = async () => {
initAudio()
if (isPlaying.value) {
audioInstance.pause()
} else {
try {
await audioInstance.play()
isPlaying.value = true
} catch (err) {
console.error('音乐播放失败:', err)
isPlaying.value = false
}
}
}
onMounted(() => {
const systemInfo = uni.getSystemInfoSync()
const safeAreaBottom = systemInfo.safeAreaInsets?.bottom || 0
bottomPosition.value = `${safeAreaBottom + 96}px`
})
onUnmounted(() => {
if (audioInstance) {
audioInstance.stop()
audioInstance.destroy()
}
})
defineExpose({
toggleMusic,
isPlaying
})
</script>
<style scoped>
.music-player {
position: fixed;
right: 16rpx;
z-index: 1000;
}
.music-toggle {
width: 88rpx;
height: 88rpx;
border-radius: 50%;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
opacity: 0.4;
}
.music-toggle:active {
transform: scale(0.95);
opacity: 0.6;
}
.music-toggle.playing {
opacity: 1;
border-color: rgba(168, 85, 247, 0.5);
box-shadow: 0 0 30rpx rgba(168, 85, 247, 0.3);
}
.music-disc {
position: absolute;
inset: 0;
border-radius: 50%;
border: 1px solid rgba(168, 85, 247, 0.2);
transition: all 0.3s ease;
}
.music-disc.spinning {
animation: spin 3s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.music-icon {
font-size: 36rpx;
z-index: 1;
}
</style>