|
|
@ -4,6 +4,7 @@ import { useRouter } from 'vue-router' |
|
|
import { dailyMissionApi, type DailyMission, DailyMissionStatus, RewardType, MissionType, MissionDifficulty, ProgressTargetType } from '@/api/dailyMission' |
|
|
import { dailyMissionApi, type DailyMission, DailyMissionStatus, RewardType, MissionType, MissionDifficulty, ProgressTargetType } from '@/api/dailyMission' |
|
|
import Particles from '@/components/Particles/Particles.vue' |
|
|
import Particles from '@/components/Particles/Particles.vue' |
|
|
import ElectricBorder from '@/components/ElectricBorder/ElectricBorder.vue' |
|
|
import ElectricBorder from '@/components/ElectricBorder/ElectricBorder.vue' |
|
|
|
|
|
import StarBorder from '@/components/StarBorder/StarBorder.vue' |
|
|
import collectionIcon from '@/assets/images/collection.svg?raw' |
|
|
import collectionIcon from '@/assets/images/collection.svg?raw' |
|
|
import huntingNormalIcon from '@/assets/images/hunting.svg?raw' |
|
|
import huntingNormalIcon from '@/assets/images/hunting.svg?raw' |
|
|
|
|
|
|
|
|
@ -140,16 +141,16 @@ const getRewardIcon = (type: RewardType) => { |
|
|
const getProgressText = (mission: DailyMission) => { |
|
|
const getProgressText = (mission: DailyMission) => { |
|
|
if (!mission.progresses || mission.progresses.length === 0) return '' |
|
|
if (!mission.progresses || mission.progresses.length === 0) return '' |
|
|
const progress = mission.progresses[0] |
|
|
const progress = mission.progresses[0] |
|
|
const targetTypeLabel = progress.targetType === ProgressTargetType.CollectItem ? '收集' |
|
|
const targetTypeLabel = progress.targetType === ProgressTargetType.CollectItem ? '收集' |
|
|
: progress.targetType === ProgressTargetType.KillMonster ? '击杀' |
|
|
: progress.targetType === ProgressTargetType.KillMonster ? '击杀' |
|
|
: progress.targetType === ProgressTargetType.Fish ? '钓鱼' |
|
|
: progress.targetType === ProgressTargetType.Fish ? '钓鱼' |
|
|
: progress.targetType === ProgressTargetType.ConsumeItem ? '消耗' |
|
|
: progress.targetType === ProgressTargetType.ConsumeItem ? '消耗' |
|
|
: progress.targetType === ProgressTargetType.Custom ? '挂机' |
|
|
: progress.targetType === ProgressTargetType.Custom ? '挂机' |
|
|
: '完成' |
|
|
: '完成' |
|
|
const targetName = progress.targetItemName || (progress.targetType === ProgressTargetType.KillMonster ? '怪物' : '物品') |
|
|
const targetName = progress.targetItemName || (progress.targetType === ProgressTargetType.KillMonster ? '怪物' : '物品') |
|
|
// Pending状态显示目标数量,进行中/已完成显示当前进度 |
|
|
// Pending状态显示目标数量,进行中/已完成显示当前进度 |
|
|
const displayCount = mission.status === DailyMissionStatus.Pending |
|
|
const displayCount = mission.status === DailyMissionStatus.Pending |
|
|
? `0/${progress.targetCount}` |
|
|
? `0/${progress.targetCount}` |
|
|
: `${progress.currentCount}/${progress.targetCount}` |
|
|
: `${progress.currentCount}/${progress.targetCount}` |
|
|
return `${targetTypeLabel} ${displayCount} ${targetName}` |
|
|
return `${targetTypeLabel} ${displayCount} ${targetName}` |
|
|
} |
|
|
} |
|
|
@ -204,9 +205,9 @@ const MissionCardContent = defineComponent({ |
|
|
]), |
|
|
]), |
|
|
props.mission.progresses && props.mission.progresses.length > 0 |
|
|
props.mission.progresses && props.mission.progresses.length > 0 |
|
|
? h('div', { class: 'objective-panel' }, [ |
|
|
? h('div', { class: 'objective-panel' }, [ |
|
|
h('span', { class: 'objective-label' }, '任务目标'), |
|
|
h('span', { class: 'objective-label' }, '任务目标'), |
|
|
h('span', { class: 'objective-value' }, getProgressText(props.mission)), |
|
|
h('span', { class: 'objective-value' }, getProgressText(props.mission)), |
|
|
]) |
|
|
]) |
|
|
: null, |
|
|
: null, |
|
|
h('div', { class: 'reward-section' }, [ |
|
|
h('div', { class: 'reward-section' }, [ |
|
|
h('div', { class: 'section-label' }, '任务奖励'), |
|
|
h('div', { class: 'section-label' }, '任务奖励'), |
|
|
@ -231,15 +232,17 @@ const MissionCardContent = defineComponent({ |
|
|
) |
|
|
) |
|
|
: null, |
|
|
: null, |
|
|
canAccept(props.mission) |
|
|
canAccept(props.mission) |
|
|
? h('button', { class: 'card-btn accept-btn', type: 'button', onClick: () => emit('accept') }, [ |
|
|
? h(StarBorder, { as: 'div', color: '#e63d3d', speed: '3s', thickness: 2 }, () => |
|
|
|
|
|
h('button', { class: 'card-btn accept-btn', type: 'button', onClick: () => emit('accept') }, [ |
|
|
h('span', { class: 'btn-label' }, '准备好后即可接取'), |
|
|
h('span', { class: 'btn-label' }, '准备好后即可接取'), |
|
|
h('span', { class: 'btn-arrow' }, '›'), |
|
|
|
|
|
]) |
|
|
]) |
|
|
|
|
|
) |
|
|
: canClaim(props.mission) |
|
|
: canClaim(props.mission) |
|
|
? h('button', { class: 'card-btn claim-btn', type: 'button', onClick: () => emit('claim') }, [ |
|
|
? h(StarBorder, { as: 'div', color: '#22c55e', speed: '3s', thickness: 2 }, () => |
|
|
|
|
|
h('button', { class: 'card-btn claim-btn', type: 'button', onClick: () => emit('claim') }, [ |
|
|
h('span', { class: 'btn-label' }, '领取奖励'), |
|
|
h('span', { class: 'btn-label' }, '领取奖励'), |
|
|
h('span', { class: 'btn-arrow' }, '›'), |
|
|
|
|
|
]) |
|
|
]) |
|
|
|
|
|
) |
|
|
: props.mission.status === DailyMissionStatus.InProgress |
|
|
: props.mission.status === DailyMissionStatus.InProgress |
|
|
? h('button', { class: 'card-btn disabled-btn', type: 'button', disabled: true }, '进行中') |
|
|
? h('button', { class: 'card-btn disabled-btn', type: 'button', disabled: true }, '进行中') |
|
|
: props.mission.status === DailyMissionStatus.Claimed |
|
|
: props.mission.status === DailyMissionStatus.Claimed |
|
|
@ -277,35 +280,17 @@ const MissionCardContent = defineComponent({ |
|
|
|
|
|
|
|
|
<div v-if="hasAnyMissions" class="mission-list"> |
|
|
<div v-if="hasAnyMissions" class="mission-list"> |
|
|
<template v-for="mission in activeMissions" :key="mission.id"> |
|
|
<template v-for="mission in activeMissions" :key="mission.id"> |
|
|
<ElectricBorder |
|
|
<ElectricBorder v-if="mission.difficulty === MissionDifficulty.Purgatory" color="#dc2626" :speed="1.2" |
|
|
v-if="mission.difficulty === MissionDifficulty.Purgatory" |
|
|
:chaos="1.5" :thickness="2" class="mission-card purgatory-card"> |
|
|
color="#dc2626" |
|
|
|
|
|
:speed="1.2" |
|
|
|
|
|
:chaos="1.5" |
|
|
|
|
|
:thickness="2" |
|
|
|
|
|
class="mission-card purgatory-card" |
|
|
|
|
|
> |
|
|
|
|
|
<div class="card-inner"> |
|
|
<div class="card-inner"> |
|
|
<component |
|
|
<component :is="MissionCardContent" :mission="mission" @accept="handleAccept(mission)" |
|
|
:is="MissionCardContent" |
|
|
@claim="handleClaim(mission)" /> |
|
|
:mission="mission" |
|
|
|
|
|
@accept="handleAccept(mission)" |
|
|
|
|
|
@claim="handleClaim(mission)" |
|
|
|
|
|
/> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</ElectricBorder> |
|
|
</ElectricBorder> |
|
|
<div |
|
|
<div v-else class="mission-card" :class="getMissionTypeClass(mission.missionType, mission.difficulty)"> |
|
|
v-else |
|
|
|
|
|
class="mission-card" |
|
|
|
|
|
:class="getMissionTypeClass(mission.missionType, mission.difficulty)" |
|
|
|
|
|
> |
|
|
|
|
|
<div class="card-inner"> |
|
|
<div class="card-inner"> |
|
|
<component |
|
|
<component :is="MissionCardContent" :mission="mission" @accept="handleAccept(mission)" |
|
|
:is="MissionCardContent" |
|
|
@claim="handleClaim(mission)" /> |
|
|
:mission="mission" |
|
|
|
|
|
@accept="handleAccept(mission)" |
|
|
|
|
|
@claim="handleClaim(mission)" |
|
|
|
|
|
/> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</template> |
|
|
</template> |
|
|
@ -392,6 +377,7 @@ const MissionCardContent = defineComponent({ |
|
|
opacity: 0; |
|
|
opacity: 0; |
|
|
transform: translateX(-50%) translateY(-10px); |
|
|
transform: translateX(-50%) translateY(-10px); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
to { |
|
|
to { |
|
|
opacity: 1; |
|
|
opacity: 1; |
|
|
transform: translateX(-50%) translateY(0); |
|
|
transform: translateX(-50%) translateY(0); |
|
|
@ -704,62 +690,48 @@ const MissionCardContent = defineComponent({ |
|
|
transform: scale(0.98); |
|
|
transform: scale(0.98); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
:deep(.btn-arrow) { |
|
|
|
|
|
font-size: 1.3rem; |
|
|
|
|
|
line-height: 1; |
|
|
|
|
|
transform: translateY(-1px); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
:deep(.card-btn.accept-btn) { |
|
|
:deep(.card-btn.accept-btn) { |
|
|
background: linear-gradient(135deg, #facc15 0%, #ff8844 45%, #ef4444 100%); |
|
|
background: rgba(255, 255, 255, 0.03); |
|
|
border-color: rgba(255, 214, 102, 0.55); |
|
|
color: #888888; |
|
|
color: #ffffff; |
|
|
width: 100%; |
|
|
box-shadow: |
|
|
border-radius: 12px; |
|
|
0 10px 24px rgba(255, 136, 68, 0.26), |
|
|
padding: 12px 16px; |
|
|
inset 0 1px 0 rgba(255, 255, 255, 0.22); |
|
|
border: none; |
|
|
text-shadow: 0 1px 8px rgba(0, 0, 0, 0.35); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
:deep(.card-btn.accept-btn .btn-label) { |
|
|
:deep(.card-btn.accept-btn .btn-label) { |
|
|
font-size: 1rem; |
|
|
font-size: 0.9rem; |
|
|
font-weight: 900; |
|
|
font-weight: 500; |
|
|
color: #ffffff; |
|
|
color: white; |
|
|
letter-spacing: 0.1em; |
|
|
letter-spacing: 0.1em; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
:deep(.card-btn.accept-btn:hover) { |
|
|
:deep(.card-btn.accept-btn:hover) { |
|
|
transform: translateY(-1px); |
|
|
background: rgba(255, 255, 255, 0.06); |
|
|
filter: brightness(1.08); |
|
|
color: #aaaaaa; |
|
|
box-shadow: |
|
|
|
|
|
0 14px 30px rgba(255, 136, 68, 0.38), |
|
|
|
|
|
0 0 20px rgba(250, 204, 21, 0.22), |
|
|
|
|
|
inset 0 1px 0 rgba(255, 255, 255, 0.26); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
:deep(.card-btn.claim-btn) { |
|
|
:deep(.card-btn.claim-btn) { |
|
|
background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%); |
|
|
background: rgba(255, 255, 255, 0.03); |
|
|
border-color: rgba(134, 239, 172, 0.4); |
|
|
color: #888888; |
|
|
color: #ffffff; |
|
|
width: 100%; |
|
|
box-shadow: |
|
|
border-radius: 12px; |
|
|
0 10px 24px rgba(34, 197, 94, 0.24), |
|
|
padding: 12px 16px; |
|
|
inset 0 1px 0 rgba(255, 255, 255, 0.2); |
|
|
border: none; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
:deep(.card-btn.claim-btn:hover) { |
|
|
:deep(.card-btn.claim-btn:hover) { |
|
|
transform: translateY(-1px); |
|
|
background: rgba(255, 255, 255, 0.06); |
|
|
filter: brightness(1.08); |
|
|
color: #aaaaaa; |
|
|
box-shadow: |
|
|
|
|
|
0 14px 30px rgba(34, 197, 94, 0.36), |
|
|
|
|
|
0 0 18px rgba(134, 239, 172, 0.18), |
|
|
|
|
|
inset 0 1px 0 rgba(255, 255, 255, 0.24); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
:deep(.card-btn.disabled-btn) { |
|
|
:deep(.card-btn.disabled-btn) { |
|
|
background: rgba(255, 255, 255, 0.05); |
|
|
background: rgba(255, 255, 255, 0.03); |
|
|
border: 1px solid rgba(255, 255, 255, 0.1); |
|
|
color: #555555; |
|
|
color: #6b7280; |
|
|
|
|
|
cursor: not-allowed; |
|
|
cursor: not-allowed; |
|
|
box-shadow: none; |
|
|
width: 100%; |
|
|
|
|
|
border-radius: 12px; |
|
|
|
|
|
padding: 12px 16px; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.status-pending { |
|
|
.status-pending { |
|
|
|