application [child-coding-miniapp] view page [pages/levels] development

This commit is contained in:
NVWA Code Agent
2026-01-05 06:47:13 +00:00
parent 7441e65b42
commit 3b60e608c9
2 changed files with 169 additions and 0 deletions

View File

@@ -23,6 +23,12 @@
"style": { "style": {
"navigationBarTitleText": "注册" "navigationBarTitleText": "注册"
} }
},
{
"path": "pages/levels",
"style": {
"navigationBarTitleText": "关卡列表"
}
} }
], ],
"globalStyle": { "globalStyle": {

View File

@@ -0,0 +1,163 @@
<template>
<view class="levels-page">
<view class="header">
<text class="title">选择关卡</text>
</view>
<uni-list>
<uni-list-item
v-for="level in levels"
:key="level.id"
:title="level.title"
:note="level.description"
@click="enterLevel(level)"
>
<template #right>
<view class="level-info">
<view class="difficulty">难度: {{ getDifficultyText(level.difficulty) }}</view>
<view class="progress" :class="{ completed: getLevelProgress(level.id) }">
{{ getLevelProgress(level.id) ? '已完成' : '未完成' }}
</view>
</view>
</template>
</uni-list-item>
</uni-list>
</view>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { entities, auth } from '@/lib/nvwa'
interface Level {
id: number
title: string
description: string
difficulty: number
order: number
}
interface UserLevelProgress {
level_id: number
completed: boolean
}
const levels = ref<Level[]>([])
const progress = ref<UserLevelProgress[]>([])
const currentUser = ref<any>(null)
onMounted(async () => {
try {
currentUser.value = await auth.currentUser()
await loadLevels()
await loadProgress()
} catch (error) {
console.error('初始化失败:', error)
}
})
async function loadLevels() {
const { data, error } = await entities
.from('level')
.select('id, title, description, difficulty, order')
.order('order')
if (error) {
console.error('加载关卡失败:', error)
uni.showToast({
title: '加载关卡失败',
icon: 'none'
})
} else {
levels.value = data || []
}
}
async function loadProgress() {
if (!currentUser.value?.id) return
const { data, error } = await entities
.from('user_level_progress')
.select('level_id, completed')
.eq('user_id', currentUser.value.id)
if (error) {
console.error('加载进度失败:', error)
} else {
progress.value = data || []
}
}
function getLevelProgress(levelId: number): boolean {
return progress.value.find(p => p.level_id === levelId)?.completed || false
}
function getDifficultyText(difficulty: number): string {
const texts = ['萌新', '简单', '中等', '挑战', '大师']
return texts[difficulty - 1] || '未知'
}
function enterLevel(level: Level) {
// TODO: 导航到关卡游戏页面
uni.showModal({
title: '进入关卡',
content: `即将进入关卡: ${level.title}`,
success: (res) => {
if (res.confirm) {
// 暂时显示提示,后续可以导航到实际游戏页面
uni.showToast({
title: '关卡功能开发中',
icon: 'none'
})
}
}
})
}
</script>
<style scoped>
.levels-page {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.header {
text-align: center;
margin-bottom: 30px;
}
.title {
font-size: 28px;
color: white;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.level-info {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 5px;
}
.difficulty {
color: #ffd93d;
font-size: 14px;
font-weight: bold;
}
.progress {
font-size: 12px;
padding: 4px 8px;
border-radius: 12px;
color: white;
}
.progress.completed {
background-color: #4CAF50;
}
.progress:not(.completed) {
background-color: #ff6b6b;
}
</style>