Files
lgp-admin-plus/apps/web-antd/src/views/customer/order/index.vue
年糕崽崽 0cdfb7e956
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled
更新若干功能
2026-08-20 19:18:39 +08:00

212 lines
5.6 KiB
Vue

<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { Page, useVbenDrawer, useVbenModal } from '@vben/common-ui';
import { Spin, Tag } from 'ant-design-vue';
import { useCrudTable } from '#/components/crud';
import UserDetailModal from '#/components/customer/user-detail-modal.vue';
import { Icon } from '#/components/icon';
import { TableAction } from '#/components/table-action';
import { getOrderStat, orderApi } from './api';
import CustomerOrderDetailDrawer from './components/detail-drawer.vue';
import CustomerOrderFormModal from './components/modal.vue';
import {
ORDER_PAY_STATUS_TEXT,
ORDER_STATUS_COLOR,
ORDER_STATUS_TEXT,
} from './config/constants';
import { formOptions } from './config/search';
import { gridOptions } from './config/table';
defineOptions({
name: 'CustomerOrder',
});
const { FormModal, Grid, gridApi, removeRows, showModal } = useCrudTable({
api: orderApi,
formOptions,
gridOptions,
modalComponent: CustomerOrderFormModal,
toFormValues: (row) => ({
id: row.id,
receiver_name: row.receiver_name,
receiver_phone: row.receiver_phone,
receiver_address: row.receiver_address,
delivery_type: row.delivery_type,
remark: row.remark,
}),
});
const [DetailDrawer, detailDrawerApi] = useVbenDrawer({
connectedComponent: CustomerOrderDetailDrawer,
});
const [UserModal, userModalApi] = useVbenModal({
connectedComponent: UserDetailModal,
});
/** 顶部统计:后端 order/stat 返回各状态数量与总金额 */
const statLoading = ref(false);
const stat = ref<{
amount: number;
amount_text: string;
auditing: number;
status: { amount: number; count: number; status: number }[];
total: number;
}>({ total: 0, amount: 0, amount_text: '0', auditing: 0, status: [] });
async function loadStat() {
statLoading.value = true;
try {
stat.value = (await getOrderStat()) ?? stat.value;
} finally {
statLoading.value = false;
}
}
const statCards = [
{
key: 'total',
label: '订单总数',
icon: 'lucide:receipt',
getValue: (s: typeof stat.value) => String(s.total),
},
{
key: 'amount',
label: '订单总额',
icon: 'lucide:circle-dollar-sign',
getValue: (s: typeof stat.value) => `¥${s.amount_text}`,
},
{
key: 'auditing',
label: '待审凭证',
icon: 'lucide:badge-check',
getValue: (s: typeof stat.value) => String(s.auditing),
},
{
key: 'pending',
label: '待付款',
icon: 'lucide:clock',
getValue: (s: typeof stat.value) =>
String(s.status.find((i) => i.status === 0)?.count ?? 0),
},
];
onMounted(loadStat);
function openDetail(row: Record<string, any>) {
detailDrawerApi.setData({ record: row, gridApi });
detailDrawerApi.open();
}
function openUser(row: Record<string, any>) {
userModalApi.setData({ record: { id: row.user_id } });
userModalApi.open();
}
</script>
<template>
<Page
auto-content-height
content-class="flex flex-col gap-3"
title="订单管理"
>
<FormModal />
<DetailDrawer />
<UserModal />
<!-- 顶部统计条 -->
<Spin :spinning="statLoading">
<div class="grid grid-cols-2 gap-3 lg:grid-cols-4">
<div
v-for="card in statCards"
:key="card.key"
class="bg-card flex items-center gap-3 rounded-lg p-3"
>
<div
class="bg-primary/10 text-primary flex h-10 w-10 shrink-0 items-center justify-center rounded-lg"
>
<Icon :icon="card.icon" :size="20" />
</div>
<div class="min-w-0">
<div class="text-muted-foreground text-xs">{{ card.label }}</div>
<div class="truncate text-lg font-semibold">
{{ card.getValue(stat) }}
</div>
</div>
</div>
</div>
</Spin>
<Grid>
<template #toolbar-actions>
<TableAction
:actions="[
{
label: '批量删除',
danger: true,
icon: 'ant-design:delete-outlined',
popConfirm: {
title: '确定删除勾选的订单吗?',
confirm: () => removeRows(),
},
},
{
label: '刷新统计',
icon: 'lucide:refresh-cw',
onClick: loadStat,
},
]"
/>
</template>
<template #user="{ row }">
<a class="text-primary" @click="openUser(row)">
{{ row.user_name || '-' }}
</a>
</template>
<template #payStatus="{ row }">
<Tag>{{ ORDER_PAY_STATUS_TEXT[row.pay_status] ?? '-' }}</Tag>
</template>
<template #status="{ row }">
<Tag :color="ORDER_STATUS_COLOR[row.status] ?? 'default'">
{{ ORDER_STATUS_TEXT[row.status] ?? '-' }}
</Tag>
</template>
<template #action="{ row }">
<TableAction
:actions="[
{
label: '详情',
type: 'link',
icon: 'uil:eye',
size: 'small',
onClick: () => openDetail(row),
},
{
label: '编辑',
type: 'link',
icon: 'uil:edit',
size: 'small',
onClick: () => showModal(row, true),
},
{
label: '删除',
type: 'link',
danger: true,
icon: 'ant-design:delete-outlined',
size: 'small',
popConfirm: {
title: '确定删除该订单吗?',
confirm: () => removeRows(row.id),
},
},
]"
/>
</template>
</Grid>
</Page>
</template>