feat: 优化游戏体验和系统平衡性
- 修复商店物品名称显示问题,添加堆叠物品出售数量选择 - 自动战斗状态持久化,战斗结束显示"寻找中"状态 - 战斗日志显示经验获取详情(战斗经验、武器经验) - 技能进度条显示当前/最大经验值 - 阅读自动解锁技能并持续获得阅读经验,背包可直接阅读 - 优化训练平衡:时长60秒,经验5点/秒,耐力消耗降低 - 实现自然回复系统:基于体质回复HP/耐力,休息提供3倍加成 - 战斗和训练时不进行自然回复 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -130,6 +130,34 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数量选择弹窗 -->
|
||||
<view v-if="quantitySelector" class="item-detail-popup" @click="cancelQuantitySell">
|
||||
<view class="item-detail" @click.stop>
|
||||
<text class="item-detail__name">选择出售数量</text>
|
||||
<view class="quantity-selector">
|
||||
<text class="quantity-selector__item-name">{{ quantitySelector.item.icon }} {{ quantitySelector.item.name }}</text>
|
||||
<text class="quantity-selector__available">拥有: {{ quantitySelector.maxCount }}</text>
|
||||
|
||||
<view class="quantity-selector__controls">
|
||||
<TextButton text="-" type="default" @click="decreaseSellCount" :disabled="quantitySelector.selectedCount <= 1" />
|
||||
<text class="quantity-selector__count">{{ quantitySelector.selectedCount }}</text>
|
||||
<TextButton text="+" type="default" @click="increaseSellCount" :disabled="quantitySelector.selectedCount >= quantitySelector.maxCount" />
|
||||
</view>
|
||||
|
||||
<TextButton text="全部" type="default" size="small" @click="setMaxSellCount" style="margin-top: 12rpx;" />
|
||||
|
||||
<view class="quantity-selector__preview">
|
||||
<text class="quantity-selector__price-label">预计获得:</text>
|
||||
<text class="quantity-selector__price">{{ getSellPrice(quantitySelector.item) * quantitySelector.selectedCount }} 铜币</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item-detail__actions">
|
||||
<TextButton text="确认出售" type="primary" @click="confirmQuantitySell" />
|
||||
<TextButton text="取消" @click="cancelQuantitySell" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -138,6 +166,7 @@ import { ref, computed } from 'vue'
|
||||
import { usePlayerStore } from '@/store/player'
|
||||
import { useGameStore } from '@/store/game'
|
||||
import { getShopConfig, getBuyPrice as calcBuyPrice, getSellPrice as calcSellPrice } from '@/config/shop.js'
|
||||
import { ITEM_CONFIG } from '@/config/items.js'
|
||||
import { addItemToInventory, removeItemFromInventory } from '@/utils/itemSystem.js'
|
||||
import FilterTabs from '@/components/common/FilterTabs.vue'
|
||||
import TextButton from '@/components/common/TextButton.vue'
|
||||
@@ -149,6 +178,8 @@ const currentMode = ref('buy')
|
||||
const selectedItem = ref(null)
|
||||
const bulkMode = ref(false)
|
||||
const selectedItems = ref([])
|
||||
// 数量选择弹窗状态
|
||||
const quantitySelector = ref(null) // { item: Object, maxCount: Number, selectedCount: Number }
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
@@ -171,10 +202,18 @@ const shopItems = computed(() => {
|
||||
return config.items
|
||||
.filter(item => item.stock === -1 || item.stock > 0)
|
||||
.map(shopItem => {
|
||||
const itemConfig = { ...shopItem }
|
||||
itemConfig.id = shopItem.itemId
|
||||
return itemConfig
|
||||
// 从 ITEM_CONFIG 获取完整物品信息
|
||||
const itemConfig = ITEM_CONFIG[shopItem.itemId]
|
||||
if (!itemConfig) return null
|
||||
|
||||
return {
|
||||
...itemConfig, // 复制所有物品属性(name, icon, description等)
|
||||
id: shopItem.itemId, // 使用 itemId 作为 id
|
||||
stock: shopItem.stock,
|
||||
baseStock: shopItem.baseStock
|
||||
}
|
||||
})
|
||||
.filter(Boolean)
|
||||
})
|
||||
|
||||
// 玩家可出售物品
|
||||
@@ -248,7 +287,7 @@ function isItemSelected(item) {
|
||||
// 处理出售列表点击
|
||||
function handleSellItemClick(item) {
|
||||
if (bulkMode.value) {
|
||||
// 批量模式:切换选中状态
|
||||
// 批量模式:切换选中状态(批量出售出售全部)
|
||||
const index = selectedItems.value.findIndex(i =>
|
||||
(i.uniqueId && i.uniqueId === item.uniqueId) || i.id === item.id
|
||||
)
|
||||
@@ -258,8 +297,18 @@ function handleSellItemClick(item) {
|
||||
selectedItems.value.push(item)
|
||||
}
|
||||
} else {
|
||||
// 普通模式:显示详情
|
||||
trySell(item)
|
||||
// 普通模式:检查是否是堆叠物品
|
||||
if (item.count > 1) {
|
||||
// 堆叠物品:显示数量选择弹窗
|
||||
quantitySelector.value = {
|
||||
item: item,
|
||||
maxCount: item.count,
|
||||
selectedCount: 1
|
||||
}
|
||||
} else {
|
||||
// 非堆叠物品:直接显示详情
|
||||
trySell(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,20 +387,68 @@ function confirmSell() {
|
||||
if (!selectedItem.value) return
|
||||
|
||||
const item = selectedItem.value
|
||||
const price = getSellPrice(item)
|
||||
const sellCount = item.sellCount || 1
|
||||
const price = getSellPrice(item) * sellCount
|
||||
|
||||
// 移除物品
|
||||
const result = removeItemFromInventory(player, item.uniqueId || item.id)
|
||||
const result = removeItemFromInventory(player, item.uniqueId || item.id, sellCount)
|
||||
|
||||
if (result.success) {
|
||||
// 增加金币
|
||||
player.currency.copper += price
|
||||
game.addLog(`出售了 ${item.name},获得 ${price} 铜币`, 'reward')
|
||||
const countText = sellCount > 1 ? `x${sellCount}` : ''
|
||||
game.addLog(`出售了 ${item.name}${countText},获得 ${price} 铜币`, 'reward')
|
||||
}
|
||||
|
||||
selectedItem.value = null
|
||||
}
|
||||
|
||||
// 确认数量选择出售
|
||||
function confirmQuantitySell() {
|
||||
if (!quantitySelector.value) return
|
||||
|
||||
const { item, selectedCount } = quantitySelector.value
|
||||
const price = getSellPrice(item) * selectedCount
|
||||
|
||||
// 移除指定数量的物品
|
||||
const result = removeItemFromInventory(player, item.uniqueId || item.id, selectedCount)
|
||||
|
||||
if (result.success) {
|
||||
// 增加金币
|
||||
player.currency.copper += price
|
||||
game.addLog(`出售了 ${item.name}x${selectedCount},获得 ${price} 铜币`, 'reward')
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
quantitySelector.value = null
|
||||
}
|
||||
|
||||
// 取消数量选择
|
||||
function cancelQuantitySell() {
|
||||
quantitySelector.value = null
|
||||
}
|
||||
|
||||
// 增加出售数量
|
||||
function increaseSellCount() {
|
||||
if (quantitySelector.value && quantitySelector.value.selectedCount < quantitySelector.value.maxCount) {
|
||||
quantitySelector.value.selectedCount++
|
||||
}
|
||||
}
|
||||
|
||||
// 减少出售数量
|
||||
function decreaseSellCount() {
|
||||
if (quantitySelector.value && quantitySelector.value.selectedCount > 1) {
|
||||
quantitySelector.value.selectedCount--
|
||||
}
|
||||
}
|
||||
|
||||
// 设置最大出售数量
|
||||
function setMaxSellCount() {
|
||||
if (quantitySelector.value) {
|
||||
quantitySelector.value.selectedCount = quantitySelector.value.maxCount
|
||||
}
|
||||
}
|
||||
|
||||
function close() {
|
||||
emit('close')
|
||||
}
|
||||
@@ -630,4 +727,58 @@ function close() {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
// 数量选择器样式
|
||||
.quantity-selector {
|
||||
&__item-name {
|
||||
display: block;
|
||||
color: $text-primary;
|
||||
font-size: 28rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
&__available {
|
||||
display: block;
|
||||
color: $text-secondary;
|
||||
font-size: 24rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
&__controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 24rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
&__count {
|
||||
min-width: 80rpx;
|
||||
text-align: center;
|
||||
color: $text-primary;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&__preview {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16rpx;
|
||||
background-color: $bg-tertiary;
|
||||
border-radius: 8rpx;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
&__price-label {
|
||||
color: $text-secondary;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
&__price {
|
||||
color: $accent;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user