|
|
@@ -1,22 +1,51 @@
|
|
|
<template>
|
|
|
<div class="page-container">
|
|
|
<PageTitle title="订单执行状态" />
|
|
|
+ <div class="filter-bar">
|
|
|
+ <el-form :model="searchForm" inline>
|
|
|
+ <el-form-item label="订单编号">
|
|
|
+ <el-input v-model="searchForm.keyword" placeholder="请输入订单编号" clearable @clear="handleSearch" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="订单日期">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="searchForm.dateRange"
|
|
|
+ type="daterange"
|
|
|
+ range-separator="至"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ @change="handleSearch"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="订单状态">
|
|
|
+ <el-select v-model="searchForm.orderStatus" placeholder="请选择订单状态" clearable @change="handleSearch">
|
|
|
+ <el-option v-for="item in orderStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" @click="handleSearch">搜索</el-button>
|
|
|
+ <el-button @click="handleReset">重置</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
|
|
|
- <SearchBar :form="searchForm" :filters="filters" />
|
|
|
-
|
|
|
- <el-table :data="tableData" border style="width: 100%">
|
|
|
+ <el-table v-loading="loading" :data="tableData" border style="width: 100%">
|
|
|
<el-table-column prop="orderDate" label="下单日期" width="110" align="center" />
|
|
|
- <el-table-column prop="orderNo" label="订单编号" width="120" align="center" />
|
|
|
- <el-table-column prop="productName" label="产品" min-width="140" show-overflow-tooltip />
|
|
|
- <el-table-column prop="quantity" label="数量" width="80" align="center" />
|
|
|
- <el-table-column prop="price" label="单价" width="100" align="center">
|
|
|
- <template #default="{ row }">¥{{ row.price.toLocaleString() }}</template>
|
|
|
+ <el-table-column prop="orderNo" label="订单编号" width="140" align="center" />
|
|
|
+ <el-table-column prop="productName" label="产品" min-width="200">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <span class="product-name-text">{{ row.productName }}</span>
|
|
|
+ </template>
|
|
|
</el-table-column>
|
|
|
+ <el-table-column prop="quantity" label="数量" width="80" align="center" />
|
|
|
+ <!-- <el-table-column prop="price" label="单价" width="100" align="center">
|
|
|
+ <template #default="{ row }">{{ row.price }}</template>
|
|
|
+ </el-table-column> -->
|
|
|
<el-table-column prop="amount" label="金额" width="100" align="center">
|
|
|
<template #default="{ row }">¥{{ row.amount.toLocaleString() }}</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column prop="shippedQty" label="发货数量" width="90" align="center" />
|
|
|
- <el-table-column prop="unshippedQty" label="未发货数量" width="100" align="center" />
|
|
|
+ <!-- <el-table-column prop="shippedQty" label="发货数量" width="90" align="center" />
|
|
|
+ <el-table-column prop="unshippedQty" label="未发货数量" width="100" align="center" /> -->
|
|
|
<el-table-column prop="status" label="订单状态" width="100" align="center">
|
|
|
<template #default="{ row }">
|
|
|
<span :class="['status-tag', getOrderStatusClass(row.status)]">{{ row.status }}</span>
|
|
|
@@ -24,142 +53,139 @@
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
|
|
|
- <TablePagination v-model:page="pagination.page" v-model:pageSize="pagination.pageSize" :total="pagination.total" />
|
|
|
+ <TablePagination v-model:page="pagination.page" v-model:pageSize="pagination.pageSize" :total="pagination.total" @change="fetchOrderList" />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { reactive, ref } from 'vue';
|
|
|
-import { PageTitle, SearchBar, TablePagination } from '@/components';
|
|
|
-import { BILL_STATUS_OPTIONS, INVOICE_STATUS_OPTIONS, PAY_STATUS_OPTIONS } from '@/constants/status';
|
|
|
+import { reactive, ref, computed } from 'vue';
|
|
|
+import { PageTitle, TablePagination } from '@/components';
|
|
|
+import { getOrderList, getOrderProducts } from '@/api/pc/enterprise/order';
|
|
|
import { getOrderStatusClass } from '@/utils/status';
|
|
|
+import { formatDate } from '@/utils';
|
|
|
+import type { ComponentInternalInstance } from 'vue';
|
|
|
+import { getCurrentInstance, toRefs } from 'vue';
|
|
|
+
|
|
|
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
+const { order_status } = toRefs<any>(proxy?.useDict('order_status'));
|
|
|
+
|
|
|
+const orderStatusOptions = computed(() => [{ label: '全部', value: '' }, ...(order_status.value || [])]);
|
|
|
+
|
|
|
+const loading = ref(false);
|
|
|
+const tableData = ref<any[]>([]);
|
|
|
|
|
|
const searchForm = reactive({
|
|
|
keyword: '',
|
|
|
- dateRange: [],
|
|
|
- billStatus: '',
|
|
|
- invoiceStatus: '',
|
|
|
- payStatus: ''
|
|
|
+ dateRange: [] as string[],
|
|
|
+ orderStatus: ''
|
|
|
});
|
|
|
|
|
|
-const filters = [
|
|
|
- { field: 'billStatus', label: '对账状态', options: BILL_STATUS_OPTIONS },
|
|
|
- { field: 'invoiceStatus', label: '开票状态', options: INVOICE_STATUS_OPTIONS },
|
|
|
- { field: 'payStatus', label: '支付状态', options: PAY_STATUS_OPTIONS }
|
|
|
-];
|
|
|
-
|
|
|
-const pagination = reactive({ page: 1, pageSize: 10, total: 100 });
|
|
|
-
|
|
|
-const tableData = ref([
|
|
|
- {
|
|
|
- orderDate: '2025-11-22',
|
|
|
- orderNo: '2323232323',
|
|
|
- productName: '清华同方超...',
|
|
|
- quantity: 2,
|
|
|
- price: 2115.97,
|
|
|
- amount: 2115.97,
|
|
|
- shippedQty: 2,
|
|
|
- unshippedQty: 2,
|
|
|
- status: '运输中'
|
|
|
- },
|
|
|
- {
|
|
|
- orderDate: '2025-12-09',
|
|
|
- orderNo: '2323412123',
|
|
|
- productName: '清华同方超...',
|
|
|
- quantity: 1,
|
|
|
- price: 4476.12,
|
|
|
- amount: 4476.12,
|
|
|
- shippedQty: 1,
|
|
|
- unshippedQty: 1,
|
|
|
- status: '待发货'
|
|
|
- },
|
|
|
- {
|
|
|
- orderDate: '2025-11-21',
|
|
|
- orderNo: '4566784543',
|
|
|
- productName: '越E500台式...',
|
|
|
- quantity: 5,
|
|
|
- price: 7751.34,
|
|
|
- amount: 7751.34,
|
|
|
- shippedQty: 5,
|
|
|
- unshippedQty: 5,
|
|
|
- status: '已收货'
|
|
|
- },
|
|
|
- {
|
|
|
- orderDate: '2025-11-27',
|
|
|
- orderNo: '2356565654',
|
|
|
- productName: '清华同机电...',
|
|
|
- quantity: 2,
|
|
|
- price: 7936.37,
|
|
|
- amount: 7936.37,
|
|
|
- shippedQty: 2,
|
|
|
- unshippedQty: 2,
|
|
|
- status: '运输中'
|
|
|
- },
|
|
|
- {
|
|
|
- orderDate: '2025-12-11',
|
|
|
- orderNo: '2323412123',
|
|
|
- productName: '清华同方超...',
|
|
|
- quantity: 1,
|
|
|
- price: 3931.45,
|
|
|
- amount: 3931.45,
|
|
|
- shippedQty: 1,
|
|
|
- unshippedQty: 1,
|
|
|
- status: '待发货'
|
|
|
- },
|
|
|
- {
|
|
|
- orderDate: '2025-11-27',
|
|
|
- orderNo: '2323232323',
|
|
|
- productName: '清00台式机...',
|
|
|
- quantity: 6,
|
|
|
- price: 6132.75,
|
|
|
- amount: 6132.75,
|
|
|
- shippedQty: 6,
|
|
|
- unshippedQty: 6,
|
|
|
- status: '已收货'
|
|
|
- },
|
|
|
- {
|
|
|
- orderDate: '2025-11-25',
|
|
|
- orderNo: '2356565654',
|
|
|
- productName: '机电脑超越...',
|
|
|
- quantity: 7,
|
|
|
- price: 3189.56,
|
|
|
- amount: 3189.56,
|
|
|
- shippedQty: 7,
|
|
|
- unshippedQty: 7,
|
|
|
- status: '已收货'
|
|
|
- },
|
|
|
- {
|
|
|
- orderDate: '2025-11-20',
|
|
|
- orderNo: '2323232323',
|
|
|
- productName: '清华同方超...',
|
|
|
- quantity: 2,
|
|
|
- price: 993.66,
|
|
|
- amount: 993.66,
|
|
|
- shippedQty: 2,
|
|
|
- unshippedQty: 2,
|
|
|
- status: '运输中'
|
|
|
- },
|
|
|
- {
|
|
|
- orderDate: '2025-11-17',
|
|
|
- orderNo: '2323412123',
|
|
|
- productName: '超越E500台...',
|
|
|
- quantity: 1,
|
|
|
- price: 2763.35,
|
|
|
- amount: 2763.35,
|
|
|
- shippedQty: 1,
|
|
|
- unshippedQty: 1,
|
|
|
- status: '待发货'
|
|
|
- },
|
|
|
- {
|
|
|
- orderDate: '2025-12-05',
|
|
|
- orderNo: '2323232323',
|
|
|
- productName: '机电脑超越...',
|
|
|
- quantity: 5,
|
|
|
- price: 9286.45,
|
|
|
- amount: 9286.45,
|
|
|
- shippedQty: 5,
|
|
|
- unshippedQty: 5,
|
|
|
- status: '已收货'
|
|
|
+const pagination = reactive({ page: 1, pageSize: 10, total: 0 });
|
|
|
+
|
|
|
+const getStatusLabel = (value: string) => {
|
|
|
+ const found = order_status.value?.find((d: any) => d.value === value);
|
|
|
+ return found?.label || value;
|
|
|
+};
|
|
|
+
|
|
|
+const fetchOrderList = async () => {
|
|
|
+ loading.value = true;
|
|
|
+ try {
|
|
|
+ const params: any = {
|
|
|
+ pageNum: pagination.page,
|
|
|
+ pageSize: pagination.pageSize
|
|
|
+ };
|
|
|
+
|
|
|
+ if (searchForm.keyword) params.orderNo = searchForm.keyword;
|
|
|
+ if (searchForm.orderStatus) params.orderStatus = searchForm.orderStatus;
|
|
|
+ if (searchForm.dateRange && searchForm.dateRange.length === 2) {
|
|
|
+ params.beginTime = formatDate(searchForm.dateRange[0]);
|
|
|
+ params.endTime = formatDate(searchForm.dateRange[1]);
|
|
|
+ }
|
|
|
+
|
|
|
+ const res = await getOrderList(params);
|
|
|
+ if (res.code !== 200) return;
|
|
|
+
|
|
|
+ const orders = res.rows || [];
|
|
|
+ pagination.total = res.total || 0;
|
|
|
+
|
|
|
+ if (orders.length === 0) {
|
|
|
+ tableData.value = [];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取订单商品
|
|
|
+ const orderProductsMap: Record<number, any[]> = {};
|
|
|
+ const orderIds = orders.map((o: any) => o.id);
|
|
|
+ const prodRes = await getOrderProducts(orderIds);
|
|
|
+ if (prodRes.code === 200 && prodRes.rows) {
|
|
|
+ prodRes.rows.forEach((p: any) => {
|
|
|
+ if (!orderProductsMap[p.orderId]) {
|
|
|
+ orderProductsMap[p.orderId] = [];
|
|
|
+ }
|
|
|
+ orderProductsMap[p.orderId].push(p);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按订单合并:同一订单的商品名称拼接,数量/金额汇总
|
|
|
+ const rows: any[] = [];
|
|
|
+ orders.forEach((order: any) => {
|
|
|
+ const products = orderProductsMap[order.id] || [];
|
|
|
+ const productNames = products
|
|
|
+ .map((p: any) => p.productName || '')
|
|
|
+ .filter(Boolean)
|
|
|
+ .join('、');
|
|
|
+ const totalQty = products.reduce((sum: number, p: any) => sum + (p.orderQuantity || 0), 0);
|
|
|
+ const totalAmount = products.reduce((sum: number, p: any) => sum + (p.totalPrice || (p.unitPrice || 0) * (p.orderQuantity || 0)), 0);
|
|
|
+ const totalShipped = products.reduce((sum: number, p: any) => sum + (p.deliveredQuantity || 0), 0);
|
|
|
+ const totalUnshipped = totalQty - totalShipped;
|
|
|
+ const unitPrices = [...new Set(products.map((p: any) => p.unitPrice).filter(Boolean))];
|
|
|
+ const priceDisplay = unitPrices.length === 1 ? `¥${unitPrices[0].toLocaleString()}` : '—';
|
|
|
+
|
|
|
+ rows.push({
|
|
|
+ orderDate: order.createTime || '',
|
|
|
+ orderNo: order.orderNo || '',
|
|
|
+ productName: productNames || '',
|
|
|
+ quantity: totalQty,
|
|
|
+ price: priceDisplay,
|
|
|
+ amount: totalAmount || order.totalAmount || 0,
|
|
|
+ shippedQty: totalShipped,
|
|
|
+ unshippedQty: totalUnshipped,
|
|
|
+ status: getStatusLabel(order.orderStatus || '')
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ tableData.value = rows;
|
|
|
+ } catch (e) {
|
|
|
+ console.error('获取订单列表失败:', e);
|
|
|
+ } finally {
|
|
|
+ loading.value = false;
|
|
|
}
|
|
|
-]);
|
|
|
+};
|
|
|
+
|
|
|
+const handleSearch = () => {
|
|
|
+ pagination.page = 1;
|
|
|
+ fetchOrderList();
|
|
|
+};
|
|
|
+
|
|
|
+const handleReset = () => {
|
|
|
+ searchForm.keyword = '';
|
|
|
+ searchForm.dateRange = [];
|
|
|
+ searchForm.orderStatus = '';
|
|
|
+ handleSearch();
|
|
|
+};
|
|
|
+
|
|
|
+fetchOrderList();
|
|
|
</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.filter-bar {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 12px;
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+.product-name-text {
|
|
|
+ word-break: break-all;
|
|
|
+ line-height: 1.5;
|
|
|
+}
|
|
|
+</style>
|