Commit d0ad412c by Hantao

feat(part4): 添加滤芯排序游戏页面和资源文件

- 新增游戏起始页和主游戏页面,包含完整的交互逻辑
- 添加所有游戏所需的静态资源文件(.webp格式)
- 在pages.json中注册新的游戏页面路由
- 实现拖拽排序功能,包含进度跟踪和完成验证
- 添加游戏重置和完成弹窗功能
parent edf95011
...@@ -52,6 +52,18 @@ ...@@ -52,6 +52,18 @@
} }
}, },
{ {
"path": "pages/second/part4/start",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/second/part4/index",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/third/index", "path": "pages/third/index",
"style": { "style": {
"navigationStyle": "custom" "navigationStyle": "custom"
......
...@@ -67,7 +67,7 @@ export function useDrag(options = {}) { ...@@ -67,7 +67,7 @@ export function useDrag(options = {}) {
} }
}; };
// Touch Event Handlers // 触摸事件处理程序
const handleTouchStart = (event, item) => { const handleTouchStart = (event, item) => {
if (event.touches && event.touches[0]) { if (event.touches && event.touches[0]) {
const { clientX, clientY } = event.touches[0]; const { clientX, clientY } = event.touches[0];
...@@ -86,7 +86,7 @@ export function useDrag(options = {}) { ...@@ -86,7 +86,7 @@ export function useDrag(options = {}) {
handleEnd(); handleEnd();
}; };
// Mouse Event Handlers // 鼠标事件处理程序
const handleMouseDown = (event, item) => { const handleMouseDown = (event, item) => {
handleStart(event.clientX, event.clientY, item); handleStart(event.clientX, event.clientY, item);
}; };
......
<script setup>
import { ref, computed, onMounted, getCurrentInstance } from 'vue';
import { useDrag } from '../hooks/useDrag';
const ASSETS = Object.freeze({
box: '/static/second/part4/index/box.webp',
white: '/static/second/part4/index/white.webp',
grey: '/static/second/part4/index/grey.webp',
black: '/static/second/part4/index/black.webp',
blue: '/static/second/part4/index/blue.webp',
sequence: '/static/second/part4/index/sequence.webp',
arrange: '/static/second/part4/index/arrange.webp',
white1: '/static/second/part4/index/white1.webp',
blue1: '/static/second/part4/index/blue1.webp',
black1: '/static/second/part4/index/black1.webp',
white2: '/static/second/part4/index/white2.webp',
blue2: '/static/second/part4/index/blue2.webp',
black2: '/static/second/part4/index/black2.webp',
grey2: '/static/second/part4/index/grey2.webp',
empty: '/static/second/part4/index/empty.webp',
progress1: '/static/second/part4/index/progress1.webp',
progress2: '/static/second/part4/index/progress2.webp',
progress3: '/static/second/part4/index/progress3.webp',
progress4: '/static/second/part4/index/progress4.webp',
right: '/static/second/part4/index/right.webp',
resetIcon: '/static/second/reset.webp',
blockIcon: '/static/second/block.webp',
completionPopup: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/d204d71cf2a54b18a6404e6132618cd6%E5%AE%8C%E6%88%90%E5%BC%B9%E7%AA%97.webp',
});
// 电池类型与 arrange 区域的映射关系
const BATTERY_ARRANGE_MAP = Object.freeze({
white: 'arrange1',
grey: 'arrange2',
blue: 'arrange3',
black: 'arrange4',
});
// 放置顺序配置
const ARRANGE_ORDER = ['arrange1', 'arrange2', 'arrange3', 'arrange4'];
// 热区配置:每个热区对应的电池索引
const HOTAREA_CONFIG = Object.freeze([
{ class: 'btn-white1', batteryIndex: 0 },
{ class: 'btn-white2', batteryIndex: 0 },
{ class: 'btn-white3', batteryIndex: 0 },
{ class: 'btn-grey', batteryIndex: 1 },
{ class: 'btn-black', batteryIndex: 2 },
{ class: 'btn-blue1', batteryIndex: 3 },
{ class: 'btn-blue2', batteryIndex: 3 },
]);
// 进度列表配置
const PROGRESS_LIST = Object.freeze([
{ key: 'arrange1', label: 'PP棉(1/4)' },
{ key: 'arrange2', label: '活性炭(2/4)' },
{ key: 'arrange3', label: 'RO膜(3/4)' },
{ key: 'arrange4', label: '后置炭棒(4/4)' },
]);
// 排序区域配置
const ARRANGE_CONFIG = Object.freeze([
{ key: 'arrange1', imgKey: 'white2', imgClass: 'white2' },
{ key: 'arrange2', imgKey: 'grey2', imgClass: 'grey2' },
{ key: 'arrange3', imgKey: 'blue2', imgClass: 'blue2' },
{ key: 'arrange4', imgKey: 'black2', imgClass: 'black2' },
]);
const batteryItems = ref([
{ id: 1, type: 'white', icon: ASSETS.white, dragIcon: ASSETS.white1, status: 'default' },
{ id: 2, type: 'grey', icon: ASSETS.grey, dragIcon: ASSETS.grey, status: 'default' },
{ id: 3, type: 'black', icon: ASSETS.black, dragIcon: ASSETS.black1, status: 'default' },
{ id: 4, type: 'blue', icon: ASSETS.blue, dragIcon: ASSETS.blue1, status: 'default' },
]);
const arrangeStatus = ref({
arrange1: false,
arrange2: false,
arrange3: false,
arrange4: false,
});
const arrangeRects = ref({});
// 计算已完成的排序数量
const completedCount = computed(() => {
return Object.values(arrangeStatus.value).filter(Boolean).length;
});
// 根据完成数量返回对应的进度条图片
const tasteBarImage = computed(() => {
const images = [ASSETS.empty, ASSETS.progress1, ASSETS.progress2, ASSETS.progress3, ASSETS.progress4];
return images[completedCount.value];
});
// 是否全部完成
const isComplete = computed(() => {
return completedCount.value === 4;
});
const showCompletion = ref(false);
// 重置
const handleReset = () => {
batteryItems.value.forEach(item => {
item.status = 'default';
});
Object.keys(arrangeStatus.value).forEach(key => {
arrangeStatus.value[key] = false;
});
};
// 完成
const handleComplete = () => {
if (isComplete.value) {
showCompletion.value = true;
}
};
// 关闭弹窗
const closeCompletion = () => {
showCompletion.value = false;
};
const instance = getCurrentInstance();
onMounted(() => {
const query = uni.createSelectorQuery().in(instance);
Object.values(BATTERY_ARRANGE_MAP).forEach(name => {
query.select(`.${name}`).boundingClientRect(data => {
if (data) arrangeRects.value[name] = data;
});
});
query.exec();
});
// 获取电池图标
const getBatteryIcon = (item) => {
return draggedItem.value?.id === item.id ? item.dragIcon : item.icon;
};
// 获取拖拽镜像图标
const getGhostIcon = () => draggedItem.value?.dragIcon || '';
// 获取拖拽电池类型
const getDraggedType = () => draggedItem.value?.type || '';
// 判断电池是否正在被拖拽
const isDraggingItem = (item) => {
return isDragging.value && draggedItem.value?.id === item.id;
};
// 判断电池是否应该显示
const shouldShowBattery = (item) => {
return !isDraggingItem(item) && item.status !== 'placed';
};
// 检测坐标是否在矩形区域内
const isInRect = (position, rect) => {
if (!rect) return false;
const { x, y } = position;
return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
};
// 检测并处理放置结果
const checkAndPlace = (item, position) => {
const targetArrange = BATTERY_ARRANGE_MAP[item.type];
const targetRect = arrangeRects.value[targetArrange];
// 检查前置是否已放置
const currentIndex = ARRANGE_ORDER.indexOf(targetArrange);
if (currentIndex > 0) {
const prevArrange = ARRANGE_ORDER[currentIndex - 1];
if (!arrangeStatus.value[prevArrange]) {
return;
}
}
if (isInRect(position, targetRect)) {
arrangeStatus.value[targetArrange] = true;
item.status = 'placed';
}
};
// 拖拽逻辑
const {
isDragging,
draggedItem,
dragPosition,
handleTouchStart,
handleTouchMove,
handleTouchEnd,
handleMouseDown,
handleMouseMove,
handleMouseUp,
} = useDrag({
onDrop: (item, position) => {
if (item) checkAndPlace(item, position);
}
});
</script>
<template>
<view class="part4-container">
<!-- 拖拽镜像 -->
<view
v-if="isDragging"
class="drag-ghost"
:style="{ left: `${dragPosition.x}px`, top: `${dragPosition.y}px` }"
>
<image
:src="getGhostIcon()"
mode="scaleToFill"
:class="['ghost-icon', `ghost-${getDraggedType()}`]"
/>
</view>
<!-- 标题 -->
<view class="title">滤芯排序游戏</view>
<!-- 排序区域 -->
<image :src="ASSETS.arrange" mode="scaleToFill" class="arrange" />
<view
v-for="item in ARRANGE_CONFIG"
:key="item.key"
:class="[item.key, { 'arrange-active': arrangeStatus[item.key] }]"
>
<image
v-show="arrangeStatus[item.key]"
:src="ASSETS[item.imgKey]"
mode="scaleToFill"
:class="item.imgClass"
/>
</view>
<!-- 提示图 -->
<image :src="ASSETS.sequence" mode="scaleToFill" class="sequence" />
<!-- 排序进度 -->
<view class="progress">
<view class="progress-title">排序进度</view>
<view class="progress-list">
<view v-for="item in PROGRESS_LIST" :key="item.key" class="progress-item">
<image v-if="arrangeStatus[item.key]" :src="ASSETS.right" mode="scaleToFill" class="progress-icon-done" />
<view v-else class="progress-icon"><view class="progress-icon-inner"></view></view>
<text class="progress-text">{{ item.label }}</text>
</view>
</view>
<view class="taste-section">
<text class="taste-label">口感指数</text>
<text class="taste-value">{{ completedCount * 25 }}%</text>
</view>
<image :src="tasteBarImage" mode="scaleToFill" class="taste-bar" />
</view>
<!-- 电池盒 -->
<image :src="ASSETS.box" mode="scaleToFill" class="box" />
<!-- 电池区域 -->
<view class="battery">
<!-- 电池图片 -->
<image
v-for="(item, index) in batteryItems"
:key="item.id"
v-show="shouldShowBattery(item)"
:src="getBatteryIcon(item)"
mode="scaleToFill"
:class="item.type"
/>
<!-- 拖拽热区 -->
<view
v-for="hotarea in HOTAREA_CONFIG"
:key="hotarea.class"
:class="['btn', hotarea.class]"
@touchstart="handleTouchStart($event, batteryItems[hotarea.batteryIndex])"
@touchmove.stop.prevent="handleTouchMove"
@touchend="handleTouchEnd"
@mousedown="handleMouseDown($event, batteryItems[hotarea.batteryIndex])"
@mousemove="handleMouseMove"
@mouseup="handleMouseUp"
/>
</view>
<!-- 底部按钮 -->
<view class="btn-group">
<view class="action-btn reset-btn" @click="handleReset">
<image class="btn-icon" :src="ASSETS.resetIcon" mode="widthFix" />
<text>重置</text>
</view>
<view
:class="['action-btn', 'complete-btn', { 'complete-btn-active': isComplete }]"
@click="handleComplete"
>
<image v-if="!isComplete" class="btn-icon block-icon" :src="ASSETS.blockIcon" mode="widthFix" />
<text class="complete-text">完成</text>
</view>
</view>
<!-- 完成弹窗 -->
<view class="completion-overlay" v-if="showCompletion" @click="closeCompletion">
<image
class="completion-img"
:src="ASSETS.completionPopup"
mode="scaleToFill"
@click.stop="closeCompletion"
/>
</view>
</view>
</template>
<style lang="scss" scoped>
.part4-container {
width: 100vw;
height: 100vh;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
background-color: #77CFF8;
box-sizing: border-box;
}
.title {
margin-top: 188rpx;
margin-bottom: 30rpx;
color: #2D4B5D;
font-size: 48rpx;
font-weight: 600;
text-shadow: 1rpx 1rpx 0 #FFF, -1rpx -1rpx 0 #FFF, 1rpx -1rpx 0 #FFF, -1rpx 1rpx 0 #FFF;
z-index: 1;
}
.arrange {
position: absolute;
left: 40rpx;
top: 280rpx;
width: 382rpx;
height: 768rpx;
}
.arrange-active {
background-color: #00CC99;
}
.arrange1,
.arrange2,
.arrange3,
.arrange4 {
position: absolute;
left: 100rpx;
width: 290rpx;
height: 131rpx;
border: 12rpx;
}
.arrange1 {
top: 320rpx;
.white2 {
position: absolute;
left: -16rpx;
top: -96rpx;
width: 330rpx;
height: 330rpx;
}
}
.arrange2 {
top: 499rpx;
.grey2 {
position: absolute;
left: 20rpx;
top: 20rpx;
width: 260rpx;
height: 98rpx;
}
}
.arrange3 {
top: 677rpx;
.blue2 {
position: absolute;
left: 0;
top: -44rpx;
width: 298rpx;
height: 224rpx;
}
}
.arrange4 {
top: 855rpx;
.black2 {
position: absolute;
left: -12rpx;
top: -92rpx;
width: 324rpx;
height: 324rpx;
}
}
.sequence {
position: absolute;
right: 14rpx;
top: 308rpx;
width: 304rpx;
height: 218rpx;
}
.progress {
position: absolute;
right: 26rpx;
top: 540rpx;
width: 280rpx;
background: #FFFFFF;
border-radius: 24rpx;
padding: 20rpx;
box-sizing: border-box;
border: 4rpx solid #000;
box-shadow: 0 6rpx 0 0 #00000040, 0 -12rpx 0 0 #77D1F6 inset;
}
.progress-title {
font-size: 32rpx;
font-weight: 600;
color: #000000;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 16rpx;
background: #AFE5FB;
border-radius: 12rpx 12rpx 0 0;
height: 62rpx;
}
.progress-list {
display: flex;
flex-direction: column;
gap: 12rpx;
}
.progress-item {
display: flex;
align-items: center;
gap: 12rpx;
}
.progress-icon {
width: 24rpx;
height: 24rpx;
border-radius: 50%;
border: 2rpx solid #8B9294;
background: #F5F5F8;
flex-shrink: 0;
display: flex;
justify-content: center;
align-items: center;
}
.progress-icon-inner {
width: 16rpx;
height: 16rpx;
border-radius: 16rpx;
background: #D9D9D9;
}
.progress-icon-done {
width: 24rpx;
height: 24rpx;
flex-shrink: 0;
}
.progress-text {
font-size: 28rpx;
color: #000000;
white-space: nowrap;
}
.taste-section {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 16rpx;
margin-bottom: 8rpx;
}
.taste-label {
font-size: 24rpx;
color: #000000;
font-weight: 600;
}
.taste-value {
font-size: 24rpx;
color: #000000;
font-weight: 600;
text-shadow: 1rpx 1rpx 0 #FFF, -1rpx -1rpx 0 #FFF, 1rpx -1rpx 0 #FFF, -1rpx 1rpx 0 #FFF;
z-index: 1;
}
.taste-bar {
width: 100%;
height: 40rpx;
}
.box {
position: absolute;
bottom: 74rpx;
width: 354rpx;
height: 598rpx;
transform: rotate(90deg);
}
.white,
.grey,
.black,
.blue {
position: absolute;
}
.white {
bottom: 274rpx;
left: 142rpx;
width: 330rpx;
height: 330rpx;
z-index: 4;
}
.grey {
bottom: 216rpx;
left: 128rpx;
width: 258rpx;
height: 248rpx;
z-index: 5;
}
.black {
bottom: 226rpx;
left: 326rpx;
width: 310rpx;
height: 314rpx;
z-index: 6;
}
.blue {
bottom: 194rpx;
right: 100rpx;
width: 276rpx;
height: 308rpx;
z-index: 5;
}
.btn {
position: absolute;
z-index: 20;
}
.btn-white1 {
bottom: 397rpx;
left: 245rpx;
width: 104rpx;
height: 84rpx;
}
.btn-white2 {
bottom: 439rpx;
left: 188rpx;
width: 60rpx;
height: 45rpx;
}
.btn-white3 {
bottom: 447rpx;
left: 342rpx;
width: 86rpx;
height: 36rpx;
}
.btn-grey {
bottom: 274rpx;
left: 124rpx;
width: 268rpx;
height: 98rpx;
transform: rotate(40deg);
}
.btn-black {
bottom: 346rpx;
left: 352rpx;
width: 246rpx;
height: 68rpx;
transform: rotate(18deg);
}
.btn-blue1 {
bottom: 244rpx;
right: 250rpx;
width: 87rpx;
height: 96rpx;
transform: rotate(-38deg);
}
.btn-blue2 {
bottom: 387rpx;
right: 138rpx;
width: 46rpx;
height: 80rpx;
transform: rotate(-38deg);
}
.drag-ghost {
position: fixed;
z-index: 9999;
transform: translate(-50%, -50%);
pointer-events: none;
.ghost-icon {
display: block;
}
.ghost-white {
width: 448rpx;
height: 456rpx;
}
.ghost-grey {
width: 258rpx;
height: 248rpx;
}
.ghost-black {
width: 456rpx;
height: 442rpx;
}
.ghost-blue {
width: 418rpx;
height: 456rpx;
}
}
.btn-group {
position: absolute;
bottom: 60rpx;
left: 50%;
transform: translateX(-50%);
display: flex;
justify-content: center;
gap: 80rpx;
z-index: 20;
.action-btn {
display: flex;
justify-content: center;
align-items: center;
border-radius: 42rpx;
height: 84rpx;
box-sizing: border-box;
}
.reset-btn {
width: 230rpx;
background: #BAC4CA;
box-shadow: 0 6rpx 2rpx 0 #529bbda6, 0 4rpx 4rpx 0 #ffffff8c inset;
border: 2rpx solid #000000;
color: #5E5C5C;
font-size: 34rpx;
font-weight: bold;
.btn-icon {
width: 44rpx;
height: 44rpx;
margin-right: 10rpx;
}
}
.complete-btn {
width: 230rpx;
background: #5EB6F0;
border: 2rpx solid #000000;
box-shadow: 0 6rpx 2rpx 0 #529bbda6, 0 4rpx 2rpx 0 #76DDEE inset;
color: #134571;
.block-icon {
width: 44rpx;
height: auto;
margin-right: 16rpx;
}
.complete-text {
font-size: 34rpx;
font-weight: bold;
}
&.complete-btn-active {
background: #FAD43E;
box-shadow: 0 4rpx 2rpx 0 #ffffff80 inset, 0 6rpx 2rpx 0 #3d330ba6;
}
}
}
.completion-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
.completion-img {
width: 100%;
height: 100%;
}
}
</style>
<script setup>
const ASSETS = Object.freeze({
bg: '/static/second/part4/start/bg.webp',
battery1: '/static/second/part4/start/1.webp',
battery2: '/static/second/part4/start/2.webp',
battery3: '/static/second/part4/start/3.webp',
battery4: '/static/second/part4/start/4.webp',
Info1: '/static/second/part4/start/1-info.webp',
Info2: '/static/second/part4/start/2-info.webp',
Info3: '/static/second/part4/start/3-info.webp',
Info4: '/static/second/part4/start/4-info.webp',
battery: '/static/second/part4/start/battery.webp',
dragBg: '/static/second/part4/start/drag-bg.webp',
right: '/static/second/part4/start/right.webp',
sz: '/static/sz.webp',
jt: '/static/second/part4/start/jt.webp',
});
</script>
<template>
<view class="container">
<image class="bg-img" :src="ASSETS.bg" mode="aspectFill" />
<view class="title">滤芯排序游戏</view>
<view class="info">
<view class="info-battery">
<image class="battery-item1" :src="ASSETS.battery1" mode="scaleToFill" />
<image class="info-icon1" :src="ASSETS.Info1" mode="scaleToFill" />
<image class="battery-item2" :src="ASSETS.battery2" mode="scaleToFill" />
<image class="info-icon2" :src="ASSETS.Info2" mode="scaleToFill" />
<image class="battery-item3" :src="ASSETS.battery3" mode="scaleToFill" />
<image class="info-icon3" :src="ASSETS.Info3" mode="scaleToFill" />
<image class="battery-item4" :src="ASSETS.battery4" mode="scaleToFill" />
<image class="info-icon4" :src="ASSETS.Info4" mode="scaleToFill" />
</view>
<!-- 右侧交互区域 -->
<image class="drag-battery" :src="ASSETS.battery" mode="scaleToFill" />
<image class="arrow-icon" :src="ASSETS.jt" mode="scaleToFill" />
<image class="finger-icon" :src="ASSETS.sz" mode="scaleToFill" />
<view class="battery-container"></view>
<image class="drag-bg" :src="ASSETS.dragBg" mode="scaleToFill" />
<view class="hint-text">拖到这里!</view>
<image class="right-icon" :src="ASSETS.right" mode="scaleToFill" />
</view>
<view class="desc">
<view class="desc-text">后置碳棒在第四层!</view>
<view class="desc-text">它能改善水的口感,让水更甘甜!</view>
<view class="desc-text">按照水流方向排列</view>
<view class="desc-text">每一层都很重要</view>
</view>
</view>
</template>
<style scoped lang="scss">
.container {
width: 100vw;
height: 100vh;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
box-sizing: border-box;
}
.bg-img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
}
.title {
margin-top: 228rpx;
margin-bottom: 30rpx;
justify-content: space-between;
align-items: center;
color: #2D4B5D;
font-size: 48rpx;
font-weight: 600;
text-shadow: 1rpx 1rpx 0 #FFF, -1rpx -1rpx 0 #FFF, 1rpx -1rpx 0 #FFF, -1rpx 1rpx 0 #FFF;
z-index: 1;
}
.info {
width: 686rpx;
height: 720rpx;
background: #FFF;
border-radius: 24rpx;
border: 4rpx solid #000;
margin-top: 20rpx;
z-index: 1;
position: relative;
.info-battery {
margin: 32rpx auto 32rpx 10rpx;
border-radius: 12rpx;
width: 420rpx;
height: 654rpx;
background: #E4F6FD;
position: relative;
.battery-item1 {
position: absolute;
left: 40%;
transform: translateX(-50%);
top: -100rpx;
width: 364rpx;
height: 362rpx;
}
.battery-item2 {
position: absolute;
left: 38%;
transform: translateX(-50%);
top: 186rpx;
width: 312rpx;
height: 106rpx;
}
.battery-item3 {
position: absolute;
left: 38%;
transform: translateX(-50%);
top: 276rpx;
width: 330rpx;
height: 248rpx;
}
.battery-item4 {
position: absolute;
left: 40%;
transform: translateX(-50%);
top: 388rpx;
width: 356rpx;
height: 354rpx;
}
.info-icon1 {
position: absolute;
right: 20rpx;
top: 40rpx;
width: 70rpx;
height: 70rpx;
}
.info-icon2 {
position: absolute;
right: 20rpx;
top: 200rpx;
width: 72rpx;
height: 72rpx;
}
.info-icon3 {
position: absolute;
right: 20rpx;
top: 350rpx;
width: 66rpx;
height: 78rpx;
}
.info-icon4 {
position: absolute;
right: 16rpx;
top: 518rpx;
width: 74rpx;
height: 82rpx;
}
}
.drag-battery {
position: absolute;
right: 24rpx;
top: 24rpx;
width: 220rpx;
height: 200rpx;
z-index: 2;
}
.arrow-icon {
position: absolute;
right: 148rpx;
top: 176rpx;
width: 52rpx;
height: 148rpx;
z-index: 3;
}
.finger-icon {
position: absolute;
top: 100rpx;
right: 0;
width: 170rpx;
height: 170rpx;
z-index: 2;
}
.battery-container {
background: #B1B5B7;
box-shadow: 0 10rpx 0 0 #00000040 inset;
border: 4rpx solid #000;
border-radius: 12rpx;
position: absolute;
right: 24rpx;
top: 290rpx;
width: 184rpx;
height: 86rpx;
z-index: 2;
}
.drag-bg {
position: absolute;
right: 24rpx;
top: 408rpx;
width: 184rpx;
height: 86rpx;
z-index: 2;
}
.hint-text {
color: #000000;
font-weight: 600;
font-size: 32rpx;
position: absolute;
right: 30rpx;
top: 432rpx;
z-index: 3;
}
.right-icon {
position: absolute;
right: 58rpx;
top: 524rpx;
width: 140rpx;
height: 140rpx;
z-index: 3;
}
}
.desc {
margin-top: 28rpx;
row-gap: 12rpx;
border-radius: 24rpx;
border: 4rpx solid #000;
background: #E4F6FD;
width: 528rpx;
height: 260rpx;
z-index: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.desc-text {
color: #2D4B5D;
font-size: 34rpx;
font-weight: 600;
text-shadow: 1rpx 1rpx 0 #FFF, -1rpx -1rpx 0 #FFF, 1rpx -1rpx 0 #FFF, -1rpx 1rpx 0 #FFF;
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment