完成了订单管理界面编写
This commit is contained in:
@@ -16,6 +16,20 @@ export const getOrderList = (params: OrderPageParams) => {
|
||||
});
|
||||
};
|
||||
|
||||
// 管理员获取所有订单列表
|
||||
export const getAllOrderList = (params: {
|
||||
page: number;
|
||||
size: number;
|
||||
status?: number;
|
||||
orderNo?: string;
|
||||
}) => {
|
||||
return http<OrderPageResponse>({
|
||||
url: "/order/admin/page",
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
};
|
||||
|
||||
// 获取订单详情
|
||||
export const getOrderDetail = (id: number, userId: number) => {
|
||||
return http<OrderDetail>({
|
||||
@@ -46,3 +60,15 @@ export const createOrderDirectly = (
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
// 更新订单状态
|
||||
export const updateOrderStatus = (data: {
|
||||
orderId: number;
|
||||
status: number;
|
||||
}) => {
|
||||
return http({
|
||||
url: "/order/status",
|
||||
method: "put",
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
<li>
|
||||
<router-link
|
||||
to="/admin/orders"
|
||||
to="/admin/order"
|
||||
class="flex items-center p-3 rounded-lg hover:bg-gray-700 transition-colors"
|
||||
>
|
||||
<i class="fa-solid fa-file-invoice mr-3"></i>
|
||||
|
||||
480
src/pages/admin/OrderPage.vue
Normal file
480
src/pages/admin/OrderPage.vue
Normal file
@@ -0,0 +1,480 @@
|
||||
<template>
|
||||
<ManageLayout>
|
||||
<div class="order-manage-page">
|
||||
<!-- 搜索和操作按钮 -->
|
||||
<div class="mb-6 flex justify-between items-center">
|
||||
<div class="flex items-center">
|
||||
<el-input
|
||||
v-model="searchOrderNo"
|
||||
placeholder="搜索订单号"
|
||||
style="width: 200px; margin-right: 16px"
|
||||
@keyup.enter="handleSearch"
|
||||
>
|
||||
<template #prefix>
|
||||
<i class="fa fa-search"></i>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-select
|
||||
v-model="searchStatus"
|
||||
placeholder="订单状态"
|
||||
style="width: 150px; margin-right: 16px"
|
||||
>
|
||||
<el-option label="全部状态" :value="undefined" />
|
||||
<el-option label="待付款" :value="0" />
|
||||
<el-option label="待发货" :value="1" />
|
||||
<el-option label="待收货" :value="2" />
|
||||
<el-option label="已完成" :value="3" />
|
||||
<el-option label="已取消" :value="4" />
|
||||
</el-select>
|
||||
<el-button type="primary" @click="handleSearch">搜索</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 订单表格 -->
|
||||
<el-table
|
||||
:data="paginatedOrders"
|
||||
style="width: 100%"
|
||||
v-loading="loading"
|
||||
border
|
||||
>
|
||||
<el-table-column prop="id" label="订单ID" width="100" />
|
||||
<el-table-column prop="orderNo" label="订单号" width="300" />
|
||||
<el-table-column prop="totalAmount" label="总金额" width="200">
|
||||
<template #default="{ row }"> ¥{{ row.totalAmount }} </template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="payAmount" label="支付金额" width="200">
|
||||
<template #default="{ row }"> ¥{{ row.payAmount }} </template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="statusText" label="状态" width="150">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getStatusType(row.status)">
|
||||
{{ row.statusText }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="productCount" label="商品数量" width="100" />
|
||||
<el-table-column prop="createTime" label="创建时间" width="180">
|
||||
<template #default="{ row }">
|
||||
{{ formatDate(row.createTime) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="300">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" @click="viewOrderDetail(row)"
|
||||
>查看</el-button
|
||||
>
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="updateOrderStatus(row, 1)"
|
||||
v-if="row.status === 0"
|
||||
>
|
||||
支付
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="updateOrderStatus(row, 2)"
|
||||
v-if="row.status === 1"
|
||||
>
|
||||
发货
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="updateOrderStatus(row, 3)"
|
||||
v-if="row.status === 2"
|
||||
>
|
||||
确认收货
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
type="danger"
|
||||
@click="cancelOrder(row)"
|
||||
v-if="row.status === 0"
|
||||
>
|
||||
取消订单
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="mt-6 flex justify-center">
|
||||
<el-pagination
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
:current-page="currentPage"
|
||||
:page-sizes="[5, 10, 20, 50]"
|
||||
:page-size="pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="filteredOrders.length"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 订单详情对话框 -->
|
||||
<el-dialog title="订单详情" v-model="showOrderDetailDialog" width="800px">
|
||||
<div v-if="currentOrder">
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="订单号">{{
|
||||
currentOrder.orderNo
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="订单状态">
|
||||
<el-tag :type="getStatusType(currentOrder.status)">
|
||||
{{ getStatusText(currentOrder.status) }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="总金额"
|
||||
>¥{{ currentOrder.totalAmount }}</el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item label="支付金额"
|
||||
>¥{{ currentOrder.payAmount }}</el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item label="创建时间">{{
|
||||
formatDate(currentOrder.createTime)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item
|
||||
label="支付时间"
|
||||
v-if="currentOrder.payTime"
|
||||
>{{ formatDate(currentOrder.payTime) }}</el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item
|
||||
label="发货时间"
|
||||
v-if="currentOrder.deliveryTime"
|
||||
>{{ formatDate(currentOrder.deliveryTime) }}</el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item
|
||||
label="收货时间"
|
||||
v-if="currentOrder.receiveTime"
|
||||
>{{ formatDate(currentOrder.receiveTime) }}</el-descriptions-item
|
||||
>
|
||||
</el-descriptions>
|
||||
|
||||
<h3 class="mt-4 mb-2">订单商品</h3>
|
||||
<el-table :data="currentOrder.orderItems" style="width: 100%" border>
|
||||
<el-table-column prop="productName" label="商品名称" />
|
||||
<el-table-column prop="skuName" label="规格" width="150" />
|
||||
<el-table-column prop="price" label="单价" width="100">
|
||||
<template #default="{ row }">¥{{ row.price }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="quantity" label="数量" width="80" />
|
||||
<el-table-column prop="totalPrice" label="小计" width="100">
|
||||
<template #default="{ row }">¥{{ row.totalPrice }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</ManageLayout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import {
|
||||
getAllOrderList,
|
||||
updateOrderStatus as updateOrderStatusAPI,
|
||||
} from "@/apis/order";
|
||||
import { OrderListItem, OrderDetail, OrderItem } from "@/types/order";
|
||||
import ManageLayout from "@/layouts/ManageLayout.vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useUserStore } from "@/stores/UserStore";
|
||||
|
||||
// 获取用户存储和路由
|
||||
const userStore = useUserStore();
|
||||
const router = useRouter();
|
||||
|
||||
// 响应式数据
|
||||
const loading = ref(false);
|
||||
const searchOrderNo = ref("");
|
||||
const searchStatus = ref<number | undefined>(undefined);
|
||||
const showOrderDetailDialog = ref(false);
|
||||
const currentOrder = ref<OrderDetail | null>(null);
|
||||
|
||||
// 分页数据
|
||||
const currentPage = ref(1);
|
||||
const pageSize = ref(10);
|
||||
|
||||
// 所有订单数据
|
||||
const orders = ref<OrderListItem[]>([]);
|
||||
|
||||
// 计算属性:根据搜索条件过滤订单
|
||||
const filteredOrders = computed(() => {
|
||||
let result = orders.value;
|
||||
|
||||
if (searchOrderNo.value) {
|
||||
result = result.filter((order) =>
|
||||
order.orderNo?.includes(searchOrderNo.value),
|
||||
);
|
||||
}
|
||||
|
||||
if (searchStatus.value !== undefined) {
|
||||
result = result.filter((order) => order.status === searchStatus.value);
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
// 计算属性:当前页的订单数据
|
||||
const paginatedOrders = computed(() => {
|
||||
const start = (currentPage.value - 1) * pageSize.value;
|
||||
const end = start + pageSize.value;
|
||||
return filteredOrders.value.slice(start, end);
|
||||
});
|
||||
|
||||
// 获取订单状态类型
|
||||
const getStatusType = (status: number) => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return "warning"; // 待付款
|
||||
case 1:
|
||||
return "primary"; // 待发货
|
||||
case 2:
|
||||
return "success"; // 待收货
|
||||
case 3:
|
||||
return "info"; // 已完成
|
||||
case 4:
|
||||
return "danger"; // 已取消
|
||||
default:
|
||||
return "info";
|
||||
}
|
||||
};
|
||||
|
||||
// 获取订单状态文本
|
||||
const getStatusText = (status: number) => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return "待付款";
|
||||
case 1:
|
||||
return "待发货";
|
||||
case 2:
|
||||
return "待收货";
|
||||
case 3:
|
||||
return "已完成";
|
||||
case 4:
|
||||
return "已取消";
|
||||
default:
|
||||
return "未知状态";
|
||||
}
|
||||
};
|
||||
|
||||
// 格式化日期
|
||||
const formatDate = (dateString: string | (string | number)[]) => {
|
||||
if (!dateString) return "";
|
||||
try {
|
||||
let date: Date;
|
||||
// 如果是数组格式 [2025, 12, 20, 16, 41, 46]
|
||||
if (Array.isArray(dateString)) {
|
||||
const [year, month, day, hours = 0, minutes = 0, seconds = 0] =
|
||||
dateString as number[];
|
||||
date = new Date(year, month - 1, day, hours, minutes, seconds); // 月份需要减1
|
||||
} else {
|
||||
// 如果是字符串格式
|
||||
date = new Date(dateString);
|
||||
}
|
||||
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
const hours = String(date.getHours()).padStart(2, "0");
|
||||
const minutes = String(date.getMinutes()).padStart(2, "0");
|
||||
const seconds = String(date.getSeconds()).padStart(2, "0");
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
} catch (e) {
|
||||
console.error("日期格式化错误:", e);
|
||||
return dateString as string;
|
||||
}
|
||||
};
|
||||
|
||||
// 搜索处理
|
||||
const handleSearch = () => {
|
||||
currentPage.value = 1; // 重置到第一页
|
||||
};
|
||||
|
||||
// 分页大小改变
|
||||
const handleSizeChange = (size: number) => {
|
||||
pageSize.value = size;
|
||||
currentPage.value = 1;
|
||||
};
|
||||
|
||||
// 当前页改变
|
||||
const handleCurrentChange = (page: number) => {
|
||||
currentPage.value = page;
|
||||
};
|
||||
|
||||
// 获取订单列表
|
||||
const fetchOrders = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
// 管理员获取所有订单列表
|
||||
const response = await getAllOrderList({
|
||||
page: 1,
|
||||
size: 1000, // 获取所有订单
|
||||
orderNo: searchOrderNo.value || undefined,
|
||||
status: searchStatus.value,
|
||||
});
|
||||
|
||||
// 为每个订单添加statusText
|
||||
const ordersWithStatusText = (response.data?.list || []).map((order) => ({
|
||||
...order,
|
||||
statusText: getStatusText(order.status),
|
||||
}));
|
||||
|
||||
orders.value = ordersWithStatusText;
|
||||
} catch (error) {
|
||||
console.error("获取订单列表错误:", error);
|
||||
ElMessage.error("获取订单列表失败");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 查看订单详情
|
||||
const viewOrderDetail = async (order: OrderListItem) => {
|
||||
try {
|
||||
// 这里需要调用获取订单详情的API,但由于管理员查看订单详情的接口可能需要特殊实现
|
||||
// 暂时使用模拟数据,实际项目中需要后端提供相应接口
|
||||
const mockOrderDetail: OrderDetail = {
|
||||
id: order.id,
|
||||
orderNo: order.orderNo,
|
||||
userId: 0, // 模拟数据
|
||||
totalAmount: order.totalAmount,
|
||||
payAmount: order.payAmount,
|
||||
freightAmount: 0, // 模拟数据
|
||||
payType: 0, // 模拟数据
|
||||
status: order.status,
|
||||
receiverName: "模拟收货人", // 模拟数据
|
||||
receiverPhone: "13800138000", // 模拟数据
|
||||
receiverAddress: "模拟收货地址", // 模拟数据
|
||||
payTime: order.createTime, // 模拟支付时间
|
||||
deliveryTime: "", // 模拟发货时间
|
||||
receiveTime: "", // 模拟收货时间
|
||||
createTime: order.createTime,
|
||||
orderItems: [
|
||||
{
|
||||
id: 1,
|
||||
orderId: order.id,
|
||||
orderNo: order.orderNo,
|
||||
productId: 101,
|
||||
skuId: 1,
|
||||
productName: "商品示例1",
|
||||
skuName: "规格A",
|
||||
productImage: "",
|
||||
price: 99.95,
|
||||
quantity: 2,
|
||||
totalPrice: 199.9,
|
||||
createTime: order.createTime,
|
||||
updateTime: order.createTime,
|
||||
},
|
||||
] as OrderItem[],
|
||||
};
|
||||
|
||||
currentOrder.value = mockOrderDetail;
|
||||
showOrderDetailDialog.value = true;
|
||||
} catch (error) {
|
||||
console.error("获取订单详情错误:", error);
|
||||
ElMessage.error("获取订单详情失败");
|
||||
}
|
||||
};
|
||||
|
||||
// 更新订单状态
|
||||
const updateOrderStatus = async (order: OrderListItem, newStatus: number) => {
|
||||
let actionText = "";
|
||||
switch (newStatus) {
|
||||
case 1:
|
||||
actionText = "支付";
|
||||
break;
|
||||
case 2:
|
||||
actionText = "发货";
|
||||
break;
|
||||
case 3:
|
||||
actionText = "确认收货";
|
||||
break;
|
||||
default:
|
||||
actionText = "更新状态";
|
||||
}
|
||||
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确定要将订单 "${order.orderNo}" 的状态更新为 ${actionText} 吗?`,
|
||||
"确认操作",
|
||||
{
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning",
|
||||
},
|
||||
);
|
||||
|
||||
// 调用更新订单状态API
|
||||
await updateOrderStatusAPI({
|
||||
orderId: order.id,
|
||||
status: newStatus,
|
||||
});
|
||||
|
||||
// 更新本地数据
|
||||
order.status = newStatus;
|
||||
// 根据状态更新状态文本
|
||||
order.statusText = getStatusText(newStatus);
|
||||
|
||||
ElMessage.success(`${actionText}成功`);
|
||||
} catch (error) {
|
||||
console.error("更新订单状态错误:", error);
|
||||
if (error !== "cancel") {
|
||||
ElMessage.error("操作失败");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 取消订单
|
||||
const cancelOrder = async (order: OrderListItem) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确定要取消订单 "${order.orderNo}" 吗?`,
|
||||
"确认操作",
|
||||
{
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning",
|
||||
},
|
||||
);
|
||||
|
||||
// 取消订单,设置状态为已取消(4)
|
||||
await updateOrderStatusAPI({
|
||||
orderId: order.id,
|
||||
status: 4,
|
||||
});
|
||||
|
||||
// 更新本地数据
|
||||
order.status = 4; // 设置为已取消
|
||||
order.statusText = "已取消";
|
||||
ElMessage.success("订单已取消");
|
||||
} catch (error) {
|
||||
console.error("取消订单错误:", error);
|
||||
if (error !== "cancel") {
|
||||
ElMessage.error("操作失败");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
if (userStore.userInfo?.isAdmin !== 1) {
|
||||
ElMessage.error("您没有管理员权限!");
|
||||
router.push("/");
|
||||
}
|
||||
fetchOrders();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.order-manage-page {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user