3 changed files with 416 additions and 2 deletions
@ -0,0 +1,108 @@ |
|||||
|
<template> |
||||
|
<view class="dl"> |
||||
|
<view class="dl-top"> |
||||
|
<view> |
||||
|
<view class="dl-kicker">2 MIN DAILY</view> |
||||
|
<view class="dl-title">今天就做这几步</view> |
||||
|
<view class="dl-sub">收券、看事件、反搜、投奖池,90秒走人</view> |
||||
|
</view> |
||||
|
<view class="dl-clock">{{data.minutesToDraw || 0}}min</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="dl-pool"> |
||||
|
<view class="dl-pool-main"> |
||||
|
<text class="dl-pool-label">今晚现金奖池</text> |
||||
|
<text class="dl-pool-money">¥{{poolAmount}}</text> |
||||
|
</view> |
||||
|
<view class="dl-prob"> |
||||
|
<text>{{data.myProbability || 0}}%</text> |
||||
|
<text>我的概率</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="dl-stat"> |
||||
|
<view> |
||||
|
<text>{{data.todayCollectedTickets || 0}}</text> |
||||
|
<text>今日收券</text> |
||||
|
</view> |
||||
|
<view> |
||||
|
<text>{{data.myPoolTickets || 0}}</text> |
||||
|
<text>已投奖池</text> |
||||
|
</view> |
||||
|
<view> |
||||
|
<text>{{data.poolJoinCount || 0}}</text> |
||||
|
<text>参与同学</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="dl-events"> |
||||
|
<view class="dl-event" v-for="(e,i) in events" :key="i">{{e}}</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="dl-actions"> |
||||
|
<view class="dl-action collect" @tap="$emit('collect')"> |
||||
|
<text>1</text> |
||||
|
<text>{{collectText}}</text> |
||||
|
</view> |
||||
|
<view class="dl-action revenge" @tap="$emit('revenge')"> |
||||
|
<text>2</text> |
||||
|
<text>{{data.hasRevengeTarget ? '反搜一下' : '随机搜查'}}</text> |
||||
|
</view> |
||||
|
<view class="dl-action join" @tap="$emit('join')"> |
||||
|
<text>3</text> |
||||
|
<text>{{joinText}}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
props: { |
||||
|
data: { type: Object, default: () => ({}) }, |
||||
|
poolAmount: { type: [String, Number], default: 0 } |
||||
|
}, |
||||
|
computed: { |
||||
|
events() { |
||||
|
return this.data.events || [] |
||||
|
}, |
||||
|
collectText() { |
||||
|
if (!this.data.signedToday) return '签到收券' |
||||
|
if (this.data.boxAvailable) return '开补给箱' |
||||
|
return '已收完' |
||||
|
}, |
||||
|
joinText() { |
||||
|
const n = this.data.suggestedAddTickets || 1 |
||||
|
return '投' + n + '券冲奖池' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.dl { margin-top: 24rpx; padding: 28rpx; border-radius: 44rpx; background: linear-gradient(155deg, rgba(255,255,255,0.92), rgba(239,255,249,0.78)); border: 2rpx solid rgba(255,255,255,0.92); box-shadow: 0 26rpx 60rpx rgba(53,214,166,0.14); overflow: hidden; position: relative; } |
||||
|
.dl:before { content: ''; position: absolute; right: -90rpx; top: -120rpx; width: 320rpx; height: 320rpx; border-radius: 50%; background: radial-gradient(circle, rgba(79,183,255,0.26), transparent 68%); } |
||||
|
.dl-top { position: relative; z-index: 1; display: flex; align-items: flex-start; justify-content: space-between; } |
||||
|
.dl-kicker { color: #59CBB5; font-size: 20rpx; font-weight: 900; letter-spacing: 2rpx; } |
||||
|
.dl-title { margin-top: 6rpx; color: #12342F; font-size: 42rpx; font-weight: 900; } |
||||
|
.dl-sub { margin-top: 8rpx; color: #6B817D; font-size: 24rpx; } |
||||
|
.dl-clock { padding: 14rpx 18rpx; border-radius: 999rpx; background: rgba(255,255,255,0.82); color: #22B889; font-size: 24rpx; font-weight: 900; } |
||||
|
.dl-pool { position: relative; z-index: 1; margin-top: 28rpx; display: flex; justify-content: space-between; align-items: center; padding: 26rpx; border-radius: 34rpx; background: linear-gradient(135deg, rgba(255,255,255,0.86), rgba(232,246,255,0.72)); } |
||||
|
.dl-pool-main { display: flex; flex-direction: column; } |
||||
|
.dl-pool-label { color: #6B817D; font-size: 24rpx; } |
||||
|
.dl-pool-money { margin-top: 8rpx; color: #12342F; font-size: 50rpx; font-weight: 900; } |
||||
|
.dl-prob { width: 132rpx; height: 132rpx; border-radius: 46rpx; background: linear-gradient(145deg, #35D6A6, #4FB7FF); color: #fff; display: flex; flex-direction: column; align-items: center; justify-content: center; box-shadow: 0 18rpx 40rpx rgba(53,214,166,0.24); } |
||||
|
.dl-prob text:first-child { font-size: 34rpx; font-weight: 900; } |
||||
|
.dl-prob text:last-child { font-size: 20rpx; margin-top: 4rpx; } |
||||
|
.dl-stat { margin-top: 18rpx; display: flex; gap: 14rpx; } |
||||
|
.dl-stat view { flex: 1; padding: 18rpx 10rpx; border-radius: 26rpx; background: rgba(255,255,255,0.66); display: flex; flex-direction: column; align-items: center; } |
||||
|
.dl-stat text:first-child { color: #12342F; font-size: 30rpx; font-weight: 900; } |
||||
|
.dl-stat text:last-child { color: #6B817D; font-size: 20rpx; margin-top: 4rpx; } |
||||
|
.dl-events { margin-top: 18rpx; } |
||||
|
.dl-event { margin-top: 10rpx; padding: 14rpx 18rpx; border-radius: 24rpx; background: rgba(255,255,255,0.62); color: #42635E; font-size: 24rpx; } |
||||
|
.dl-actions { margin-top: 22rpx; display: flex; gap: 14rpx; } |
||||
|
.dl-action { flex: 1; min-height: 94rpx; border-radius: 30rpx; display: flex; flex-direction: column; align-items: center; justify-content: center; color: #12342F; font-size: 23rpx; font-weight: 900; background: rgba(255,255,255,0.78); } |
||||
|
.dl-action text:first-child { width: 34rpx; height: 34rpx; line-height: 34rpx; text-align: center; border-radius: 50%; background: #22B889; color: #fff; font-size: 20rpx; margin-bottom: 8rpx; } |
||||
|
.dl-action.join { background: linear-gradient(135deg, #35D6A6, #4FB7FF); color: #fff; box-shadow: 0 18rpx 36rpx rgba(53,214,166,0.22); } |
||||
|
.dl-action.join text:first-child { background: rgba(255,255,255,0.28); } |
||||
|
</style> |
||||
@ -0,0 +1,157 @@ |
|||||
|
<template> |
||||
|
<view class="po"> |
||||
|
<view class="po-head"> |
||||
|
<view> |
||||
|
<view class="po-kicker">CAMPUS FARM</view> |
||||
|
<view class="po-title">松鼠星际农场</view> |
||||
|
<view class="po-sub">种券、仓库、防御塔和地标争夺,每天都有一点成长</view> |
||||
|
</view> |
||||
|
<view class="po-stamina"> |
||||
|
<text class="po-stamina-num">{{state.stamina || 0}}</text> |
||||
|
<text class="po-stamina-label">体力</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="po-grid"> |
||||
|
<view class="po-card tree"> |
||||
|
<view class="po-tree"> |
||||
|
<view class="po-tree-crown"></view> |
||||
|
<view class="po-tree-body"></view> |
||||
|
</view> |
||||
|
<view class="po-card-title">券树培育</view> |
||||
|
<view class="po-card-desc">选择周期投入星球券,成熟后返还本金和收益</view> |
||||
|
<scroll-view scroll-x class="po-cycles"> |
||||
|
<view class="po-cycle" v-for="(c,i) in treeConfigs" :key="i" @tap="$emit('plant', c)"> |
||||
|
<text>{{c.cycleHours}}h</text> |
||||
|
<text>收益 {{rateText(c.rate)}}</text> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="po-card warehouse"> |
||||
|
<view class="po-icon">SAFE</view> |
||||
|
<view class="po-card-title">松鼠仓库 Lv{{state.warehouseLevel || 1}}</view> |
||||
|
<view class="po-progress"><view class="po-progress-in" :style="{width: warehousePercent + '%'}"></view></view> |
||||
|
<view class="po-card-desc">{{state.warehouseTicketCount || 0}} / {{state.warehouseCapacity || 10}} 张安全券</view> |
||||
|
<view class="po-actions"> |
||||
|
<text @tap="$emit('store')">存入</text> |
||||
|
<text @tap="$emit('take')">取出</text> |
||||
|
<text @tap="$emit('upgradeWarehouse')">升级</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="po-card tower"> |
||||
|
<view class="po-icon">TOWER</view> |
||||
|
<view class="po-card-title">防御塔 Lv{{state.towerLevel || 1}}</view> |
||||
|
<view class="po-card-desc">拦截 {{state.towerInterceptRate || 0}}% · 伤害 {{state.towerDamage || 0}}</view> |
||||
|
<view class="po-main-btn" @tap="$emit('upgradeTower')">升级防御</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="po-card search"> |
||||
|
<view class="po-icon">RADAR</view> |
||||
|
<view class="po-card-title">星际搜查</view> |
||||
|
<view class="po-card-desc">今日 {{state.dailySearchCount || 0}} 次 · 获得 {{state.dailySearchGain || 0}} 券</view> |
||||
|
<view class="po-main-btn" @tap="$emit('search')">派出松鼠宇航员</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="po-land"> |
||||
|
<view class="po-land-title">校园地标</view> |
||||
|
<scroll-view scroll-x class="po-land-scroll"> |
||||
|
<view class="po-land-item" v-for="(l,i) in landmarks" :key="i" @tap="$emit('bid', l)"> |
||||
|
<view class="po-land-icon">{{l.icon || 'LAND'}}</view> |
||||
|
<view class="po-land-name">{{l.name}}</view> |
||||
|
<view class="po-land-benefit">{{benefitText(l)}}</view> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="po-orders" v-if="treeOrders.length"> |
||||
|
<view class="po-land-title">成长中的券树</view> |
||||
|
<view class="po-order" v-for="(o,i) in treeOrders" :key="i"> |
||||
|
<view> |
||||
|
<view class="po-order-title">{{o.cycleHours}}h · 投入{{o.investTickets}}券</view> |
||||
|
<view class="po-order-desc">预计收获 {{o.expectedTotal}} 券</view> |
||||
|
</view> |
||||
|
<view class="po-order-btn" @tap="$emit('harvest', o)">{{o.status === 2 ? '已收' : '收获'}}</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
props: { |
||||
|
data: { type: Object, default: () => ({}) } |
||||
|
}, |
||||
|
computed: { |
||||
|
state() { |
||||
|
return (this.data && this.data.state) || {} |
||||
|
}, |
||||
|
treeConfigs() { |
||||
|
return (this.data && this.data.treeConfigs) || [] |
||||
|
}, |
||||
|
treeOrders() { |
||||
|
return (this.data && this.data.treeOrders) || [] |
||||
|
}, |
||||
|
landmarks() { |
||||
|
return (this.data && this.data.landmarks) || [] |
||||
|
}, |
||||
|
warehousePercent() { |
||||
|
const cap = this.state.warehouseCapacity || 10 |
||||
|
return Math.min(100, Math.round(((this.state.warehouseTicketCount || 0) / cap) * 100)) |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
rateText(rate) { |
||||
|
return Math.round((Number(rate || 0)) * 100) + '%' |
||||
|
}, |
||||
|
benefitText(item) { |
||||
|
if (item.benefitType === 'ticket') return '每日+' + item.benefitValue + '券' |
||||
|
if (item.benefitType === 'stamina_speed') return '体力+' + item.benefitValue + '%' |
||||
|
if (item.benefitType === 'search_rate') return '搜查+' + item.benefitValue + '%' |
||||
|
if (item.benefitType === 'tower_damage') return '防御+' + item.benefitValue + '%' |
||||
|
return '校园增益' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.po { margin-top: 24rpx; } |
||||
|
.po-head { display: flex; justify-content: space-between; align-items: flex-start; padding: 0 10rpx 14rpx; } |
||||
|
.po-kicker { color: #59CBB5; font-size: 20rpx; font-weight: 900; letter-spacing: 2rpx; } |
||||
|
.po-title { margin-top: 6rpx; color: #12342F; font-size: 40rpx; font-weight: 900; } |
||||
|
.po-sub { margin-top: 8rpx; color: #6B817D; font-size: 24rpx; } |
||||
|
.po-stamina { width: 124rpx; height: 124rpx; border-radius: 44rpx; background: linear-gradient(145deg, rgba(255,255,255,0.96), rgba(225,250,255,0.82)); display: flex; flex-direction: column; align-items: center; justify-content: center; box-shadow: 0 18rpx 42rpx rgba(79,183,255,0.16); } |
||||
|
.po-stamina-num { color: #22B889; font-size: 36rpx; font-weight: 900; } |
||||
|
.po-stamina-label { color: #6B817D; font-size: 20rpx; } |
||||
|
.po-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18rpx; } |
||||
|
.po-card { position: relative; min-height: 250rpx; padding: 24rpx; border-radius: 38rpx; background: linear-gradient(155deg, rgba(255,255,255,0.9), rgba(241,255,249,0.72)); border: 2rpx solid rgba(255,255,255,0.9); box-shadow: 0 20rpx 46rpx rgba(53,214,166,0.12); overflow: hidden; } |
||||
|
.po-card.tree { grid-column: span 2; min-height: 280rpx; } |
||||
|
.po-card-title { color: #12342F; font-size: 30rpx; font-weight: 900; } |
||||
|
.po-card-desc { margin-top: 10rpx; color: #6B817D; font-size: 23rpx; line-height: 1.5; } |
||||
|
.po-tree { position: absolute; right: 54rpx; top: 34rpx; width: 140rpx; height: 150rpx; animation: treeBreath 2.6s ease-in-out infinite; } |
||||
|
.po-tree-crown { width: 130rpx; height: 110rpx; border-radius: 70rpx 70rpx 50rpx 50rpx; background: radial-gradient(circle at 35% 28%, #FFFFFF, #A8F7C1 42%, #35D6A6); box-shadow: 0 18rpx 38rpx rgba(53,214,166,0.24); } |
||||
|
.po-tree-body { margin: -12rpx auto 0; width: 28rpx; height: 66rpx; border-radius: 20rpx; background: linear-gradient(180deg, #F5C68A, #D8894F); } |
||||
|
@keyframes treeBreath { 0%,100%{ transform: translateY(0) scale(1); } 50%{ transform: translateY(-10rpx) scale(1.04); } } |
||||
|
.po-cycles { margin-top: 34rpx; white-space: nowrap; width: 430rpx; } |
||||
|
.po-cycle { display: inline-flex; flex-direction: column; justify-content: center; width: 132rpx; height: 86rpx; margin-right: 14rpx; padding-left: 20rpx; border-radius: 28rpx; background: rgba(255,255,255,0.82); color: #22B889; font-size: 22rpx; font-weight: 800; box-shadow: 0 12rpx 26rpx rgba(53,214,166,0.1); } |
||||
|
.po-icon { display: inline-flex; padding: 10rpx 16rpx; margin-bottom: 18rpx; border-radius: 999rpx; background: rgba(255,255,255,0.8); color: #22B889; font-size: 20rpx; font-weight: 900; } |
||||
|
.po-progress { margin-top: 18rpx; height: 14rpx; border-radius: 999rpx; background: rgba(53,214,166,0.12); overflow: hidden; } |
||||
|
.po-progress-in { height: 100%; border-radius: 999rpx; background: linear-gradient(90deg, #35D6A6, #4FB7FF); } |
||||
|
.po-actions { display: flex; gap: 10rpx; margin-top: 18rpx; } |
||||
|
.po-actions text, .po-main-btn { display: inline-flex; align-items: center; justify-content: center; height: 54rpx; padding: 0 18rpx; border-radius: 999rpx; background: linear-gradient(135deg, #DFFBF1, #E8F6FF); color: #22B889; font-size: 22rpx; font-weight: 800; } |
||||
|
.po-main-btn { margin-top: 18rpx; } |
||||
|
.po-land, .po-orders { margin-top: 20rpx; padding: 24rpx; border-radius: 38rpx; background: rgba(255,255,255,0.62); border: 2rpx solid rgba(255,255,255,0.86); box-shadow: 0 18rpx 42rpx rgba(79,183,255,0.1); } |
||||
|
.po-land-title { color: #12342F; font-size: 30rpx; font-weight: 900; } |
||||
|
.po-land-scroll { margin-top: 18rpx; white-space: nowrap; width: 100%; } |
||||
|
.po-land-item { display: inline-flex; flex-direction: column; justify-content: center; width: 190rpx; height: 170rpx; margin-right: 18rpx; padding: 18rpx; border-radius: 32rpx; background: linear-gradient(155deg, rgba(255,255,255,0.92), rgba(247,239,255,0.68)); box-sizing: border-box; } |
||||
|
.po-land-icon { color: #8F7CFF; font-size: 20rpx; font-weight: 900; } |
||||
|
.po-land-name { margin-top: 12rpx; color: #12342F; font-size: 27rpx; font-weight: 900; } |
||||
|
.po-land-benefit { margin-top: 8rpx; color: #6B817D; font-size: 22rpx; } |
||||
|
.po-order { display: flex; align-items: center; justify-content: space-between; margin-top: 18rpx; padding: 18rpx; border-radius: 28rpx; background: rgba(255,255,255,0.78); } |
||||
|
.po-order-title { color: #12342F; font-size: 26rpx; font-weight: 800; } |
||||
|
.po-order-desc { margin-top: 6rpx; color: #6B817D; font-size: 22rpx; } |
||||
|
.po-order-btn { padding: 14rpx 20rpx; border-radius: 999rpx; background: #22B889; color: #fff; font-size: 22rpx; font-weight: 800; } |
||||
|
</style> |
||||
Loading…
Reference in new issue