feat: 图片压缩后上传COS + 修复订单LazyInitializationException + 添加调试日志
This commit is contained in:
@@ -102,13 +102,10 @@
|
||||
<el-option :label="$t('orders.cancelled')" value="CANCELLED" />
|
||||
<el-option :label="$t('orders.refunded')" value="REFUNDED" />
|
||||
</el-select>
|
||||
<el-select v-model="filters.type" :placeholder="$t('orders.allTypes')" size="small" @change="handleFilterChange">
|
||||
<el-option :label="$t('orders.allTypes')" value="" />
|
||||
<el-option label="商品订单" value="PRODUCT" />
|
||||
<el-option label="服务订单" value="SERVICE" />
|
||||
<el-option label="订阅订单" value="SUBSCRIPTION" />
|
||||
<el-option label="数字商品" value="DIGITAL" />
|
||||
<el-option label="实体商品" value="PHYSICAL" />
|
||||
<el-select v-model="filters.paymentMethod" :placeholder="$t('orders.allPaymentMethods') || '全部支付方式'" size="small" @change="handleFilterChange">
|
||||
<el-option :label="$t('orders.allPaymentMethods') || '全部支付方式'" value="" />
|
||||
<el-option :label="$t('orders.alipay') || '支付宝'" value="ALIPAY" />
|
||||
<el-option :label="$t('orders.paypal') || 'PayPal'" value="PAYPAL" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="toolbar-right">
|
||||
@@ -200,6 +197,92 @@
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<!-- 订单详情弹窗 -->
|
||||
<el-dialog
|
||||
v-model="orderDetailVisible"
|
||||
:title="$t('orders.orderDetail') || '订单详情'"
|
||||
width="600px"
|
||||
class="order-detail-dialog"
|
||||
>
|
||||
<div v-if="currentOrderDetail" class="order-detail-content">
|
||||
<div class="detail-section">
|
||||
<h4>{{ $t('orders.basicInfo') || '基本信息' }}</h4>
|
||||
<div class="detail-grid">
|
||||
<div class="detail-item">
|
||||
<span class="label">{{ $t('orders.orderNumber') }}:</span>
|
||||
<span class="value">{{ currentOrderDetail.orderNumber || currentOrderDetail.id }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="label">{{ $t('orders.username') }}:</span>
|
||||
<span class="value">{{ currentOrderDetail.user?.username || '-' }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="label">{{ $t('orders.orderType') || '订单类型' }}:</span>
|
||||
<span class="value">{{ getOrderTypeText(currentOrderDetail.orderType) }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="label">{{ $t('orders.status') }}:</span>
|
||||
<span class="status-tag" :class="getStatusClass(currentOrderDetail.status)">
|
||||
{{ getStatusText(currentOrderDetail.status) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<h4>{{ $t('orders.paymentInfo') || '支付信息' }}</h4>
|
||||
<div class="detail-grid">
|
||||
<div class="detail-item">
|
||||
<span class="label">{{ $t('orders.amount') }}:</span>
|
||||
<span class="value amount">{{ currentOrderDetail.currency || '¥' }}{{ currentOrderDetail.totalAmount || 0 }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="label">{{ $t('orders.paymentMethod') }}:</span>
|
||||
<span class="value">
|
||||
<template v-if="currentOrderDetail.paymentMethod === 'ALIPAY'">{{ $t('orders.alipay') }}</template>
|
||||
<template v-else-if="currentOrderDetail.paymentMethod === 'WECHAT'">{{ $t('orders.wechat') }}</template>
|
||||
<template v-else-if="currentOrderDetail.paymentMethod === 'PAYPAL'">{{ $t('orders.paypal') }}</template>
|
||||
<template v-else>{{ $t('orders.unpaid') }}</template>
|
||||
</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="label">{{ $t('orders.createTime') }}:</span>
|
||||
<span class="value">{{ formatDate(currentOrderDetail.createdAt) }}</span>
|
||||
</div>
|
||||
<div class="detail-item" v-if="currentOrderDetail.paidAt">
|
||||
<span class="label">{{ $t('orders.paidTime') || '支付时间' }}:</span>
|
||||
<span class="value">{{ formatDate(currentOrderDetail.paidAt) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section" v-if="currentOrderDetail.contactEmail || currentOrderDetail.contactPhone">
|
||||
<h4>{{ $t('orders.contactInfo') || '联系信息' }}</h4>
|
||||
<div class="detail-grid">
|
||||
<div class="detail-item" v-if="currentOrderDetail.contactEmail">
|
||||
<span class="label">{{ $t('orders.email') || '邮箱' }}:</span>
|
||||
<span class="value">{{ currentOrderDetail.contactEmail }}</span>
|
||||
</div>
|
||||
<div class="detail-item" v-if="currentOrderDetail.contactPhone">
|
||||
<span class="label">{{ $t('orders.phone') || '电话' }}:</span>
|
||||
<span class="value">{{ currentOrderDetail.contactPhone }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section" v-if="currentOrderDetail.description">
|
||||
<h4>{{ $t('orders.description') || '订单描述' }}</h4>
|
||||
<p class="description-text">{{ currentOrderDetail.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="loading-container">
|
||||
<el-icon class="is-loading"><Loading /></el-icon>
|
||||
<span>{{ $t('common.loading') || '加载中...' }}</span>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="orderDetailVisible = false">{{ $t('common.close') || '关闭' }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -219,7 +302,8 @@ import {
|
||||
ArrowRight,
|
||||
Delete,
|
||||
CreditCard,
|
||||
Wallet
|
||||
Wallet,
|
||||
Loading
|
||||
} from '@element-plus/icons-vue'
|
||||
import { getOrders, getAdminOrders, getOrderStats, deleteOrder as deleteOrderAPI, deleteOrders } from '@/api/orders'
|
||||
import LanguageSwitcher from '@/components/LanguageSwitcher.vue'
|
||||
@@ -245,7 +329,7 @@ const systemUptime = ref('加载中...')
|
||||
// 筛选条件
|
||||
const filters = reactive({
|
||||
status: '',
|
||||
type: '',
|
||||
paymentMethod: '',
|
||||
search: ''
|
||||
})
|
||||
|
||||
@@ -417,8 +501,13 @@ const goToPage = (page) => {
|
||||
fetchOrders()
|
||||
}
|
||||
|
||||
const viewOrder = (order) => {
|
||||
router.push(`/orders/${order.id}`)
|
||||
// 订单详情弹窗相关
|
||||
const orderDetailVisible = ref(false)
|
||||
const currentOrderDetail = ref(null)
|
||||
|
||||
const viewOrder = async (order) => {
|
||||
currentOrderDetail.value = order
|
||||
orderDetailVisible.value = true
|
||||
}
|
||||
|
||||
const deleteOrder = async (order) => {
|
||||
@@ -433,19 +522,24 @@ const deleteOrder = async (order) => {
|
||||
}
|
||||
)
|
||||
|
||||
await deleteOrderAPI(order.id)
|
||||
const response = await deleteOrderAPI(order.id)
|
||||
console.log('删除订单响应:', response)
|
||||
|
||||
const index = orders.value.findIndex(o => o.id === order.id)
|
||||
if (index > -1) {
|
||||
orders.value.splice(index, 1)
|
||||
totalOrders.value--
|
||||
// 检查响应状态
|
||||
if (response.data?.success) {
|
||||
const index = orders.value.findIndex(o => o.id === order.id)
|
||||
if (index > -1) {
|
||||
orders.value.splice(index, 1)
|
||||
totalOrders.value--
|
||||
}
|
||||
ElMessage.success('删除成功')
|
||||
} else {
|
||||
ElMessage.error(response.data?.message || '删除失败')
|
||||
}
|
||||
|
||||
ElMessage.success('删除成功')
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('删除失败:', error)
|
||||
ElMessage.error('删除失败')
|
||||
ElMessage.error('删除失败: ' + (error.message || '未知错误'))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -468,17 +562,21 @@ const deleteSelected = async () => {
|
||||
)
|
||||
|
||||
const ids = selectedOrders.value.map(o => o.id)
|
||||
await deleteOrders(ids)
|
||||
const response = await deleteOrders(ids)
|
||||
console.log('批量删除订单响应:', response)
|
||||
|
||||
orders.value = orders.value.filter(o => !ids.includes(o.id))
|
||||
totalOrders.value -= ids.length
|
||||
selectedOrders.value = []
|
||||
|
||||
ElMessage.success('批量删除成功')
|
||||
if (response.data?.success) {
|
||||
orders.value = orders.value.filter(o => !ids.includes(o.id))
|
||||
totalOrders.value -= response.data?.deletedCount || ids.length
|
||||
selectedOrders.value = []
|
||||
ElMessage.success(response.data?.message || '批量删除成功')
|
||||
} else {
|
||||
ElMessage.error(response.data?.message || '批量删除失败')
|
||||
}
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('批量删除失败:', error)
|
||||
ElMessage.error('批量删除失败')
|
||||
ElMessage.error('批量删除失败: ' + (error.message || '未知错误'))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -493,8 +591,9 @@ const fetchOrders = async () => {
|
||||
const response = await apiFunction({
|
||||
page: currentPage.value - 1,
|
||||
size: pageSize.value,
|
||||
status: filters.status,
|
||||
search: filters.search || searchText.value
|
||||
status: filters.status || undefined,
|
||||
paymentMethod: filters.paymentMethod || undefined,
|
||||
search: filters.search || searchText.value || undefined
|
||||
})
|
||||
|
||||
console.log('获取订单列表响应:', response)
|
||||
@@ -1002,6 +1101,98 @@ const fetchSystemStats = async () => {
|
||||
padding: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 订单详情弹窗样式 */
|
||||
.order-detail-content {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.detail-section {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.detail-section:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.detail-section h4 {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
margin: 0 0 16px 0;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.detail-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 12px 24px;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.detail-item .label {
|
||||
color: #64748b;
|
||||
font-size: 14px;
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.detail-item .value {
|
||||
color: #1e293b;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.detail-item .value.amount {
|
||||
color: #f59e0b;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.description-text {
|
||||
color: #475569;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
padding: 12px;
|
||||
background: #f8fafc;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 40px;
|
||||
color: #64748b;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.loading-container .el-icon {
|
||||
font-size: 32px;
|
||||
color: #3b82f6;
|
||||
}
|
||||
|
||||
:deep(.order-detail-dialog .el-dialog__header) {
|
||||
padding: 16px 20px;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
:deep(.order-detail-dialog .el-dialog__body) {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
:deep(.order-detail-dialog .el-dialog__footer) {
|
||||
padding: 12px 20px;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user