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>
This commit is contained in:
Claude
2026-01-23 16:20:10 +08:00
parent 021f6a54f5
commit 16223c89a5
25 changed files with 2731 additions and 318 deletions

View File

@@ -1,10 +1,17 @@
<template>
<view
class="text-button"
:class="[`text-button--${type}`, { 'text-button--disabled': disabled }]"
:class="[
`text-button--${type}`,
{
'text-button--disabled': disabled,
'text-button--loading': loading
}
]"
@click="handleClick"
>
<text>{{ text }}</text>
<text v-if="!loading" class="text-button__text">{{ text }}</text>
<view v-else class="text-button__spinner"></view>
</view>
</template>
@@ -12,13 +19,14 @@
const props = defineProps({
text: { type: String, required: true },
type: { type: String, default: 'default' },
disabled: { type: Boolean, default: false }
disabled: { type: Boolean, default: false },
loading: { type: Boolean, default: false }
})
const emit = defineEmits(['click'])
function handleClick() {
if (!props.disabled) {
if (!props.disabled && !props.loading) {
emit('click')
}
}
@@ -26,43 +34,133 @@ function handleClick() {
<style lang="scss" scoped>
.text-button {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 16rpx 32rpx;
border-radius: 8rpx;
transition: all 0.2s;
font-size: 26rpx;
font-weight: 500;
overflow: hidden;
transition: all 0.2s ease;
user-select: none;
// 涟漪效果
&::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.3);
transform: translate(-50%, -50%);
transition: width 0.3s, height 0.3s;
}
&:active::after {
width: 200%;
height: 200%;
}
&__text {
position: relative;
z-index: 1;
}
&--default {
background-color: $bg-tertiary;
color: $text-primary;
border: 1rpx solid transparent;
&:active {
background-color: $bg-secondary;
transform: scale(0.98);
}
}
&--primary {
background-color: $accent;
color: #fff;
border: 1rpx solid $accent;
box-shadow: 0 4rpx 12rpx rgba($accent, 0.3);
&:active {
background-color: darken($accent, 10%);
transform: scale(0.98);
box-shadow: 0 2rpx 6rpx rgba($accent, 0.3);
}
}
&--danger {
background-color: rgba($danger, 0.2);
background-color: rgba($danger, 0.15);
color: $danger;
border: 1rpx solid rgba($danger, 0.3);
&:active {
background-color: rgba($danger, 0.3);
background-color: rgba($danger, 0.25);
transform: scale(0.98);
}
}
&--warning {
background-color: rgba($warning, 0.2);
background-color: rgba($warning, 0.15);
color: $warning;
border: 1rpx solid rgba($warning, 0.3);
&:active {
background-color: rgba($warning, 0.3);
background-color: rgba($warning, 0.25);
transform: scale(0.98);
}
}
&--success {
background-color: rgba($success, 0.15);
color: $success;
border: 1rpx solid rgba($success, 0.3);
&:active {
background-color: rgba($success, 0.25);
transform: scale(0.98);
}
}
&--info {
background-color: rgba($info, 0.15);
color: $info;
border: 1rpx solid rgba($info, 0.3);
&:active {
background-color: rgba($info, 0.25);
transform: scale(0.98);
}
}
&--disabled {
opacity: 0.5;
pointer-events: none;
filter: grayscale(0.5);
}
&--loading {
pointer-events: none;
}
&__spinner {
width: 32rpx;
height: 32rpx;
border: 3rpx solid rgba(255, 255, 255, 0.3);
border-top-color: #fff;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
</style>