Files
text-adventure-game/components/panels/LogPanel.vue
Claude 16223c89a5 feat: 实现游戏核心系统和UI组件
核心系统:
- combatSystem: 战斗逻辑、伤害计算、战斗状态管理
- skillSystem: 技能系统、技能解锁、经验值、里程碑
- taskSystem: 任务系统、任务类型、任务执行和完成
- eventSystem: 事件系统、随机事件处理
- environmentSystem: 环境系统、时间流逝、区域效果
- levelingSystem: 升级系统、属性成长
- soundSystem: 音效系统

配置文件:
- enemies: 敌人配置、掉落表
- events: 事件配置、事件效果
- items: 物品配置、装备属性
- locations: 地点配置、探索事件
- skills: 技能配置、技能树

UI组件:
- CraftingDrawer: 制造界面
- InventoryDrawer: 背包界面
- 其他UI优化和动画

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 16:20:10 +08:00

193 lines
3.5 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<scroll-view
class="log-panel"
scroll-y
:scroll-into-view="scrollToId"
:scroll-with-animation="true"
:scroll-top="scrollTop"
>
<view
v-for="log in logs"
:key="log.id"
class="log-item"
:class="`log-item--${log.type}`"
:id="'log-' + log.id"
>
<text class="log-item__icon">{{ getLogIcon(log.type) }}</text>
<text class="log-item__time">[{{ log.time }}]</text>
<text class="log-item__message">{{ log.message }}</text>
</view>
<view :id="'log-anchor-' + lastLogId" class="log-anchor"></view>
</scroll-view>
</template>
<script setup>
import { computed, watch, nextTick, ref } from 'vue'
import { useGameStore } from '@/store/game'
const game = useGameStore()
const scrollToId = ref('')
const scrollTop = ref(0)
const logs = computed(() => game.logs)
const lastLogId = computed(() => {
return logs.value.length > 0 ? logs.value[logs.value.length - 1].id : 0
})
watch(lastLogId, (newId) => {
if (newId) {
nextTick(() => {
scrollToId.value = 'log-anchor-' + newId
// 重置scrollToId以允许下次滚动
setTimeout(() => {
scrollToId.value = ''
}, 100)
})
}
}, { immediate: true })
// 获取日志类型图标
function getLogIcon(type) {
const icons = {
combat: '⚔️',
system: '🔔',
reward: '🎁',
info: '',
warning: '⚠️',
error: '❌',
success: '✅',
story: '📖'
}
return icons[type] || '•'
}
</script>
<style lang="scss" scoped>
.log-panel {
height: 100%;
padding: 12rpx 16rpx;
background-color: $bg-primary;
}
.log-item {
display: flex;
align-items: flex-start;
padding: 8rpx 12rpx;
margin-bottom: 4rpx;
border-radius: 6rpx;
background-color: $bg-secondary;
border-left: 3rpx solid transparent;
animation: slideIn 0.2s ease;
&__icon {
font-size: 20rpx;
margin-right: 8rpx;
flex-shrink: 0;
}
&__time {
color: $text-muted;
font-size: 20rpx;
margin-right: 8rpx;
flex-shrink: 0;
}
&__message {
color: $text-primary;
font-size: 24rpx;
line-height: 1.5;
flex: 1;
word-break: break-word;
}
// 不同类型的日志样式
&--combat {
background-color: rgba($danger, 0.1);
border-left-color: $danger;
.log-item__message {
color: $danger;
}
}
&--system {
background-color: rgba($accent, 0.1);
border-left-color: $accent;
.log-item__message {
color: $accent;
font-weight: 500;
}
}
&--reward {
background-color: rgba($warning, 0.1);
border-left-color: $warning;
.log-item__message {
color: $warning;
font-weight: 500;
}
}
&--info {
.log-item__message {
color: $text-secondary;
}
}
&--warning {
background-color: rgba($warning, 0.1);
border-left-color: $warning;
.log-item__message {
color: $warning;
}
}
&--error {
background-color: rgba($danger, 0.15);
border-left-color: $danger;
.log-item__message {
color: $danger;
}
}
&--success {
background-color: rgba($success, 0.1);
border-left-color: $success;
.log-item__message {
color: $success;
}
}
&--story {
background-color: rgba($info, 0.1);
border-left-color: $info;
.log-item__message {
color: $info;
font-style: italic;
}
}
}
.log-anchor {
height: 1rpx;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateX(-20rpx);
}
to {
opacity: 1;
transform: translateX(0);
}
}
</style>