21 changed files with 735 additions and 2 deletions
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 351 B |
After Width: | Height: | Size: 359 B |
After Width: | Height: | Size: 990 B |
After Width: | Height: | Size: 107 KiB |
@ -0,0 +1,8 @@
|
||||
import type { Ref } from 'vue' |
||||
|
||||
export interface Task { |
||||
task1: Ref<HTMLElement | null> |
||||
task2: Ref<HTMLElement | null> |
||||
task3: Ref<HTMLElement | null> |
||||
task4: Ref<HTMLElement | null> |
||||
} |
@ -0,0 +1,3 @@
|
||||
import AppTaskMenuList from './index.vue' |
||||
|
||||
export { AppTaskMenuList } |
@ -0,0 +1,99 @@
|
||||
<!-- 子菜单列表组件 --> |
||||
<script setup lang="ts"> |
||||
import { inject, ref } from 'vue' |
||||
import type { Task } from './index.d' |
||||
|
||||
const sectionRefs = inject<Task>('sectionRefs') |
||||
const taskContainer = inject('taskContainer') |
||||
const activeIndex = ref(0) |
||||
const list = [ |
||||
{ |
||||
title: '基础任务', |
||||
status: true, |
||||
task: 'task1', |
||||
}, |
||||
{ |
||||
title: '新手任务', |
||||
status: false, |
||||
task: 'task2', |
||||
}, |
||||
{ |
||||
title: '每日任务', |
||||
status: false, |
||||
task: 'task3', |
||||
}, |
||||
{ |
||||
title: '其他任务', |
||||
status: false, |
||||
task: 'task4', |
||||
}, |
||||
] |
||||
// 切换任务 |
||||
function handleClick(index: number, task: string) { |
||||
activeIndex.value = index |
||||
|
||||
const target = sectionRefs[task].value.$el.offsetTop - 40 |
||||
|
||||
taskContainer.value.scrollTo({ |
||||
top: target, |
||||
behavior: 'smooth', |
||||
}) |
||||
} |
||||
</script> |
||||
|
||||
<template> |
||||
<div class="app-task-menu-list"> |
||||
<div |
||||
v-for="(item, index) in list" |
||||
:key="index" |
||||
class="app-task-menu-list-item" |
||||
:class="[activeIndex === index && 'app-task-menu-list-item-active']" |
||||
@click="handleClick(index, item.task)" |
||||
> |
||||
<p class="title"> |
||||
{{ item.title }} |
||||
</p> |
||||
<div v-show="item.status" class="dot"></div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<style lang="scss" scoped> |
||||
@include app('task-menu-list') { |
||||
&-item { |
||||
width: 80%; |
||||
margin: 5px auto; |
||||
padding: 6px; |
||||
border-radius: 10px; |
||||
transition: all 0.2s; |
||||
text-align: center; |
||||
cursor: pointer; |
||||
color: #888c90; |
||||
position: relative; |
||||
.title { |
||||
font-size: 11px; |
||||
font-family: PingFang-SC, PingFang-SC; |
||||
font-weight: bold; |
||||
line-height: 20px; |
||||
margin: 0; |
||||
} |
||||
.dot { |
||||
width: 6px; |
||||
height: 6px; |
||||
background-color: red; |
||||
border-radius: 50%; |
||||
position: absolute; |
||||
right: 40px; |
||||
top: 10px; |
||||
} |
||||
} |
||||
&-item-active { |
||||
background: #e1e9f9; |
||||
color: #4670e3; |
||||
} |
||||
&-item:hover { |
||||
background: #e1e9f9; |
||||
color: #4670e3; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,3 @@
|
||||
import BasicTask from './index.vue' |
||||
|
||||
export { BasicTask } |
@ -0,0 +1,466 @@
|
||||
<script lang="ts" setup> |
||||
import { ref } from 'vue' |
||||
import History from '@/assets/images/task/history.png' |
||||
import unclaimed from '@/assets/images/task/dlq.png' |
||||
import dot from '@/assets/images/task/dot.png' |
||||
import money from '@/assets/images/task/money.png' |
||||
|
||||
// 签到天数 |
||||
const sign = ref([ |
||||
{ |
||||
day: '第1天', |
||||
img: unclaimed, |
||||
status: 1, |
||||
}, |
||||
{ |
||||
day: '第2天', |
||||
img: unclaimed, |
||||
status: 1, |
||||
}, |
||||
{ |
||||
day: '第3天', |
||||
img: unclaimed, |
||||
status: 1, |
||||
}, |
||||
{ |
||||
day: '第4天', |
||||
img: unclaimed, |
||||
status: 2, |
||||
}, |
||||
{ |
||||
day: '第5天', |
||||
img: unclaimed, |
||||
status: 3, |
||||
}, |
||||
{ |
||||
day: '第6天', |
||||
img: unclaimed, |
||||
status: 3, |
||||
}, |
||||
{ |
||||
day: '第7天', |
||||
img: unclaimed, |
||||
status: 3, |
||||
}, |
||||
]) |
||||
// 做任务赚积分 |
||||
const earn = ref([ |
||||
{ |
||||
title: '登录微信小程序', |
||||
dot: 1, |
||||
status: 1, |
||||
}, |
||||
{ |
||||
title: '邀请注册', |
||||
dot: 200, |
||||
status: 0, |
||||
}, |
||||
{ |
||||
title: '每日登录', |
||||
dot: 2, |
||||
status: 1, |
||||
}, |
||||
]) |
||||
</script> |
||||
|
||||
<template> |
||||
<div class="basic-task-box"> |
||||
<div class="title"> |
||||
基础任务 |
||||
</div> |
||||
<div class="contant flex flex-row"> |
||||
<div class="left basis-3/5"> |
||||
<div class="top flex flex-row"> |
||||
<div class="login-day"> |
||||
您已连续登录 <span>3</span> 天 |
||||
</div> |
||||
<div class="historyBox"> |
||||
<img class="historyImg" :src="History" alt=""> |
||||
<div class="historyName"> |
||||
历史 |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="bottom"> |
||||
<div class="accumulate"> |
||||
<div class="three"> |
||||
累计领取:3点数 |
||||
</div> |
||||
<div class="ten"> |
||||
连续签到7天可得 10 点数 |
||||
</div> |
||||
</div> |
||||
<div class="sign-box"> |
||||
<div v-for="(item, index) in sign" :key="index" class="sign"> |
||||
<div class="sign-photo" :style="{ backgroundImage: `url(${item.img})`, backgroundSize: '100% 100%', backgroundRepeat: 'no-repeat' }"> |
||||
<div class="count"> |
||||
{{ index === 6 ? "10点数" : "1点数" }} |
||||
</div> |
||||
</div> |
||||
<div v-show="item.status !== 2" class="sign-day"> |
||||
{{ item.day }} |
||||
</div> |
||||
<div v-show="item.status === 2" class="sign-get"> |
||||
领取 |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="right basis-2/5"> |
||||
<div class="earn-points"> |
||||
<div class="title-box"> |
||||
<div class="dot"> |
||||
<img :src="dot" alt=""> |
||||
</div> |
||||
<div class="name"> |
||||
做任务赚积分 |
||||
</div> |
||||
<div class="dot"> |
||||
<img :src="dot" alt=""> |
||||
</div> |
||||
</div> |
||||
<div class="earn-list-box"> |
||||
<div v-for="(item, index) in earn" :key="index" class="earn-list"> |
||||
<div class="earn-list-left"> |
||||
<div class="name"> |
||||
{{ item.title }} |
||||
</div> |
||||
<div v-show="item.status === 1" class="accomplish"> |
||||
已获得{{ item.dot }}点数 |
||||
</div> |
||||
<div v-show="item.status === 0" class="unfinished"> |
||||
0/{{ item.dot }} |
||||
</div> |
||||
</div> |
||||
<div class="earn-list-right"> |
||||
<div class="add-dot-box"> |
||||
<div class="flex items-center"> |
||||
<img class="add-dot-photo" :src="money" alt=""> |
||||
<div class="add-dot-num"> |
||||
+{{ item.dot }} |
||||
</div> |
||||
</div> |
||||
|
||||
<div v-show="item.status === 1" class="add-dot-btn accomplish"> |
||||
已完成 |
||||
</div> |
||||
|
||||
<div v-if="item.status === 0 && index !== 1" class="add-dot-btn unfinished"> |
||||
未完成 |
||||
</div> |
||||
<div v-if="item.status === 0 && index === 1" class="add-dot-btn invite"> |
||||
去邀请 |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<style lang="scss" scoped> |
||||
.basic-task-box { |
||||
width: 95%; |
||||
.title { |
||||
font-size: 13px; |
||||
font-family: PingFang-SC, PingFang-SC; |
||||
font-weight: bold; |
||||
color: #000000; |
||||
line-height: 22px; |
||||
letter-spacing: 1px; |
||||
margin: 16px 0; |
||||
} |
||||
.contant { |
||||
width: 100%; |
||||
column-gap: 10px; |
||||
.left { |
||||
width: 100%; |
||||
|
||||
background-image: url(@/assets/images/task/qiandao.png); |
||||
background-size: 100% 100%; |
||||
padding: 20px; |
||||
.top { |
||||
width: 100%; |
||||
justify-content: space-between; |
||||
.login-day { |
||||
font-size: 19px; |
||||
font-family: PingFang-SC, PingFang-SC; |
||||
color: #ffffff; |
||||
line-height: 33px; |
||||
letter-spacing: 2px; |
||||
span { |
||||
font-size: 27px; |
||||
font-weight: bold; |
||||
} |
||||
} |
||||
.historyBox { |
||||
display: flex; |
||||
cursor: pointer; |
||||
align-items: flex-start; |
||||
.historyImg { |
||||
width: 13px; |
||||
height: 13px; |
||||
} |
||||
.historyName { |
||||
padding-left: 5px; |
||||
font-size: 11px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #ffffff; |
||||
margin-top: -2px; |
||||
} |
||||
} |
||||
} |
||||
.bottom { |
||||
margin-top: 15px; |
||||
|
||||
.accumulate { |
||||
width: 100%; |
||||
display: flex; |
||||
|
||||
.three { |
||||
width: 30%; |
||||
height: 100%; |
||||
padding: 3px 0; |
||||
text-align: center; |
||||
background-color: #ffffff; |
||||
font-size: 12px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #4670e3; |
||||
border-top-left-radius: 6px; |
||||
position: relative; |
||||
z-index: 2; |
||||
&::after { |
||||
content: ''; |
||||
position: absolute; |
||||
top: 0; |
||||
left: 10px; |
||||
width: 96%; |
||||
height: 100%; |
||||
background-color: inherit; |
||||
transform: skewX(35deg); /* 可调整此值以改变倾斜的程度 */ |
||||
transform-origin: 100% 0; |
||||
z-index: -1; |
||||
} |
||||
} |
||||
.ten { |
||||
width: 70%; |
||||
padding: 3px 0; |
||||
font-size: 12px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #ffffff; |
||||
padding-left: 30px; |
||||
} |
||||
} |
||||
.sign-box { |
||||
width: 100%; |
||||
height: 100px; |
||||
background-color: #ffffff; |
||||
border-top-right-radius: 6px; |
||||
border-bottom-right-radius: 6px; |
||||
border-bottom-left-radius: 6px; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-around; |
||||
.sign { |
||||
.sign-photo { |
||||
width: 50px; |
||||
height: 64px; |
||||
position: relative; |
||||
.count { |
||||
font-size: 10px; |
||||
font-family: PingFang-SC, PingFang-SC; |
||||
font-weight: 500; |
||||
color: #ff9b00; |
||||
text-align: center; |
||||
font-weight: bold; |
||||
padding-top: 5px; |
||||
} |
||||
} |
||||
.sign-day { |
||||
text-align: center; |
||||
font-size: 10px; |
||||
font-family: PingFang-SC, PingFang-SC; |
||||
font-weight: bold; |
||||
color: #888c90; |
||||
padding-top: 5px; |
||||
} |
||||
.sign-get { |
||||
cursor: pointer; |
||||
margin-top: 5px; |
||||
width: 100%; |
||||
height: 15px; |
||||
background: linear-gradient(180deg, #ffb33d 0%, #ff9b00 100%); |
||||
border-radius: 11px; |
||||
font-size: 11px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #ffffff; |
||||
line-height: 15px; |
||||
text-align: center; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
.right { |
||||
width: 100%; |
||||
padding: 20px 14px; |
||||
|
||||
background-color: aliceblue; |
||||
border-radius: 15px; |
||||
.earn-points { |
||||
.title-box { |
||||
display: flex; |
||||
align-items: center; |
||||
padding-left: 10px; |
||||
.dot { |
||||
display: flex; |
||||
align-items: center; |
||||
} |
||||
.name { |
||||
padding: 0 7px; |
||||
font-size: 13px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 500; |
||||
color: #000000; |
||||
line-height: 22px; |
||||
font-weight: bold; |
||||
letter-spacing: 1px; |
||||
} |
||||
} |
||||
.earn-list-box { |
||||
margin-top: 15px; |
||||
width: 100%; |
||||
height: 150px; |
||||
|
||||
background-color: #ffffff; |
||||
border-radius: 4px; |
||||
padding: 0 10px; |
||||
.earn-list { |
||||
width: 100%; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
padding: 10px 0; |
||||
border-bottom: 1px solid #ededed; |
||||
&:last-child { |
||||
border: 0; |
||||
} |
||||
.earn-list-left { |
||||
display: flex; |
||||
align-items: center; |
||||
width: 60%; |
||||
.name { |
||||
font-size: 12px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 500; |
||||
|
||||
color: #000000; |
||||
|
||||
letter-spacing: 1px; |
||||
} |
||||
.accomplish { |
||||
font-size: 9px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #f7b606; |
||||
padding-left: 10px; |
||||
} |
||||
.unfinished { |
||||
font-size: 10px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #888c90; |
||||
padding-left: 10px; |
||||
} |
||||
} |
||||
.earn-list-right { |
||||
width: 40%; |
||||
|
||||
.add-dot-box { |
||||
width: 100%; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
.add-dot-photo { |
||||
width: 13px; |
||||
height: 13px; |
||||
display: flex; |
||||
align-items: center; |
||||
} |
||||
.add-dot-num { |
||||
font-size: 11px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #f7b500; |
||||
padding-left: 3px; |
||||
} |
||||
.add-dot-btn { |
||||
cursor: pointer; |
||||
width: 45px; |
||||
height: 20px; |
||||
border-radius: 16px; |
||||
font-size: 10px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
line-height: 20px; |
||||
letter-spacing: 1px; |
||||
text-align: center; |
||||
&.accomplish { |
||||
background: linear-gradient( |
||||
90deg, |
||||
#b5ceff 0%, |
||||
#a6baff 100% |
||||
); |
||||
color: #ffffff; |
||||
} |
||||
&.unfinished { |
||||
background: #ffffff; |
||||
border: 1px solid #cdcdcd; |
||||
line-height: 18px; |
||||
color: #888c90; |
||||
} |
||||
&.invite { |
||||
background: linear-gradient( |
||||
90deg, |
||||
#6fa3ff 0%, |
||||
#486dff 100% |
||||
); |
||||
color: #ffffff; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,3 @@
|
||||
import DailyTask from './index.vue' |
||||
|
||||
export { DailyTask } |
@ -0,0 +1,32 @@
|
||||
<script lang="ts" setup> |
||||
|
||||
</script> |
||||
|
||||
<template> |
||||
<div class="daily-task-box"> |
||||
<div class="title"> |
||||
每日任务 |
||||
</div> |
||||
<div class="contant"></div> |
||||
</div> |
||||
</template> |
||||
|
||||
<style lang="scss" scoped> |
||||
.daily-task-box { |
||||
width: 95%; |
||||
.title { |
||||
font-size: 13px; |
||||
font-family: PingFang-SC, PingFang-SC; |
||||
font-weight: bold; |
||||
color: #000000; |
||||
line-height: 22px; |
||||
letter-spacing: 1px; |
||||
margin: 16px 0; |
||||
} |
||||
.contant { |
||||
width: 100%; |
||||
height: 200px; |
||||
background-color: red; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,3 @@
|
||||
import NoviceTask from './index.vue' |
||||
|
||||
export { NoviceTask } |
@ -0,0 +1,32 @@
|
||||
<script lang="ts" setup> |
||||
|
||||
</script> |
||||
|
||||
<template> |
||||
<div class="nvoice-task-box"> |
||||
<div class="title"> |
||||
新手任务 |
||||
</div> |
||||
<div class="contant"></div> |
||||
</div> |
||||
</template> |
||||
|
||||
<style lang="scss" scoped> |
||||
.nvoice-task-box { |
||||
width: 95%; |
||||
.title { |
||||
font-size: 13px; |
||||
font-family: PingFang-SC, PingFang-SC; |
||||
font-weight: bold; |
||||
color: #000000; |
||||
line-height: 22px; |
||||
letter-spacing: 1px; |
||||
margin: 16px 0; |
||||
} |
||||
.contant { |
||||
width: 100%; |
||||
height: 200px; |
||||
background-color: red; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,3 @@
|
||||
import OtherTask from './index.vue' |
||||
|
||||
export { OtherTask } |
@ -0,0 +1,32 @@
|
||||
<script lang="ts" setup> |
||||
|
||||
</script> |
||||
|
||||
<template> |
||||
<div class="other-task-box"> |
||||
<div class="title"> |
||||
其他任务 |
||||
</div> |
||||
<div class="contant"></div> |
||||
</div> |
||||
</template> |
||||
|
||||
<style lang="scss" scoped> |
||||
.other-task-box { |
||||
width: 95%; |
||||
.title { |
||||
font-size: 13px; |
||||
font-family: PingFang-SC, PingFang-SC; |
||||
font-weight: bold; |
||||
color: #000000; |
||||
line-height: 22px; |
||||
letter-spacing: 1px; |
||||
margin: 16px 0; |
||||
} |
||||
.contant { |
||||
width: 100%; |
||||
height: 200px; |
||||
background-color: red; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,40 @@
|
||||
<script setup lang="ts"> |
||||
import { provide, ref } from 'vue' |
||||
import { BasicTask } from './components/BasicTask' |
||||
import { NoviceTask } from './components/NoviceTask' |
||||
import { DailyTask } from './components/DailyTask' |
||||
import { OtherTask } from './components/OtherTask' |
||||
|
||||
import { AppContainerBox } from '@/components/AppContainerBox' |
||||
import { AppSubMenuTitle } from '@/components/AppSubMenuTitle' |
||||
import { AppTaskMenuList } from '@/components/AppTaskMenuList' |
||||
|
||||
const taskContainer = ref(null) |
||||
const task1 = ref(null) |
||||
const task2 = ref(null) |
||||
const task3 = ref(null) |
||||
const task4 = ref(null) |
||||
const sectionRefs = { task1, task2, task3, task4 } |
||||
provide('sectionRefs', sectionRefs) |
||||
provide('taskContainer', taskContainer) |
||||
</script> |
||||
|
||||
<template> |
||||
<AppContainerBox> |
||||
<template #subMenu> |
||||
<AppSubMenuTitle title="任务中心"></AppSubMenuTitle> |
||||
<AppTaskMenuList></AppTaskMenuList> |
||||
</template> |
||||
<template #content> |
||||
<div ref="taskContainer" class="w-full h-full overflow-auto"> |
||||
<BasicTask ref="task1" /> |
||||
<NoviceTask ref="task2" /> |
||||
<DailyTask ref="task3" /> |
||||
<OtherTask ref="task4" /> |
||||
</div> |
||||
</template> |
||||
</AppContainerBox> |
||||
</template> |
||||
|
||||
<style lang="scss" scoped> |
||||
</style> |
Loading…
Reference in new issue