feat: 新增翻牌幸运值悬浮球及相关逻辑
- .claude/settings.local.json:新增 Read 权限路径(Read(//e/code/github/Yi/Yi.Ai.Vue3/**)) - Yi.Ai.Vue3/src/components/userPersonalCenter/components/CardFlipActivity.vue: - 新增 luckyValue 响应式状态与 updateLuckyValue() 方法,并在获取任务状态后更新幸运值 - 新增悬浮球 UI(SVG 进度环、图标、百分比文本)及样式和动画 - 调整了 v-loading 为 false,并注释了部分错误提示(可能为调试遗留) - 说明:样式使用嵌套写法(scss/sass 风格),请确认构建流程支持;建议确认 v-loading 与错误提示变更是否为预期并视情况修正。
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(dotnet build \"E:\\code\\github\\Yi\\Yi.Abp.Net8\\module\\ai-hub\\Yi.Framework.AiHub.Application\\Yi.Framework.AiHub.Application.csproj\" --no-restore)"
|
||||
"Bash(dotnet build \"E:\\code\\github\\Yi\\Yi.Abp.Net8\\module\\ai-hub\\Yi.Framework.AiHub.Application\\Yi.Framework.AiHub.Application.csproj\" --no-restore)",
|
||||
"Read(//e/code/github/Yi/Yi.Ai.Vue3/**)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
|
||||
@@ -17,6 +17,9 @@ const showInviteSection = ref(false);
|
||||
// 翻牌动画状态
|
||||
const flippingCards = ref<Set<number>>(new Set());
|
||||
|
||||
// 幸运值状态
|
||||
const luckyValue = ref(0); // 当前幸运值 0-100
|
||||
|
||||
onMounted(() => {
|
||||
fetchTaskStatus();
|
||||
});
|
||||
@@ -35,6 +38,9 @@ async function fetchTaskStatus() {
|
||||
try {
|
||||
const res = await getWeeklyTaskStatus();
|
||||
taskData.value = res.data;
|
||||
|
||||
// 根据已翻牌次数更新幸运值
|
||||
updateLuckyValue();
|
||||
}
|
||||
catch (error: any) {
|
||||
ElMessage.error(error?.message || '获取任务状态失败');
|
||||
@@ -49,6 +55,15 @@ async function fetchTaskStatus() {
|
||||
}
|
||||
}
|
||||
|
||||
// 更新幸运值
|
||||
function updateLuckyValue() {
|
||||
if (taskData.value) {
|
||||
const flips = taskData.value.totalFlips;
|
||||
// 每次翻牌增加10%幸运值
|
||||
luckyValue.value = Math.min(flips * 12, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// 翻牌
|
||||
async function handleFlipCard(record: CardFlipRecord) {
|
||||
// 检查是否可以翻牌(任何未翻过的牌都可以)
|
||||
@@ -183,7 +198,7 @@ async function handleUseInviteCode() {
|
||||
await fetchTaskStatus();
|
||||
}
|
||||
catch (error: any) {
|
||||
ElMessage.error(error?.message || '使用邀请码失败');
|
||||
// ElMessage.error(error?.message || '使用邀请码失败');
|
||||
}
|
||||
finally {
|
||||
loading.value = false;
|
||||
@@ -261,7 +276,39 @@ function toggleInviteSection() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-loading="loading" class="card-flip-container">
|
||||
<div v-loading="false" class="card-flip-container">
|
||||
<!-- 幸运值悬浮球 -->
|
||||
<div class="lucky-float-ball" :class="{ 'lucky-full': luckyValue >= 100 }">
|
||||
<div class="lucky-circle">
|
||||
<svg class="lucky-progress" viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="luckyGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#667eea;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#764ba2;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<circle
|
||||
class="lucky-bg"
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="40"
|
||||
/>
|
||||
<circle
|
||||
class="lucky-bar"
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="40"
|
||||
:stroke-dasharray="`${luckyValue * 2.51} 251`"
|
||||
/>
|
||||
</svg>
|
||||
<div class="lucky-content">
|
||||
<div class="lucky-icon">{{ luckyValue >= 100 ? '🍀' : '✨' }}</div>
|
||||
<div class="lucky-text">{{ luckyValue }}%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lucky-label">翻牌幸运值</div>
|
||||
</div>
|
||||
|
||||
<!-- 初始加载骨架屏 -->
|
||||
<div v-if="initialLoading" class="loading-skeleton">
|
||||
<div class="skeleton-stats">
|
||||
@@ -545,6 +592,128 @@ function toggleInviteSection() {
|
||||
}
|
||||
}
|
||||
|
||||
/* 幸运值悬浮球 */
|
||||
.lucky-float-ball {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
/* left: 20px; */
|
||||
/* top: 20px; */
|
||||
z-index: 999;
|
||||
bottom: 20px;
|
||||
transition: all 0.3s
|
||||
cubic-bezier(0.4, 0, 0.2, 1);
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
&.lucky-full {
|
||||
animation: lucky-celebration 2s ease-in-out infinite;
|
||||
|
||||
.lucky-circle {
|
||||
box-shadow: 0 0 20px rgba(255, 215, 0, 0.8), 0 0 40px rgba(255, 215, 0, 0.6);
|
||||
}
|
||||
|
||||
.lucky-content {
|
||||
animation: lucky-pulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lucky-circle {
|
||||
position: relative;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2), 0 8px 32px rgba(102, 126, 234, 0.3);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.lucky-progress {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform: rotate(-90deg);
|
||||
|
||||
.lucky-bg {
|
||||
fill: none;
|
||||
stroke: rgba(102, 126, 234, 0.1);
|
||||
stroke-width: 6;
|
||||
}
|
||||
|
||||
.lucky-bar {
|
||||
fill: none;
|
||||
stroke: url(#luckyGradient);
|
||||
stroke-width: 6;
|
||||
stroke-linecap: round;
|
||||
transition: stroke-dasharray 0.5s ease;
|
||||
}
|
||||
}
|
||||
|
||||
.lucky-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
|
||||
.lucky-icon {
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
|
||||
}
|
||||
|
||||
.lucky-text {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.lucky-label {
|
||||
text-align: center;
|
||||
margin-top: 6px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
@keyframes lucky-celebration {
|
||||
0%, 100% {
|
||||
transform: scale(1) rotate(0deg);
|
||||
}
|
||||
25% {
|
||||
transform: scale(1.1) rotate(-5deg);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.15) rotate(0deg);
|
||||
}
|
||||
75% {
|
||||
transform: scale(1.1) rotate(5deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes lucky-pulse {
|
||||
0%, 100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 顶部统计栏 */
|
||||
.top-stats {
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user