2026-01-21 17:13:51 +08:00
|
|
|
|
<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"
|
|
|
|
|
|
>
|
2026-01-23 16:20:10 +08:00
|
|
|
|
<text class="log-item__icon">{{ getLogIcon(log.type) }}</text>
|
2026-01-21 17:13:51 +08:00
|
|
|
|
<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 })
|
2026-01-23 16:20:10 +08:00
|
|
|
|
|
|
|
|
|
|
// 获取日志类型图标
|
|
|
|
|
|
function getLogIcon(type) {
|
|
|
|
|
|
const icons = {
|
|
|
|
|
|
combat: '⚔️',
|
|
|
|
|
|
system: '🔔',
|
|
|
|
|
|
reward: '🎁',
|
|
|
|
|
|
info: 'ℹ️',
|
|
|
|
|
|
warning: '⚠️',
|
|
|
|
|
|
error: '❌',
|
|
|
|
|
|
success: '✅',
|
|
|
|
|
|
story: '📖'
|
|
|
|
|
|
}
|
|
|
|
|
|
return icons[type] || '•'
|
|
|
|
|
|
}
|
2026-01-21 17:13:51 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.log-panel {
|
|
|
|
|
|
height: 100%;
|
2026-01-23 16:20:10 +08:00
|
|
|
|
padding: 12rpx 16rpx;
|
2026-01-21 17:13:51 +08:00
|
|
|
|
background-color: $bg-primary;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.log-item {
|
|
|
|
|
|
display: flex;
|
2026-01-23 16:20:10 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-01-21 17:13:51 +08:00
|
|
|
|
|
|
|
|
|
|
&__time {
|
|
|
|
|
|
color: $text-muted;
|
2026-01-23 16:20:10 +08:00
|
|
|
|
font-size: 20rpx;
|
2026-01-21 17:13:51 +08:00
|
|
|
|
margin-right: 8rpx;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&__message {
|
|
|
|
|
|
color: $text-primary;
|
2026-01-23 16:20:10 +08:00
|
|
|
|
font-size: 24rpx;
|
2026-01-21 17:13:51 +08:00
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
flex: 1;
|
2026-01-23 16:20:10 +08:00
|
|
|
|
word-break: break-word;
|
2026-01-21 17:13:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 不同类型的日志样式
|
|
|
|
|
|
&--combat {
|
2026-01-23 16:20:10 +08:00
|
|
|
|
background-color: rgba($danger, 0.1);
|
|
|
|
|
|
border-left-color: $danger;
|
|
|
|
|
|
|
2026-01-21 17:13:51 +08:00
|
|
|
|
.log-item__message {
|
|
|
|
|
|
color: $danger;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&--system {
|
2026-01-23 16:20:10 +08:00
|
|
|
|
background-color: rgba($accent, 0.1);
|
|
|
|
|
|
border-left-color: $accent;
|
|
|
|
|
|
|
2026-01-21 17:13:51 +08:00
|
|
|
|
.log-item__message {
|
|
|
|
|
|
color: $accent;
|
2026-01-23 16:20:10 +08:00
|
|
|
|
font-weight: 500;
|
2026-01-21 17:13:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&--reward {
|
2026-01-23 16:20:10 +08:00
|
|
|
|
background-color: rgba($warning, 0.1);
|
|
|
|
|
|
border-left-color: $warning;
|
|
|
|
|
|
|
2026-01-21 17:13:51 +08:00
|
|
|
|
.log-item__message {
|
|
|
|
|
|
color: $warning;
|
2026-01-23 16:20:10 +08:00
|
|
|
|
font-weight: 500;
|
2026-01-21 17:13:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&--info {
|
|
|
|
|
|
.log-item__message {
|
|
|
|
|
|
color: $text-secondary;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&--warning {
|
2026-01-23 16:20:10 +08:00
|
|
|
|
background-color: rgba($warning, 0.1);
|
|
|
|
|
|
border-left-color: $warning;
|
|
|
|
|
|
|
2026-01-21 17:13:51 +08:00
|
|
|
|
.log-item__message {
|
|
|
|
|
|
color: $warning;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&--error {
|
2026-01-23 16:20:10 +08:00
|
|
|
|
background-color: rgba($danger, 0.15);
|
|
|
|
|
|
border-left-color: $danger;
|
|
|
|
|
|
|
2026-01-21 17:13:51 +08:00
|
|
|
|
.log-item__message {
|
|
|
|
|
|
color: $danger;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&--success {
|
2026-01-23 16:20:10 +08:00
|
|
|
|
background-color: rgba($success, 0.1);
|
|
|
|
|
|
border-left-color: $success;
|
|
|
|
|
|
|
2026-01-21 17:13:51 +08:00
|
|
|
|
.log-item__message {
|
|
|
|
|
|
color: $success;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-23 16:20:10 +08:00
|
|
|
|
|
|
|
|
|
|
&--story {
|
|
|
|
|
|
background-color: rgba($info, 0.1);
|
|
|
|
|
|
border-left-color: $info;
|
|
|
|
|
|
|
|
|
|
|
|
.log-item__message {
|
|
|
|
|
|
color: $info;
|
|
|
|
|
|
font-style: italic;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-21 17:13:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.log-anchor {
|
|
|
|
|
|
height: 1rpx;
|
|
|
|
|
|
}
|
2026-01-23 16:20:10 +08:00
|
|
|
|
|
|
|
|
|
|
@keyframes slideIn {
|
|
|
|
|
|
from {
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
transform: translateX(-20rpx);
|
|
|
|
|
|
}
|
|
|
|
|
|
to {
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
transform: translateX(0);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-21 17:13:51 +08:00
|
|
|
|
</style>
|