Initial commit: AIGC项目完整代码
This commit is contained in:
784
demo/frontend/src/views/AdminOrders.vue
Normal file
784
demo/frontend/src/views/AdminOrders.vue
Normal file
@@ -0,0 +1,784 @@
|
||||
<template>
|
||||
<div class="admin-orders">
|
||||
<!-- 页面标题 -->
|
||||
<div class="page-header">
|
||||
<h2>
|
||||
<el-icon><Management /></el-icon>
|
||||
订单管理 - 管理员
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<!-- 统计面板 -->
|
||||
<el-row :gutter="20" class="stats-row">
|
||||
<el-col :xs="12" :sm="6">
|
||||
<el-card class="stat-card clickable" @click="handleStatClick('all')">
|
||||
<div class="stat-content">
|
||||
<div class="stat-number">{{ stats.totalOrders || 0 }}</div>
|
||||
<div class="stat-label">总订单数</div>
|
||||
</div>
|
||||
<el-icon class="stat-icon" color="#409EFF"><List /></el-icon>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="12" :sm="6">
|
||||
<el-card class="stat-card clickable" @click="handleStatClick('PENDING')">
|
||||
<div class="stat-content">
|
||||
<div class="stat-number">{{ stats.pendingOrders || 0 }}</div>
|
||||
<div class="stat-label">待支付</div>
|
||||
</div>
|
||||
<el-icon class="stat-icon" color="#E6A23C"><Clock /></el-icon>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="12" :sm="6">
|
||||
<el-card class="stat-card clickable" @click="handleStatClick('COMPLETED')">
|
||||
<div class="stat-content">
|
||||
<div class="stat-number">{{ stats.completedOrders || 0 }}</div>
|
||||
<div class="stat-label">已完成</div>
|
||||
</div>
|
||||
<el-icon class="stat-icon" color="#67C23A"><Check /></el-icon>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="12" :sm="6">
|
||||
<el-card class="stat-card clickable" @click="handleStatClick('today')">
|
||||
<div class="stat-content">
|
||||
<div class="stat-number">{{ stats.todayOrders || 0 }}</div>
|
||||
<div class="stat-label">今日订单</div>
|
||||
</div>
|
||||
<el-icon class="stat-icon" color="#F56C6C"><Calendar /></el-icon>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 第二行统计卡片 -->
|
||||
<el-row :gutter="20" class="stats-row" style="margin-top: 20px;">
|
||||
<el-col :xs="12" :sm="6">
|
||||
<el-card class="stat-card clickable" @click="handleStatClick('PAID')">
|
||||
<div class="stat-content">
|
||||
<div class="stat-number">{{ stats.paidOrders || 0 }}</div>
|
||||
<div class="stat-label">已支付</div>
|
||||
</div>
|
||||
<el-icon class="stat-icon" color="#409EFF"><CreditCard /></el-icon>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="12" :sm="6">
|
||||
<el-card class="stat-card clickable" @click="handleStatClick('PROCESSING')">
|
||||
<div class="stat-content">
|
||||
<div class="stat-number">{{ stats.processingOrders || 0 }}</div>
|
||||
<div class="stat-label">处理中</div>
|
||||
</div>
|
||||
<el-icon class="stat-icon" color="#909399"><Loading /></el-icon>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<!-- 只有存在实体商品时才显示发货统计 -->
|
||||
<el-col v-if="hasPhysicalOrders" :xs="12" :sm="6">
|
||||
<el-card class="stat-card clickable" @click="handleStatClick('SHIPPED')">
|
||||
<div class="stat-content">
|
||||
<div class="stat-number">{{ stats.shippedOrders || 0 }}</div>
|
||||
<div class="stat-label">已发货</div>
|
||||
</div>
|
||||
<el-icon class="stat-icon" color="#67C23A"><Truck /></el-icon>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<!-- 如果没有实体商品,显示已退款统计 -->
|
||||
<el-col v-else :xs="12" :sm="6">
|
||||
<el-card class="stat-card clickable" @click="handleStatClick('REFUNDED')">
|
||||
<div class="stat-content">
|
||||
<div class="stat-number">{{ stats.refundedOrders || 0 }}</div>
|
||||
<div class="stat-label">已退款</div>
|
||||
</div>
|
||||
<el-icon class="stat-icon" color="#909399"><Money /></el-icon>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="12" :sm="6">
|
||||
<el-card class="stat-card clickable" @click="handleStatClick('CANCELLED')">
|
||||
<div class="stat-content">
|
||||
<div class="stat-number">{{ stats.cancelledOrders || 0 }}</div>
|
||||
<div class="stat-label">已取消</div>
|
||||
</div>
|
||||
<el-icon class="stat-icon" color="#F56C6C"><Close /></el-icon>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 筛选和搜索 -->
|
||||
<el-card class="filter-card">
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-select
|
||||
v-model="filters.status"
|
||||
placeholder="选择订单状态"
|
||||
clearable
|
||||
@change="handleFilterChange"
|
||||
>
|
||||
<el-option label="全部状态" value="" />
|
||||
<el-option label="待支付" value="PENDING" />
|
||||
<el-option label="已确认" value="CONFIRMED" />
|
||||
<el-option label="已支付" value="PAID" />
|
||||
<el-option label="处理中" value="PROCESSING" />
|
||||
<el-option label="已发货" value="SHIPPED" />
|
||||
<el-option label="已送达" value="DELIVERED" />
|
||||
<el-option label="已完成" value="COMPLETED" />
|
||||
<el-option label="已取消" value="CANCELLED" />
|
||||
<el-option label="已退款" value="REFUNDED" />
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-input
|
||||
v-model="filters.search"
|
||||
placeholder="搜索订单号或用户名"
|
||||
clearable
|
||||
@input="handleSearch"
|
||||
>
|
||||
<template #prefix>
|
||||
<el-icon><Search /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-button @click="resetFilters">重置筛选</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<!-- 订单列表 -->
|
||||
<el-card class="orders-card">
|
||||
<el-table
|
||||
:data="orders"
|
||||
v-loading="loading"
|
||||
empty-text="暂无订单"
|
||||
@sort-change="handleSortChange"
|
||||
>
|
||||
<el-table-column prop="orderNumber" label="订单号" width="150" sortable="custom">
|
||||
<template #default="{ row }">
|
||||
<router-link :to="`/orders/${row.id}`" class="order-link">
|
||||
{{ row.orderNumber }}
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="user.username" label="用户" width="120">
|
||||
<template #default="{ row }">
|
||||
<div class="user-info">
|
||||
<el-avatar :size="24">{{ row.user.username.charAt(0).toUpperCase() }}</el-avatar>
|
||||
<span class="username">{{ row.user.username }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="totalAmount" label="金额" width="120" sortable="custom">
|
||||
<template #default="{ row }">
|
||||
<span class="amount">{{ row.currency }} {{ row.totalAmount }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="status" label="状态" width="120">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getStatusType(row.status)">
|
||||
{{ getStatusText(row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="orderType" label="类型" width="120">
|
||||
<template #default="{ row }">
|
||||
{{ getOrderTypeText(row.orderType) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="createdAt" label="创建时间" width="160" sortable="custom">
|
||||
<template #default="{ row }">
|
||||
{{ formatDate(row.createdAt) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" width="200" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button-group>
|
||||
<el-button size="small" @click="$router.push(`/orders/${row.id}`)">
|
||||
查看
|
||||
</el-button>
|
||||
|
||||
<el-dropdown trigger="click" :teleported="true" popper-class="table-dropdown" @command="(command) => handleAdminAction(row, command)">
|
||||
<el-button size="small" type="primary">
|
||||
管理<el-icon class="el-icon--right"><ArrowDown /></el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-if="canShip(row)" command="ship">
|
||||
<el-icon><Truck /></el-icon>
|
||||
发货
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="canComplete(row)" command="complete">
|
||||
<el-icon><Check /></el-icon>
|
||||
完成订单
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="canCancel(row)" command="cancel">
|
||||
<el-icon><Close /></el-icon>
|
||||
取消订单
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item divided command="updateStatus">
|
||||
<el-icon><Edit /></el-icon>
|
||||
更新状态
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</el-button-group>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination-container">
|
||||
<el-pagination
|
||||
v-model:current-page="pagination.page"
|
||||
v-model:page-size="pagination.size"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:total="pagination.total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 发货对话框 -->
|
||||
<el-dialog
|
||||
v-model="shipDialogVisible"
|
||||
title="订单发货"
|
||||
width="400px"
|
||||
>
|
||||
<el-form :model="shipForm" label-width="80px">
|
||||
<el-form-item label="物流单号">
|
||||
<el-input
|
||||
v-model="shipForm.trackingNumber"
|
||||
placeholder="请输入物流单号(可选)"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="shipDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmShip">确认发货</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 更新状态对话框 -->
|
||||
<el-dialog
|
||||
v-model="statusDialogVisible"
|
||||
title="更新订单状态"
|
||||
width="400px"
|
||||
>
|
||||
<el-form :model="statusForm" label-width="80px">
|
||||
<el-form-item label="新状态">
|
||||
<el-select v-model="statusForm.status" placeholder="选择新状态">
|
||||
<el-option label="待支付" value="PENDING" />
|
||||
<el-option label="已确认" value="CONFIRMED" />
|
||||
<el-option label="已支付" value="PAID" />
|
||||
<el-option label="处理中" value="PROCESSING" />
|
||||
|
||||
<!-- 实体商品才显示发货相关状态 -->
|
||||
<template v-if="isPhysicalOrder(currentStatusOrder)">
|
||||
<el-option label="已发货" value="SHIPPED" />
|
||||
<el-option label="已送达" value="DELIVERED" />
|
||||
</template>
|
||||
|
||||
<el-option label="已完成" value="COMPLETED" />
|
||||
<el-option label="已取消" value="CANCELLED" />
|
||||
<el-option label="已退款" value="REFUNDED" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input
|
||||
v-model="statusForm.notes"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入备注(可选)"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="statusDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmUpdateStatus">确认更新</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { getOrders, getOrderStats } from '@/api/orders'
|
||||
|
||||
const loading = ref(false)
|
||||
const orders = ref([])
|
||||
|
||||
// 统计数据
|
||||
const stats = ref({
|
||||
totalOrders: 0,
|
||||
pendingOrders: 0,
|
||||
completedOrders: 0,
|
||||
todayOrders: 0
|
||||
})
|
||||
|
||||
// 筛选条件
|
||||
const filters = reactive({
|
||||
status: '',
|
||||
search: ''
|
||||
})
|
||||
|
||||
// 分页信息
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 排序
|
||||
const sortBy = ref('createdAt')
|
||||
const sortDir = ref('desc')
|
||||
|
||||
// 发货对话框
|
||||
const shipDialogVisible = ref(false)
|
||||
const shipForm = reactive({
|
||||
trackingNumber: ''
|
||||
})
|
||||
const currentShipOrder = ref(null)
|
||||
|
||||
// 状态更新对话框
|
||||
const statusDialogVisible = ref(false)
|
||||
const statusForm = reactive({
|
||||
status: '',
|
||||
notes: ''
|
||||
})
|
||||
const currentStatusOrder = ref(null)
|
||||
|
||||
// 获取状态类型
|
||||
const getStatusType = (status) => {
|
||||
const statusMap = {
|
||||
'PENDING': 'warning',
|
||||
'CONFIRMED': 'info',
|
||||
'PAID': 'primary',
|
||||
'PROCESSING': '',
|
||||
'SHIPPED': 'success',
|
||||
'DELIVERED': 'success',
|
||||
'COMPLETED': 'success',
|
||||
'CANCELLED': 'danger',
|
||||
'REFUNDED': 'info'
|
||||
}
|
||||
return statusMap[status] || ''
|
||||
}
|
||||
|
||||
// 获取状态文本
|
||||
const getStatusText = (status) => {
|
||||
const statusMap = {
|
||||
'PENDING': '待支付',
|
||||
'CONFIRMED': '已确认',
|
||||
'PAID': '已支付',
|
||||
'PROCESSING': '处理中',
|
||||
'SHIPPED': '已发货',
|
||||
'DELIVERED': '已送达',
|
||||
'COMPLETED': '已完成',
|
||||
'CANCELLED': '已取消',
|
||||
'REFUNDED': '已退款'
|
||||
}
|
||||
return statusMap[status] || status
|
||||
}
|
||||
|
||||
// 获取订单类型文本
|
||||
const getOrderTypeText = (orderType) => {
|
||||
const typeMap = {
|
||||
'PRODUCT': '商品订单',
|
||||
'SERVICE': '服务订单',
|
||||
'SUBSCRIPTION': '订阅订单',
|
||||
'DIGITAL': '数字商品',
|
||||
'PHYSICAL': '实体商品'
|
||||
}
|
||||
return typeMap[orderType] || orderType
|
||||
}
|
||||
|
||||
// 格式化日期
|
||||
const formatDate = (dateString) => {
|
||||
const date = new Date(dateString)
|
||||
return date.toLocaleDateString('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
})
|
||||
}
|
||||
|
||||
// 检查是否可以发货(仅限实体商品)
|
||||
const canShip = (order) => {
|
||||
// 只有实体商品才需要发货
|
||||
const physicalOrderTypes = ['PRODUCT', 'PHYSICAL']
|
||||
return physicalOrderTypes.includes(order.orderType) &&
|
||||
(order.status === 'PAID' || order.status === 'CONFIRMED')
|
||||
}
|
||||
|
||||
// 检查是否可以完成
|
||||
const canComplete = (order) => {
|
||||
// 实体商品需要先发货才能完成
|
||||
if (['PRODUCT', 'PHYSICAL'].includes(order.orderType)) {
|
||||
return order.status === 'SHIPPED'
|
||||
}
|
||||
// 虚拟商品支付后可以直接完成
|
||||
return ['PAID', 'CONFIRMED'].includes(order.status)
|
||||
}
|
||||
|
||||
// 检查是否可以取消
|
||||
const canCancel = (order) => {
|
||||
return order.status === 'PENDING' || order.status === 'CONFIRMED'
|
||||
}
|
||||
|
||||
// 检查是否为实体商品
|
||||
const isPhysicalOrder = (order) => {
|
||||
if (!order) return false
|
||||
const physicalOrderTypes = ['PRODUCT', 'PHYSICAL']
|
||||
return physicalOrderTypes.includes(order.orderType)
|
||||
}
|
||||
|
||||
// 检查是否有实体商品订单
|
||||
const hasPhysicalOrders = computed(() => {
|
||||
return orders.value.some(order => isPhysicalOrder(order))
|
||||
})
|
||||
|
||||
// 处理统计卡片点击
|
||||
const handleStatClick = (type) => {
|
||||
if (type === 'all') {
|
||||
// 显示所有订单
|
||||
filters.status = ''
|
||||
filters.search = ''
|
||||
} else if (type === 'today') {
|
||||
// 显示今日订单(这里可以添加日期筛选逻辑)
|
||||
filters.status = ''
|
||||
filters.search = ''
|
||||
// 可以添加日期筛选逻辑
|
||||
} else {
|
||||
// 按状态筛选
|
||||
filters.status = type
|
||||
filters.search = ''
|
||||
}
|
||||
|
||||
// 重置分页并重新加载数据
|
||||
pagination.page = 1
|
||||
fetchOrders()
|
||||
}
|
||||
|
||||
// 获取订单列表
|
||||
const fetchOrders = async () => {
|
||||
try {
|
||||
loading.value = true
|
||||
|
||||
// 调用真实API获取订单数据
|
||||
const response = await getOrders({
|
||||
page: pagination.page - 1,
|
||||
size: pagination.size,
|
||||
status: filters.status,
|
||||
search: filters.search
|
||||
})
|
||||
|
||||
if (response.success) {
|
||||
orders.value = response.data.content || []
|
||||
pagination.total = response.data.totalElements || 0
|
||||
} else {
|
||||
ElMessage.error('获取订单列表失败')
|
||||
}
|
||||
|
||||
// 获取统计数据
|
||||
const statsResponse = await getOrderStats()
|
||||
if (statsResponse.success) {
|
||||
stats.value = statsResponse.data
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fetch orders error:', error)
|
||||
ElMessage.error('获取订单列表失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 筛选变化
|
||||
const handleFilterChange = () => {
|
||||
pagination.page = 1
|
||||
fetchOrders()
|
||||
}
|
||||
|
||||
// 搜索
|
||||
const handleSearch = () => {
|
||||
pagination.page = 1
|
||||
fetchOrders()
|
||||
}
|
||||
|
||||
// 重置筛选
|
||||
const resetFilters = () => {
|
||||
filters.status = ''
|
||||
filters.search = ''
|
||||
pagination.page = 1
|
||||
fetchOrders()
|
||||
}
|
||||
|
||||
// 排序变化
|
||||
const handleSortChange = ({ prop, order }) => {
|
||||
if (prop) {
|
||||
sortBy.value = prop
|
||||
sortDir.value = order === 'ascending' ? 'asc' : 'desc'
|
||||
fetchOrders()
|
||||
}
|
||||
}
|
||||
|
||||
// 分页大小变化
|
||||
const handleSizeChange = (size) => {
|
||||
pagination.size = size
|
||||
pagination.page = 1
|
||||
fetchOrders()
|
||||
}
|
||||
|
||||
// 当前页变化
|
||||
const handleCurrentChange = (page) => {
|
||||
pagination.page = page
|
||||
fetchOrders()
|
||||
}
|
||||
|
||||
// 处理管理员操作
|
||||
const handleAdminAction = (order, command) => {
|
||||
switch (command) {
|
||||
case 'ship':
|
||||
currentShipOrder.value = order
|
||||
shipForm.trackingNumber = ''
|
||||
shipDialogVisible.value = true
|
||||
break
|
||||
case 'complete':
|
||||
handleCompleteOrder(order)
|
||||
break
|
||||
case 'cancel':
|
||||
handleCancelOrder(order)
|
||||
break
|
||||
case 'updateStatus':
|
||||
currentStatusOrder.value = order
|
||||
statusForm.status = order.status
|
||||
statusForm.notes = ''
|
||||
statusDialogVisible.value = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 完成订单
|
||||
const handleCompleteOrder = async (order) => {
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要完成此订单吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
|
||||
ElMessage.success('订单完成成功')
|
||||
fetchOrders()
|
||||
} catch (error) {
|
||||
// 用户取消
|
||||
}
|
||||
}
|
||||
|
||||
// 更新统计数据
|
||||
const updateStats = () => {
|
||||
const today = new Date().toISOString().split('T')[0]
|
||||
stats.value = {
|
||||
totalOrders: orders.value.length,
|
||||
pendingOrders: orders.value.filter(order => order.status === 'PENDING').length,
|
||||
paidOrders: orders.value.filter(order => order.status === 'PAID').length,
|
||||
processingOrders: orders.value.filter(order => order.status === 'PROCESSING').length,
|
||||
shippedOrders: orders.value.filter(order => order.status === 'SHIPPED').length,
|
||||
completedOrders: orders.value.filter(order => order.status === 'COMPLETED').length,
|
||||
cancelledOrders: orders.value.filter(order => order.status === 'CANCELLED').length,
|
||||
refundedOrders: orders.value.filter(order => order.status === 'REFUNDED').length,
|
||||
todayOrders: orders.value.filter(order => order.createdAt.startsWith(today)).length
|
||||
}
|
||||
}
|
||||
|
||||
// 取消订单
|
||||
const handleCancelOrder = async (order) => {
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要取消此订单吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
|
||||
// 更新订单状态为已取消
|
||||
const orderIndex = orders.value.findIndex(o => o.id === order.id)
|
||||
if (orderIndex !== -1) {
|
||||
orders.value[orderIndex].status = 'CANCELLED'
|
||||
}
|
||||
|
||||
// 更新统计数据
|
||||
updateStats()
|
||||
|
||||
ElMessage.success('订单取消成功')
|
||||
} catch (error) {
|
||||
// 用户取消
|
||||
}
|
||||
}
|
||||
|
||||
// 确认发货
|
||||
const confirmShip = async () => {
|
||||
if (!currentShipOrder.value) return
|
||||
|
||||
try {
|
||||
ElMessage.success('发货成功')
|
||||
shipDialogVisible.value = false
|
||||
fetchOrders()
|
||||
} catch (error) {
|
||||
ElMessage.error('发货失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 确认更新状态
|
||||
const confirmUpdateStatus = async () => {
|
||||
if (!currentStatusOrder.value) return
|
||||
|
||||
try {
|
||||
// 更新订单状态
|
||||
const orderIndex = orders.value.findIndex(o => o.id === currentStatusOrder.value.id)
|
||||
if (orderIndex !== -1) {
|
||||
orders.value[orderIndex].status = statusForm.status
|
||||
}
|
||||
|
||||
// 更新统计数据
|
||||
updateStats()
|
||||
|
||||
ElMessage.success('状态更新成功')
|
||||
statusDialogVisible.value = false
|
||||
} catch (error) {
|
||||
ElMessage.error('状态更新失败')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchOrders()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.admin-orders {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.page-header h2 {
|
||||
margin: 0;
|
||||
color: #303133;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.stats-row {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.stat-card.clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.stat-card.clickable:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.stat-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.stat-number {
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
font-size: 2rem;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.filter-card {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.orders-card {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.order-link {
|
||||
color: #409EFF;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.order-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.username {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-weight: 600;
|
||||
color: #E6A23C;
|
||||
}
|
||||
|
||||
.pagination-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
/* 确保表格内下拉菜单不被裁剪/遮挡 */
|
||||
:deep(.table-dropdown) {
|
||||
z-index: 3000 !important;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.page-header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user