商城实现

This commit is contained in:
2025-08-29 16:58:00 +08:00
parent 186ee157af
commit 6e0ae59f43
10 changed files with 613 additions and 445 deletions

View File

@@ -73,10 +73,17 @@
<h4 class="item-name">{{ item.product.name }}</h4>
<p class="item-desc">{{ truncateText(item.product.description, 40) }}</p>
<div class="item-price">
<span class="price">
<el-icon><Coin /></el-icon>
{{ item.points }}
</span>
<div class="price-group">
<span class="price">
<el-icon><Coin /></el-icon>
{{ item.points }}
</span>
<span class="plus-sign">+</span>
<span class="price">
<img src="/imgs/profile/融豆.png" alt="融豆" class="rongdou-icon" />
{{ item.rongdouPrice }}
</span>
</div>
<span class="quantity">x{{ item.quantity }}</span>
</div>
</div>
@@ -86,12 +93,21 @@
<!-- 订单总计 -->
<div class="order-total">
<div class="total-info">
<span>{{ order.totalQuantity }}件商品</span>
<span class="total-points">
总计<el-icon><Coin /></el-icon>{{ order.totalPoints }}
</span>
<span>{{ order.totalQuantity }}件商品</span>
<div class="total-price">
<span>总计</span>
<div class="total-price-group">
<span class="total-points">
<el-icon><Coin /></el-icon>{{ order.totalPoints }}
</span>
<span class="plus-sign">+</span>
<span class="total-rongdou">
<img src="/imgs/profile/融豆.png" alt="融豆" class="rongdou-icon" />{{ order.totalRongdou }}
</span>
</div>
</div>
</div>
</div>
<!-- 订单操作 -->
<div class="order-actions">
@@ -202,10 +218,18 @@
<span class="label">订单号</span>
<span class="value">{{ orderDetail.orderNumber }}</span>
</div>
<div class="detail-item">
<span class="label">用户名</span>
<span class="value">{{ orderDetail.username || '未知用户' }}</span>
</div>
<div class="detail-item">
<span class="label">下单时间</span>
<span class="value">{{ formatDateTime(orderDetail.createdAt) }}</span>
</div>
<div class="detail-item">
<span class="label">更新时间</span>
<span class="value">{{ formatDateTime(orderDetail.updatedAt) }}</span>
</div>
<div class="detail-item">
<span class="label">订单状态</span>
<span class="value">
@@ -223,8 +247,14 @@
<div class="product-info">
<h5>{{ item.product.name }}</h5>
<p>{{ item.product.description }}</p>
<p v-if="item.specInfo" class="spec-info">规格{{ item.specInfo }}</p>
<div class="product-price">
<span><el-icon><Coin /></el-icon>{{ item.points }} x {{ item.quantity }}</span>
<div class="detail-item-price-group">
<span><el-icon><Coin /></el-icon>{{ item.points }}</span>
<span class="plus-sign">+</span>
<span><img src="/imgs/profile/融豆.png" alt="融豆" class="rongdou-icon" />{{ item.rongdouPrice }}</span>
</div>
<span class="quantity-text">x {{ item.quantity }}</span>
</div>
</div>
</div>
@@ -246,11 +276,23 @@
<h4>费用明细</h4>
<div class="detail-item">
<span class="label">商品总计</span>
<span class="value"><el-icon><Coin /></el-icon>{{ orderDetail.totalPoints }}</span>
<div class="value">
<span class="detail-price-group">
<span><el-icon><Coin /></el-icon>{{ orderDetail.totalPoints }}</span>
<span class="plus-sign">+</span>
<span><img src="/imgs/profile/融豆.png" alt="融豆" class="rongdou-icon" />{{ orderDetail.totalRongdou }}</span>
</span>
</div>
</div>
<div class="detail-item total">
<span class="label">实付积分</span>
<span class="value"><el-icon><Coin /></el-icon>{{ orderDetail.totalPoints }}</span>
<span class="label">实付</span>
<div class="value">
<span class="detail-price-group">
<span><el-icon><Coin /></el-icon>{{ orderDetail.totalPoints }}</span>
<span class="plus-sign">+</span>
<span><img src="/imgs/profile/融豆.png" alt="融豆" class="rongdou-icon" />{{ orderDetail.totalRongdou }}</span>
</span>
</div>
</div>
</div>
</div>
@@ -331,6 +373,17 @@ const getStatusType = (status) => {
return typeMap[status] || 'info'
}
const mapOrderStatus = (backendStatus) => {
const statusMap = {
'pre_order': 'pending',
'pending': 'pending',
'shipped': 'shipped',
'completed': 'completed',
'cancelled': 'cancelled'
}
return statusMap[backendStatus] || 'pending'
}
const getStatusText = (status) => {
const textMap = {
pending: '待发货',
@@ -451,13 +504,40 @@ const submitReview = async () => {
}
}
const viewOrderDetail = async (orderId) => {
const viewOrderDetail = (orderId) => {
try {
const response = await api.get(`/orders/${orderId}`)
orderDetail.value = response.data
console.log('正在查找订单详情订单ID:', orderId)
// 从已加载的订单列表中查找对应订单
const order = orders.value.find(o => o.id === orderId)
console.log('找到的订单数据:', order)
if (!order) {
ElMessage.error('未找到订单信息')
return
}
// 直接使用已映射的订单数据
orderDetail.value = {
id: order.id,
orderNumber: order.orderNumber,
createdAt: order.createdAt,
updatedAt: order.updatedAt || order.createdAt,
username: order.username || '未知用户',
status: order.status,
totalPoints: order.totalPoints,
totalRongdou: order.totalRongdou,
totalQuantity: order.totalQuantity,
items: order.items || [],
shippingAddress: order.shippingAddress || null,
trackingNumber: order.trackingNumber || null
}
console.log('设置的订单详情数据:', orderDetail.value)
showOrderDetail.value = true
} catch (error) {
ElMessage.error('获取订单详情失败')
console.error('查看订单详情失败:', error)
ElMessage.error(`查看订单详情失败: ${error.message || '未知错误'}`)
}
}
@@ -478,13 +558,41 @@ const getOrders = async (isLoadMore = false) => {
})
console.log(data,'response');
// 映射后端数据结构到前端需要的格式
const mappedOrders = data.data.orders.map(order => ({
id: order.id,
orderNumber: order.order_no,
createdAt: order.created_at,
updatedAt: order.updated_at,
username: order.username,
status: mapOrderStatus(order.status),
totalPoints: order.total_points,
totalRongdou: order.total_rongdou,
totalQuantity: order.items?.reduce((sum, item) => sum + item.quantity, 0) || 0,
items: order.items?.map(item => ({
id: item.id,
productId: item.product_id,
quantity: item.quantity,
points: item.points_price,
rongdouPrice: item.rongdou_price,
specInfo: item.spec_info,
product: {
name: item.product_name || '商品名称',
description: item.description || '商品描述',
image: item.image_url || '/imgs/loading.png'
}
})) || [],
shippingAddress: order.address || null,
trackingNumber: null
}))
if (isLoadMore) {
orders.value.push(...data.data.orders)
orders.value.push(...mappedOrders)
} else {
orders.value = data.data.orders
orders.value = mappedOrders
}
hasMore.value = data.data.hasMore
hasMore.value = data.data.pagination.page < data.data.pagination.pages
page.value++
updateStatusCounts()
@@ -702,6 +810,12 @@ onMounted(() => {
align-items: center;
}
.price-group {
display: flex;
align-items: center;
gap: 4px;
}
.price {
display: flex;
align-items: center;
@@ -711,6 +825,30 @@ onMounted(() => {
font-size: 14px;
}
.plus-sign {
color: #999;
font-size: 12px;
margin: 0 2px;
}
.rongdou-icon {
width: 14px;
height: 14px;
object-fit: contain;
}
.detail-price-group {
display: flex;
align-items: center;
gap: 4px;
}
.detail-item-price-group {
display: flex;
align-items: center;
gap: 4px;
}
.quantity {
color: #999;
font-size: 12px;
@@ -728,7 +866,20 @@ onMounted(() => {
align-items: center;
}
.total-points {
.total-price {
display: flex;
align-items: center;
gap: 8px;
}
.total-price-group {
display: flex;
align-items: center;
gap: 4px;
}
.total-points,
.total-rongdou {
display: flex;
align-items: center;
gap: 4px;
@@ -877,6 +1028,13 @@ onMounted(() => {
}
.detail-product .product-price {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.detail-item-price-group {
display: flex;
align-items: center;
gap: 4px;
@@ -885,6 +1043,29 @@ onMounted(() => {
font-size: 14px;
}
.quantity-text {
color: #999;
font-size: 12px;
}
.detail-price-group {
display: flex;
align-items: center;
gap: 4px;
color: #ff6b35;
font-weight: 600;
}
.spec-info {
font-size: 12px;
color: #666;
margin: 4px 0;
background: #f5f5f5;
padding: 2px 8px;
border-radius: 4px;
display: inline-block;
}
/* 响应式设计 */
@media (max-width: 480px) {
.order-header {