You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
413 lines
11 KiB
413 lines
11 KiB
<template> |
|
<div class="flex justify-between items-center h-[64px] px-5 bg-white"> |
|
<h1>金融产品设计及数字化营销沙盘系统</h1> |
|
<div class="inline-flex items-center"> |
|
<el-tooltip effect="light" |
|
content="退出实训" |
|
placement="bottom"> |
|
<img class="mr-3 cursor-pointer" |
|
src="@/assets/images/11.png" |
|
alt="" |
|
@click="logout" /> |
|
</el-tooltip> |
|
</div> |
|
</div> |
|
<div class="relative h-[calc(100vh-64px)] pt-5 pl-5 bg-[url('@/assets/images/level/4.png')] bg-[length:100%_100%] bg-no-repeat bg-fixed overflow-auto" |
|
id="wrap"> |
|
<div class="fixed z-10"> |
|
<div class="w-[354px] h-[68px] bg-[url('@/assets/images/level/5.png')] bg-[length:100%_100%] bg-no-repeat"></div> |
|
<div class="absolute top-5 left-40 flex items-center cursor-pointer" |
|
@click="getLevel(1)"> |
|
<img v-if="collected" |
|
src="@/assets/images/level/7.png" |
|
alt="" /> |
|
<img v-else |
|
src="@/assets/images/level/6.png" |
|
alt="" /> |
|
<span class="ml-2 text-sm text-[#999]">仅显示已收藏的关卡</span> |
|
</div> |
|
</div> |
|
<div class="relative mt-20"> |
|
<div v-for="(item, i) in levels" |
|
:key="i" |
|
:class="['item', { active: curLevel === item.checkpointId }]" |
|
@click="selecLevel(item)"> |
|
<span class="num">LV.{{ item.serialNumber }}</span> |
|
<div class="texts"> |
|
<h6>第{{ numToChinese(item.serialNumber) }}关</h6> |
|
<p class="des mul-ellipsis2">{{ item.customsPassName }}</p> |
|
<img v-if="item.collect" |
|
class="icon" |
|
src="@/assets/images/level/star2.png" |
|
alt="" |
|
@click.stop="collectItem(item)" /> |
|
<img v-else |
|
class="icon" |
|
src="@/assets/images/level/star1.png" |
|
alt="" |
|
@click.stop="collectItem(item)" /> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div class="arrow top-[68px] left-[50%] translate-x-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-up.png')]" |
|
@click="move('up')"></div> |
|
<div class="arrow right-0 top-[50%] translate-y-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-right.png')]" |
|
@click="move('right')"></div> |
|
<div class="arrow bottom-0 left-[50%] translate-x-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-down.png')]" |
|
@click="move('down')"></div> |
|
<div class="arrow left-0 top-[50%] translate-y-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-left.png')]" |
|
@click="move('left')"></div> |
|
<div class="fixed bottom-2 right-1 w-[262px] h-[74px] bg-[url('@/assets/images/level/submit.png')] bg-[length:100%_100%] bg-no-repeat cursor-pointer hover:bg-[url('@/assets/images/level/submit-hover.png')]" |
|
@click="toRole"></div> |
|
</div> |
|
<Panel /> |
|
</template> |
|
|
|
<script setup lang="ts"> |
|
import { ref, onMounted, provide } from 'vue'; |
|
import { cancelCollection, collect } from '@/api/bank'; |
|
import { checkPointListByStu } from '@/api/config'; |
|
import Panel from '@/components/Panel/index.vue'; |
|
import { useRouter, useRoute } from 'vue-router'; |
|
import { ElMessage } from 'element-plus'; |
|
import { logout } from '@/store/useCurrentUser'; |
|
import { numToChinese } from '@/utils/common'; |
|
import Cookies from 'js-cookie'; |
|
|
|
const router = useRouter(); |
|
const route = useRoute(); |
|
const collected = ref<boolean>(false); |
|
const curLevel = ref<number | string>(''); |
|
const levels = ref<Record<string, any>[]>([]); |
|
const projectId = Cookies.get('sand-projectId') ?? route.query.projectId; |
|
// 关卡列表 |
|
const getLevel = async (only: any = '') => { |
|
if (only) collected.value = !collected.value; |
|
const { data } = await checkPointListByStu(+projectId, collected.value ? 1 : ''); |
|
levels.value = data; |
|
}; |
|
provide('getLevel', getLevel); |
|
// 点击关卡回调 |
|
const selecLevel = (item: Record<string, any>) => { |
|
curLevel.value = item.checkpointId; |
|
}; |
|
// 收藏 |
|
const collectItem = async (item: Record<string, any>) => { |
|
if (item.collect) { |
|
await cancelCollection(item.favoriteId); |
|
} else { |
|
await collect({ |
|
checkpointId: item.checkpointId, |
|
projectId, |
|
}); |
|
} |
|
getLevel(); |
|
}; |
|
// 确定 |
|
const toRole = () => { |
|
if (curLevel.value) { |
|
Cookies.set('sand-level', curLevel.value); |
|
router.push({ |
|
path: `/role`, |
|
query: { |
|
levelId: curLevel.value, |
|
}, |
|
}); |
|
} else { |
|
ElMessage.error('请选择关卡!'); |
|
} |
|
}; |
|
const move = (dir: string) => { |
|
const el = document.querySelector('#wrap'); |
|
const param = { |
|
behavior: 'smooth', |
|
}; |
|
if (dir === 'left' || dir === 'right') param.left = el.scrollLeft + (dir === 'left' ? -150 : 150); |
|
if (dir === 'up' || dir === 'down') param.top = el.scrollTop + (dir === 'up' ? -150 : 150); |
|
el.scrollTo(param); |
|
}; |
|
onMounted(() => { |
|
getLevel(); |
|
}); |
|
</script> |
|
|
|
<style lang="scss" scoped> |
|
@mixin verticalLine { |
|
@apply left-[108px] h-[98px] bg-[url('@/assets/images/level/line3.png')]; |
|
} |
|
.item { |
|
--w: 330px; |
|
--line2: 160px; |
|
--line3: 360px; |
|
--line4: 520px; |
|
--line5: 680px; |
|
--line6: 840px; |
|
--line7: 1000px; |
|
--line8: 1160px; |
|
--line9: 1320px; |
|
--line10: 1480px; |
|
@apply absolute w-[218px] h-[120px] text-white bg-[url('@/assets/images/level/8.png')] bg-[length:100%_100%] bg-no-repeat cursor-pointer; |
|
&:before, |
|
&:after { |
|
content: ''; |
|
@apply absolute top-[86%] left-[100px] w-[90px] h-[70px] bg-[length:auto] bg-no-repeat; |
|
} |
|
.num { |
|
@apply absolute bottom-[37px] left-[12px] w-[60px] font-['DIN-BlackItalic'] text-center; |
|
text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2); |
|
} |
|
.texts { |
|
@apply pl-[90px] pt-[10px] pr-[13px]; |
|
} |
|
h6 { |
|
@apply text-[#FFB627] text-lg font-['AlibabaPuHuiTi_2_105_Heavy'] rounded-[24px]; |
|
text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2); |
|
background: linear-gradient(180deg, #fffcf0 0%, #ffc868 100%); |
|
-webkit-background-clip: text; |
|
-webkit-text-fill-color: transparent; |
|
} |
|
.des { |
|
@apply text-sm leading-[20px]; |
|
text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2); |
|
} |
|
.icon { |
|
@apply absolute top-[13px] right-[11px]; |
|
} |
|
&:hover { |
|
@apply opacity-80; |
|
} |
|
&.active { |
|
@apply bg-[url('@/assets/images/level/10.png')]; |
|
h6 { |
|
@apply bg-none; |
|
text-shadow: none; |
|
-webkit-text-fill-color: #fff; |
|
} |
|
} |
|
|
|
&:nth-child(2) { |
|
@apply top-[var(--line2)] left-[160px]; |
|
} |
|
&:nth-child(3) { |
|
@apply left-[var(--w)]; |
|
} |
|
&:nth-child(4) { |
|
@apply top-[var(--line2)] left-[510px]; |
|
} |
|
&:nth-child(5) { |
|
@apply left-[calc(var(--w)*2)]; |
|
} |
|
&:nth-child(6) { |
|
@apply top-[var(--line2)] left-[820px]; |
|
} |
|
&:nth-child(7) { |
|
@apply left-[calc(var(--w)*3)]; |
|
} |
|
&:nth-child(8) { |
|
@apply top-[var(--line2)] left-[1170px]; |
|
} |
|
&:nth-child(9) { |
|
@apply left-[calc(var(--w)*4)]; |
|
} |
|
&:nth-child(10) { |
|
@apply top-[var(--line2)] left-[1500px]; |
|
&:before { |
|
display: none; |
|
} |
|
&:after { |
|
@include verticalLine; |
|
} |
|
} |
|
&:nth-child(11) { |
|
@apply top-[var(--line3)] left-[1500px]; |
|
&:before { |
|
@apply left-[40px] bg-[url('@/assets/images/level/line2.png')]; |
|
transform: rotateX(180deg); |
|
} |
|
&:after { |
|
display: none; |
|
} |
|
} |
|
&:nth-child(12) { |
|
@apply top-[var(--line4)] left-[calc(var(--w)*4)]; |
|
} |
|
&:nth-child(13) { |
|
@apply top-[var(--line3)] left-[1170px]; |
|
} |
|
&:nth-child(14) { |
|
@apply top-[var(--line4)] left-[calc(var(--w)*3)]; |
|
} |
|
&:nth-child(15) { |
|
@apply top-[var(--line3)] left-[820px]; |
|
} |
|
&:nth-child(16) { |
|
@apply top-[var(--line4)] left-[calc(var(--w)*2)]; |
|
} |
|
&:nth-child(17) { |
|
@apply top-[var(--line3)] left-[510px]; |
|
} |
|
&:nth-child(18) { |
|
@apply top-[var(--line4)] left-[var(--w)]; |
|
} |
|
&:nth-child(19) { |
|
@apply top-[var(--line3)] left-[160px]; |
|
} |
|
&:nth-child(20) { |
|
@apply top-[var(--line4)]; |
|
&:after { |
|
@include verticalLine; |
|
} |
|
} |
|
|
|
&:nth-child(odd) { |
|
&:before { |
|
@apply left-[40px] bg-[url('@/assets/images/level/line2.png')]; |
|
transform: rotateX(180deg); |
|
} |
|
&:after { |
|
@apply bg-[url('@/assets/images/level/line2.png')]; |
|
} |
|
} |
|
&:first-child { |
|
z-index: 1; |
|
&:before { |
|
display: none; |
|
} |
|
&:after { |
|
@apply bg-[url('@/assets/images/level/line2.png')]; |
|
} |
|
} |
|
&:nth-child(21) { |
|
@apply top-[var(--line5)]; |
|
&:before { |
|
display: none; |
|
} |
|
} |
|
&:nth-child(22) { |
|
@apply top-[var(--line6)] left-[160px]; |
|
} |
|
&:nth-child(23) { |
|
@apply top-[var(--line5)] left-[var(--w)]; |
|
} |
|
&:nth-child(24) { |
|
@apply top-[var(--line6)] left-[510px]; |
|
} |
|
&:nth-child(25) { |
|
@apply top-[var(--line5)] left-[calc(var(--w)*2)]; |
|
} |
|
&:nth-child(26) { |
|
@apply top-[var(--line6)] left-[820px]; |
|
} |
|
&:nth-child(27) { |
|
@apply top-[var(--line5)] left-[calc(var(--w)*3)]; |
|
} |
|
&:nth-child(28) { |
|
@apply top-[var(--line6)] left-[1170px]; |
|
} |
|
&:nth-child(29) { |
|
@apply top-[var(--line5)] left-[calc(var(--w)*4)]; |
|
} |
|
&:nth-child(30) { |
|
@apply top-[var(--line6)] left-[1500px]; |
|
&:before { |
|
display: none; |
|
} |
|
&:after { |
|
@include verticalLine; |
|
} |
|
} |
|
&:nth-child(31) { |
|
@apply top-[var(--line7)] left-[1500px]; |
|
&:before { |
|
@apply left-[40px] bg-[url('@/assets/images/level/line2.png')]; |
|
transform: rotateX(180deg); |
|
} |
|
&:after { |
|
display: none; |
|
} |
|
} |
|
&:nth-child(32) { |
|
@apply top-[var(--line8)] left-[calc(var(--w)*4)]; |
|
} |
|
&:nth-child(33) { |
|
@apply top-[var(--line7)] left-[1170px]; |
|
} |
|
&:nth-child(34) { |
|
@apply top-[var(--line8)] left-[calc(var(--w)*3)]; |
|
} |
|
&:nth-child(35) { |
|
@apply top-[var(--line7)] left-[820px]; |
|
} |
|
&:nth-child(36) { |
|
@apply top-[var(--line8)] left-[calc(var(--w)*2)]; |
|
} |
|
&:nth-child(37) { |
|
@apply top-[var(--line7)] left-[510px]; |
|
} |
|
&:nth-child(38) { |
|
@apply top-[var(--line8)] left-[var(--w)]; |
|
} |
|
&:nth-child(39) { |
|
@apply top-[var(--line7)] left-[160px]; |
|
} |
|
&:nth-child(40) { |
|
@apply top-[var(--line8)]; |
|
&:after { |
|
@include verticalLine; |
|
} |
|
} |
|
&:nth-child(41) { |
|
@apply top-[var(--line9)]; |
|
&:before { |
|
display: none; |
|
} |
|
} |
|
&:nth-child(42) { |
|
@apply top-[var(--line10)] left-[160px]; |
|
} |
|
&:nth-child(43) { |
|
@apply top-[var(--line9)] left-[var(--w)]; |
|
} |
|
&:nth-child(44) { |
|
@apply top-[var(--line10)] left-[510px]; |
|
} |
|
&:nth-child(45) { |
|
@apply top-[var(--line9)] left-[calc(var(--w)*2)]; |
|
} |
|
&:nth-child(46) { |
|
@apply top-[var(--line10)] left-[820px]; |
|
} |
|
&:nth-child(47) { |
|
@apply top-[var(--line9)] left-[calc(var(--w)*3)]; |
|
} |
|
&:nth-child(48) { |
|
@apply top-[var(--line10)] left-[1170px]; |
|
} |
|
&:nth-child(49) { |
|
@apply top-[var(--line9)] left-[calc(var(--w)*4)]; |
|
} |
|
// &:last-child { |
|
// &:before { |
|
// display: none; |
|
// } |
|
// } |
|
} |
|
.arrow { |
|
@apply fixed bg-[length:100%_100%] bg-no-repeat animate-bounce cursor-pointer; |
|
} |
|
|
|
@keyframes bounce { |
|
0%, |
|
100% { |
|
// transform: translateY(-250%); |
|
margin-top: -10px; |
|
animation-timing-function: cubic-bezier(0.8, 0, 1, 1); |
|
} |
|
50% { |
|
// transform: translateY(0); |
|
margin-top: 0; |
|
animation-timing-function: cubic-bezier(0, 0, 0.2, 1); |
|
} |
|
} |
|
</style>
|
|
|