霖雨寺
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
<script setup lang="ts">
|
||||
import { DeleteOutlined, EditOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons-vue';
|
||||
import { Modal, message } from 'ant-design-vue';
|
||||
import type { ColumnsType } from 'ant-design-vue/es/table';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import {
|
||||
deleteProduct,
|
||||
listProducts,
|
||||
type Product,
|
||||
type ProductStatus,
|
||||
} from '@/api/products';
|
||||
|
||||
const router = useRouter();
|
||||
const products = ref<Product[]>([]);
|
||||
const loading = ref(false);
|
||||
|
||||
const columns: ColumnsType<Product> = [
|
||||
{ title: '商品名称', dataIndex: 'name', width: 180 },
|
||||
{ title: '简称', dataIndex: 'alias', width: 120 },
|
||||
{ title: '销量', dataIndex: 'sales_count', width: 100 },
|
||||
{ title: '首页展示', dataIndex: 'show_on_home', width: 110 },
|
||||
{ title: '上架时间', dataIndex: 'listed_at', width: 180 },
|
||||
{ title: '开售时间', dataIndex: 'sale_starts_at', width: 180 },
|
||||
{ title: '商品状态', dataIndex: 'status', width: 120 },
|
||||
{ title: '操作', key: 'actions', width: 140, fixed: 'right' },
|
||||
];
|
||||
|
||||
const statusLabels: Record<ProductStatus, string> = {
|
||||
delisted: '已下架',
|
||||
ended: '已结束',
|
||||
inactive: '未启用',
|
||||
pending_list: '待上架',
|
||||
pending_sale: '待开售',
|
||||
selling: '销售中',
|
||||
};
|
||||
|
||||
const statusColors: Record<ProductStatus, string> = {
|
||||
delisted: 'default',
|
||||
ended: 'default',
|
||||
inactive: 'default',
|
||||
pending_list: 'orange',
|
||||
pending_sale: 'blue',
|
||||
selling: 'green',
|
||||
};
|
||||
|
||||
function getStatusLabel(status: ProductStatus) {
|
||||
return statusLabels[status] || status;
|
||||
}
|
||||
|
||||
function getStatusColor(status: ProductStatus) {
|
||||
return statusColors[status] || 'default';
|
||||
}
|
||||
|
||||
function formatDate(value: string | null) {
|
||||
if (!value) {
|
||||
return '-';
|
||||
}
|
||||
const date = new Date(value);
|
||||
return Number.isNaN(date.getTime()) ? value : date.toLocaleString('zh-CN', { hour12: false });
|
||||
}
|
||||
|
||||
async function fetchProducts() {
|
||||
loading.value = true;
|
||||
try {
|
||||
products.value = await listProducts();
|
||||
} catch (error) {
|
||||
message.error(error instanceof Error ? error.message : '加载商品失败,请先选择寺院');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function openCreatePage() {
|
||||
router.push('/products/create');
|
||||
}
|
||||
|
||||
function openEditPage(product: Product) {
|
||||
router.push(`/products/${product.id}/edit`);
|
||||
}
|
||||
|
||||
function confirmDelete(product: Product) {
|
||||
Modal.confirm({
|
||||
title: '删除商品',
|
||||
content: `确认删除商品 ${product.name}?`,
|
||||
okText: '删除',
|
||||
okType: 'danger',
|
||||
cancelText: '取消',
|
||||
async onOk() {
|
||||
await deleteProduct(product.id);
|
||||
message.success('商品已删除');
|
||||
await fetchProducts();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(fetchProducts);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="workspace">
|
||||
<div class="page-heading">
|
||||
<h1>商品管理</h1>
|
||||
<a-space>
|
||||
<a-button :loading="loading" @click="fetchProducts">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
刷新
|
||||
</a-button>
|
||||
<a-button type="primary" @click="openCreatePage">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
新建商品
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="products"
|
||||
:loading="loading"
|
||||
:pagination="{ pageSize: 8, showSizeChanger: false }"
|
||||
:scroll="{ x: 1120 }"
|
||||
bordered
|
||||
row-key="id"
|
||||
size="middle"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'alias'">
|
||||
{{ record.alias || '-' }}
|
||||
</template>
|
||||
|
||||
<template v-if="column.dataIndex === 'show_on_home'">
|
||||
<a-tag :color="record.show_on_home ? 'green' : 'default'">
|
||||
{{ record.show_on_home ? '展示' : '不展示' }}
|
||||
</a-tag>
|
||||
</template>
|
||||
|
||||
<template v-if="column.dataIndex === 'listed_at'">
|
||||
{{ formatDate(record.listed_at) }}
|
||||
</template>
|
||||
|
||||
<template v-if="column.dataIndex === 'sale_starts_at'">
|
||||
{{ formatDate(record.sale_starts_at) }}
|
||||
</template>
|
||||
|
||||
<template v-if="column.dataIndex === 'status'">
|
||||
<a-tag :color="getStatusColor(record.status)">
|
||||
{{ getStatusLabel(record.status) }}
|
||||
</a-tag>
|
||||
</template>
|
||||
|
||||
<template v-if="column.key === 'actions'">
|
||||
<a-space>
|
||||
<a-tooltip title="编辑">
|
||||
<a-button type="text" @click="openEditPage(record)">
|
||||
<template #icon><EditOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip title="删除">
|
||||
<a-button type="text" danger @click="confirmDelete(record)">
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</section>
|
||||
</template>
|
||||
Reference in New Issue
Block a user