634 lines
14 KiB
Vue
634 lines
14 KiB
Vue
|
|
<template>
|
|||
|
|
<view class="shop-drawer">
|
|||
|
|
<view class="drawer-header">
|
|||
|
|
<view class="header-left">
|
|||
|
|
<text class="drawer-title">{{ shopConfig.icon }} {{ shopConfig.name }}</text>
|
|||
|
|
<text class="drawer-owner">{{ shopConfig.owner }}</text>
|
|||
|
|
</view>
|
|||
|
|
<text class="drawer-close" @click="close">×</text>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 玩家货币显示 -->
|
|||
|
|
<view class="currency-display">
|
|||
|
|
<text class="currency-label">你的金币:</text>
|
|||
|
|
<text class="currency-value">{{ formatCurrency(player.currency.copper) }}</text>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 买/卖切换 -->
|
|||
|
|
<FilterTabs
|
|||
|
|
:tabs="modeTabs"
|
|||
|
|
:modelValue="currentMode"
|
|||
|
|
@update:modelValue="currentMode = $event"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<!-- 批量操作栏(仅出售模式) -->
|
|||
|
|
<view v-if="currentMode === 'sell'" class="bulk-actions">
|
|||
|
|
<view class="bulk-actions__left">
|
|||
|
|
<text class="bulk-actions__count">已选: {{ selectedItems.length }}</text>
|
|||
|
|
<text class="bulk-actions__total">总价: {{ totalSellPrice }}铜</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="bulk-actions__right">
|
|||
|
|
<text
|
|||
|
|
v-if="!bulkMode"
|
|||
|
|
class="bulk-actions__link"
|
|||
|
|
@click="bulkMode = true"
|
|||
|
|
>
|
|||
|
|
批量出售
|
|||
|
|
</text>
|
|||
|
|
<template v-else>
|
|||
|
|
<text class="bulk-actions__link" @click="selectAll">全选</text>
|
|||
|
|
<text class="bulk-actions__link" @click="cancelBulk">取消</text>
|
|||
|
|
</template>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 购买列表 -->
|
|||
|
|
<scroll-view v-if="currentMode === 'buy'" class="shop-list" scroll-y>
|
|||
|
|
<view
|
|||
|
|
v-for="item in shopItems"
|
|||
|
|
:key="item.id"
|
|||
|
|
class="shop-item"
|
|||
|
|
:class="{ 'shop-item--disabled': !canBuy(item) }"
|
|||
|
|
@click="tryBuy(item)"
|
|||
|
|
>
|
|||
|
|
<view class="shop-item__main">
|
|||
|
|
<text class="shop-item__icon">{{ item.icon || '📦' }}</text>
|
|||
|
|
<view class="shop-item__info">
|
|||
|
|
<text class="shop-item__name">{{ item.name }}</text>
|
|||
|
|
<text class="shop-item__desc">{{ item.description }}</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="shop-item__right">
|
|||
|
|
<text class="shop-item__price">{{ getBuyPrice(item.id) }}铜</text>
|
|||
|
|
<text v-if="item.stock > 0" class="shop-item__stock">库存:{{ item.stock }}</text>
|
|||
|
|
<text v-else class="shop-item__stock">无限</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view v-if="shopItems.length === 0" class="shop-empty">
|
|||
|
|
<text class="shop-empty__text">商店空空如也</text>
|
|||
|
|
</view>
|
|||
|
|
</scroll-view>
|
|||
|
|
|
|||
|
|
<!-- 出售列表 -->
|
|||
|
|
<scroll-view v-else class="shop-list" scroll-y>
|
|||
|
|
<view
|
|||
|
|
v-for="item in sellableItems"
|
|||
|
|
:key="item.uniqueId || item.id"
|
|||
|
|
class="shop-item"
|
|||
|
|
:class="{
|
|||
|
|
'shop-item--selected': isItemSelected(item),
|
|||
|
|
'shop-item--bulk': bulkMode
|
|||
|
|
}"
|
|||
|
|
@click="handleSellItemClick(item)"
|
|||
|
|
>
|
|||
|
|
<!-- 多选复选框 -->
|
|||
|
|
<view v-if="bulkMode" class="shop-item__checkbox">
|
|||
|
|
<text v-if="isItemSelected(item)" class="checkbox-icon">✓</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="shop-item__main">
|
|||
|
|
<text class="shop-item__icon">{{ item.icon || '📦' }}</text>
|
|||
|
|
<view class="shop-item__info">
|
|||
|
|
<text class="shop-item__name">{{ item.name }}</text>
|
|||
|
|
<text v-if="item.count > 1" class="shop-item__count">x{{ item.count }}</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<text class="shop-item__price">{{ getSellPrice(item) }}铜</text>
|
|||
|
|
</view>
|
|||
|
|
<view v-if="sellableItems.length === 0" class="shop-empty">
|
|||
|
|
<text class="shop-empty__text">没有可出售的物品</text>
|
|||
|
|
</view>
|
|||
|
|
</scroll-view>
|
|||
|
|
|
|||
|
|
<!-- 批量出售按钮 -->
|
|||
|
|
<view v-if="bulkMode && selectedItems.length > 0" class="bulk-confirm-bar">
|
|||
|
|
<text class="bulk-confirm-text">出售 {{ selectedItems.length }} 件物品,获得 {{ totalSellPrice }} 铜币</text>
|
|||
|
|
<TextButton text="确认出售" type="primary" @click="confirmBulkSell" />
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 物品详情弹窗 -->
|
|||
|
|
<view v-if="selectedItem" class="item-detail-popup" @click="selectedItem = null">
|
|||
|
|
<view class="item-detail" @click.stop>
|
|||
|
|
<text class="item-detail__name">{{ selectedItem.name }}</text>
|
|||
|
|
<text class="item-detail__desc">{{ selectedItem.description }}</text>
|
|||
|
|
<view class="item-detail__actions">
|
|||
|
|
<TextButton
|
|||
|
|
v-if="currentMode === 'buy' && selectedItem.buyItem"
|
|||
|
|
text="购买"
|
|||
|
|
type="primary"
|
|||
|
|
@click="confirmBuy"
|
|||
|
|
/>
|
|||
|
|
<TextButton
|
|||
|
|
v-if="currentMode === 'sell' && selectedItem.sellItem"
|
|||
|
|
text="出售"
|
|||
|
|
type="primary"
|
|||
|
|
@click="confirmSell"
|
|||
|
|
/>
|
|||
|
|
<TextButton
|
|||
|
|
text="取消"
|
|||
|
|
@click="selectedItem = null"
|
|||
|
|
/>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
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 { addItemToInventory, removeItemFromInventory } from '@/utils/itemSystem.js'
|
|||
|
|
import FilterTabs from '@/components/common/FilterTabs.vue'
|
|||
|
|
import TextButton from '@/components/common/TextButton.vue'
|
|||
|
|
|
|||
|
|
const player = usePlayerStore()
|
|||
|
|
const game = useGameStore()
|
|||
|
|
|
|||
|
|
const currentMode = ref('buy')
|
|||
|
|
const selectedItem = ref(null)
|
|||
|
|
const bulkMode = ref(false)
|
|||
|
|
const selectedItems = ref([])
|
|||
|
|
|
|||
|
|
const emit = defineEmits(['close'])
|
|||
|
|
|
|||
|
|
const modeTabs = [
|
|||
|
|
{ id: 'buy', label: '购买' },
|
|||
|
|
{ id: 'sell', label: '出售' }
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
// 获取当前商店配置
|
|||
|
|
const shopConfig = computed(() => {
|
|||
|
|
const config = getShopConfig(player.currentLocation)
|
|||
|
|
return config || { name: '未知商店', owner: '未知', icon: '🏪', items: [] }
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// 商店可售物品
|
|||
|
|
const shopItems = computed(() => {
|
|||
|
|
const config = shopConfig.value
|
|||
|
|
if (!config.items) return []
|
|||
|
|
|
|||
|
|
return config.items
|
|||
|
|
.filter(item => item.stock === -1 || item.stock > 0)
|
|||
|
|
.map(shopItem => {
|
|||
|
|
const itemConfig = { ...shopItem }
|
|||
|
|
itemConfig.id = shopItem.itemId
|
|||
|
|
return itemConfig
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// 玩家可出售物品
|
|||
|
|
const sellableItems = computed(() => {
|
|||
|
|
return (player.inventory || []).filter(item => {
|
|||
|
|
// 关键道具不能出售
|
|||
|
|
if (item.type === 'key') return false
|
|||
|
|
return true
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// 计算选中物品总价
|
|||
|
|
const totalSellPrice = computed(() => {
|
|||
|
|
return selectedItems.value.reduce((total, item) => {
|
|||
|
|
return total + getSellPrice(item) * item.count
|
|||
|
|
}, 0)
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
function formatCurrency(copper) {
|
|||
|
|
if (copper >= 10000) {
|
|||
|
|
const gold = Math.floor(copper / 10000)
|
|||
|
|
const silver = Math.floor((copper % 10000) / 100)
|
|||
|
|
const remaining = copper % 100
|
|||
|
|
return `${gold}金 ${silver}银 ${remaining}铜`
|
|||
|
|
} else if (copper >= 100) {
|
|||
|
|
const silver = Math.floor(copper / 100)
|
|||
|
|
const remaining = copper % 100
|
|||
|
|
return `${silver}银 ${remaining}铜`
|
|||
|
|
}
|
|||
|
|
return `${copper}铜`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function getBuyPrice(itemId) {
|
|||
|
|
return calcBuyPrice(game, itemId)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function getSellPrice(item) {
|
|||
|
|
return calcSellPrice(game, item.id, item.quality || 100)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function canBuy(item) {
|
|||
|
|
const price = getBuyPrice(item.id)
|
|||
|
|
return player.currency.copper >= price
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function tryBuy(item) {
|
|||
|
|
if (!canBuy(item)) {
|
|||
|
|
game.addLog('金币不足!', 'error')
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
selectedItem.value = {
|
|||
|
|
...item,
|
|||
|
|
buyItem: true
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function trySell(item) {
|
|||
|
|
selectedItem.value = {
|
|||
|
|
...item,
|
|||
|
|
sellItem: true
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查物品是否被选中
|
|||
|
|
function isItemSelected(item) {
|
|||
|
|
return selectedItems.value.some(i =>
|
|||
|
|
(i.uniqueId && i.uniqueId === item.uniqueId) || i.id === item.id
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 处理出售列表点击
|
|||
|
|
function handleSellItemClick(item) {
|
|||
|
|
if (bulkMode.value) {
|
|||
|
|
// 批量模式:切换选中状态
|
|||
|
|
const index = selectedItems.value.findIndex(i =>
|
|||
|
|
(i.uniqueId && i.uniqueId === item.uniqueId) || i.id === item.id
|
|||
|
|
)
|
|||
|
|
if (index > -1) {
|
|||
|
|
selectedItems.value.splice(index, 1)
|
|||
|
|
} else {
|
|||
|
|
selectedItems.value.push(item)
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
// 普通模式:显示详情
|
|||
|
|
trySell(item)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 全选
|
|||
|
|
function selectAll() {
|
|||
|
|
selectedItems.value = [...sellableItems.value]
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 取消批量模式
|
|||
|
|
function cancelBulk() {
|
|||
|
|
bulkMode.value = false
|
|||
|
|
selectedItems.value = []
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 批量出售
|
|||
|
|
function confirmBulkSell() {
|
|||
|
|
if (selectedItems.value.length === 0) return
|
|||
|
|
|
|||
|
|
let totalEarned = 0
|
|||
|
|
const itemsToRemove = []
|
|||
|
|
|
|||
|
|
for (const item of selectedItems.value) {
|
|||
|
|
const price = getSellPrice(item) * item.count
|
|||
|
|
totalEarned += price
|
|||
|
|
itemsToRemove.push(item)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 移除所有选中的物品
|
|||
|
|
for (const item of itemsToRemove) {
|
|||
|
|
removeItemFromInventory(player, item.uniqueId || item.id)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 增加金币
|
|||
|
|
player.currency.copper += totalEarned
|
|||
|
|
game.addLog(`批量出售了 ${itemsToRemove.length} 件物品,获得 ${totalEarned} 铜币`, 'reward')
|
|||
|
|
|
|||
|
|
// 重置选择
|
|||
|
|
bulkMode.value = false
|
|||
|
|
selectedItems.value = []
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function confirmBuy() {
|
|||
|
|
if (!selectedItem.value) return
|
|||
|
|
|
|||
|
|
const item = selectedItem.value
|
|||
|
|
const price = getBuyPrice(item.id)
|
|||
|
|
|
|||
|
|
if (player.currency.copper < price) {
|
|||
|
|
game.addLog('金币不足!', 'error')
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 扣除金币
|
|||
|
|
player.currency.copper -= price
|
|||
|
|
|
|||
|
|
// 添加物品
|
|||
|
|
const result = addItemToInventory(player, item.id, 1)
|
|||
|
|
|
|||
|
|
if (result.success) {
|
|||
|
|
game.addLog(`购买了 ${result.item.name}`, 'reward')
|
|||
|
|
|
|||
|
|
// 减少商店库存
|
|||
|
|
const shop = getShopConfig(player.currentLocation)
|
|||
|
|
if (shop) {
|
|||
|
|
const shopItem = shop.items.find(i => i.itemId === item.id)
|
|||
|
|
if (shopItem && shopItem.stock > 0) {
|
|||
|
|
shopItem.stock--
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
selectedItem.value = null
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function confirmSell() {
|
|||
|
|
if (!selectedItem.value) return
|
|||
|
|
|
|||
|
|
const item = selectedItem.value
|
|||
|
|
const price = getSellPrice(item)
|
|||
|
|
|
|||
|
|
// 移除物品
|
|||
|
|
const result = removeItemFromInventory(player, item.uniqueId || item.id)
|
|||
|
|
|
|||
|
|
if (result.success) {
|
|||
|
|
// 增加金币
|
|||
|
|
player.currency.copper += price
|
|||
|
|
game.addLog(`出售了 ${item.name},获得 ${price} 铜币`, 'reward')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
selectedItem.value = null
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function close() {
|
|||
|
|
emit('close')
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
.shop-drawer {
|
|||
|
|
height: 100%;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
background-color: $bg-secondary;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.drawer-header {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: flex-start;
|
|||
|
|
padding: 24rpx;
|
|||
|
|
border-bottom: 1rpx solid $border-color;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.header-left {
|
|||
|
|
flex: 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.drawer-title {
|
|||
|
|
display: block;
|
|||
|
|
color: $text-primary;
|
|||
|
|
font-size: 32rpx;
|
|||
|
|
font-weight: bold;
|
|||
|
|
margin-bottom: 4rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.drawer-owner {
|
|||
|
|
display: block;
|
|||
|
|
color: $text-secondary;
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.drawer-close {
|
|||
|
|
color: $text-secondary;
|
|||
|
|
font-size: 48rpx;
|
|||
|
|
padding: 0 16rpx;
|
|||
|
|
|
|||
|
|
&:active {
|
|||
|
|
color: $text-primary;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.currency-display {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
padding: 16rpx 24rpx;
|
|||
|
|
background-color: rgba($accent, 0.1);
|
|||
|
|
border-bottom: 1rpx solid $border-color;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.currency-label {
|
|||
|
|
color: $text-secondary;
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.currency-value {
|
|||
|
|
color: $accent;
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bulk-actions {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
padding: 12rpx 24rpx;
|
|||
|
|
background-color: rgba($bg-primary, 0.5);
|
|||
|
|
border-bottom: 1rpx solid $border-color;
|
|||
|
|
|
|||
|
|
&__left {
|
|||
|
|
display: flex;
|
|||
|
|
gap: 24rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__count {
|
|||
|
|
color: $text-primary;
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__total {
|
|||
|
|
color: $accent;
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__right {
|
|||
|
|
display: flex;
|
|||
|
|
gap: 24rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__link {
|
|||
|
|
color: $accent;
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
|
|||
|
|
&:active {
|
|||
|
|
opacity: 0.7;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bulk-confirm-bar {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
padding: 16rpx 24rpx;
|
|||
|
|
background-color: rgba($accent, 0.1);
|
|||
|
|
border-top: 1rpx solid $border-color;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bulk-confirm-text {
|
|||
|
|
color: $text-primary;
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.shop-list {
|
|||
|
|
flex: 1;
|
|||
|
|
padding: 16rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.shop-item {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
padding: 16rpx;
|
|||
|
|
background-color: $bg-primary;
|
|||
|
|
border-radius: 8rpx;
|
|||
|
|
margin-bottom: 8rpx;
|
|||
|
|
|
|||
|
|
&:active {
|
|||
|
|
background-color: $bg-tertiary;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&--disabled {
|
|||
|
|
opacity: 0.5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&--selected {
|
|||
|
|
background-color: rgba($accent, 0.15);
|
|||
|
|
border: 1rpx solid $accent;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&--bulk {
|
|||
|
|
cursor: pointer;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__checkbox {
|
|||
|
|
width: 40rpx;
|
|||
|
|
height: 40rpx;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
border: 2rpx solid $border-color;
|
|||
|
|
border-radius: 4rpx;
|
|||
|
|
margin-right: 12rpx;
|
|||
|
|
background-color: $bg-secondary;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__main {
|
|||
|
|
flex: 1;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 16rpx;
|
|||
|
|
min-width: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__icon {
|
|||
|
|
font-size: 40rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__info {
|
|||
|
|
flex: 1;
|
|||
|
|
min-width: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__name {
|
|||
|
|
display: block;
|
|||
|
|
color: $text-primary;
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__desc {
|
|||
|
|
display: block;
|
|||
|
|
color: $text-secondary;
|
|||
|
|
font-size: 22rpx;
|
|||
|
|
margin-top: 4rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__count {
|
|||
|
|
display: block;
|
|||
|
|
color: $text-muted;
|
|||
|
|
font-size: 22rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__right {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
align-items: flex-end;
|
|||
|
|
gap: 4rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__price {
|
|||
|
|
color: $accent;
|
|||
|
|
font-size: 26rpx;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__stock {
|
|||
|
|
color: $text-muted;
|
|||
|
|
font-size: 20rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.checkbox-icon {
|
|||
|
|
color: $accent;
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.shop-empty {
|
|||
|
|
padding: 80rpx;
|
|||
|
|
text-align: center;
|
|||
|
|
|
|||
|
|
&__text {
|
|||
|
|
color: $text-muted;
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.item-detail-popup {
|
|||
|
|
position: absolute;
|
|||
|
|
top: 0;
|
|||
|
|
left: 0;
|
|||
|
|
right: 0;
|
|||
|
|
bottom: 0;
|
|||
|
|
background-color: rgba(0,0,0,0.6);
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
z-index: 100;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.item-detail {
|
|||
|
|
width: 80%;
|
|||
|
|
max-width: 500rpx;
|
|||
|
|
padding: 32rpx;
|
|||
|
|
background-color: $bg-secondary;
|
|||
|
|
border-radius: 16rpx;
|
|||
|
|
|
|||
|
|
&__name {
|
|||
|
|
display: block;
|
|||
|
|
color: $text-primary;
|
|||
|
|
font-size: 32rpx;
|
|||
|
|
font-weight: bold;
|
|||
|
|
margin-bottom: 16rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__desc {
|
|||
|
|
display: block;
|
|||
|
|
color: $text-secondary;
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
line-height: 1.6;
|
|||
|
|
margin-bottom: 24rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__actions {
|
|||
|
|
display: flex;
|
|||
|
|
gap: 12rpx;
|
|||
|
|
justify-content: flex-end;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|