This commit is contained in:
@@ -26,4 +26,9 @@ export const postService = {
|
||||
sendTo(id, userId) {
|
||||
return httpClient.post(`/posts/${id}/send-to/${userId}`);
|
||||
},
|
||||
}
|
||||
getBuyers(id, { page = 1, limit = 10 } = {}) {
|
||||
return httpClient.get(`/posts/${id}/buyers`, {
|
||||
params: { page, limit }
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
@@ -194,6 +194,15 @@ const sendDialogVisible = ref(false);
|
||||
const selectedPost = ref(null);
|
||||
const selectedUser = ref(null);
|
||||
|
||||
// Buyers dialog state (购买人列表)
|
||||
const buyersDialogVisible = ref(false);
|
||||
const buyersPost = ref(null);
|
||||
const buyersItems = ref([]);
|
||||
const buyersLoading = ref(false);
|
||||
const buyersFirst = ref(0);
|
||||
const buyersRows = ref(10);
|
||||
const buyersTotal = ref(0);
|
||||
|
||||
// 修改用户列表相关变量
|
||||
const users = ref({
|
||||
items: [],
|
||||
@@ -288,6 +297,48 @@ const handleSendConfirm = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const formatBuyerPrice = (priceCents) => {
|
||||
if (priceCents < 0) return '赠送';
|
||||
return formatPrice(priceCents / 100);
|
||||
};
|
||||
|
||||
const fetchBuyers = async () => {
|
||||
if (!buyersPost.value) return;
|
||||
buyersLoading.value = true;
|
||||
try {
|
||||
const currentPage = (buyersFirst.value / buyersRows.value) + 1;
|
||||
const response = await postService.getBuyers(buyersPost.value.id, {
|
||||
page: currentPage,
|
||||
limit: buyersRows.value
|
||||
});
|
||||
buyersItems.value = response.data.items || [];
|
||||
buyersTotal.value = response.data.total || 0;
|
||||
} catch (error) {
|
||||
toast.add({
|
||||
severity: 'error',
|
||||
summary: '错误',
|
||||
detail: '加载购买人列表失败',
|
||||
life: 3000
|
||||
});
|
||||
} finally {
|
||||
buyersLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const openBuyers = async (post) => {
|
||||
if (!post || !post.bought_count || post.bought_count <= 0) return;
|
||||
buyersPost.value = post;
|
||||
buyersFirst.value = 0;
|
||||
buyersDialogVisible.value = true;
|
||||
await fetchBuyers();
|
||||
};
|
||||
|
||||
const onBuyersPage = (event) => {
|
||||
buyersFirst.value = event.first;
|
||||
buyersRows.value = event.rows;
|
||||
fetchBuyers();
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -363,6 +414,64 @@ const handleSendConfirm = async () => {
|
||||
</template>
|
||||
</Dialog>
|
||||
|
||||
<!-- Buyers list dialog -->
|
||||
<Dialog v-model:visible="buyersDialogVisible" modal header="购买人列表" :style="{ width: '80vw' }">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="mb-2">
|
||||
<span class="font-bold">曲谱:</span>
|
||||
{{ buyersPost?.title }}
|
||||
</div>
|
||||
|
||||
<DataTable :value="buyersItems" :loading="buyersLoading" :paginator="true" :rows="buyersRows"
|
||||
:totalRecords="buyersTotal" :lazy="true" :first="buyersFirst" @page="onBuyersPage" dataKey="user_id"
|
||||
class="p-datatable-sm" responsiveLayout="scroll" style="max-height: 60vh" scrollable>
|
||||
<template #empty>
|
||||
<div class="text-center p-4">暂无购买记录</div>
|
||||
</template>
|
||||
|
||||
<template #loading>
|
||||
<div class="flex flex-col items-center justify-center p-4">
|
||||
<ProgressSpinner style="width:50px;height:50px" />
|
||||
<span class="mt-2">加载购买人数据...</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<Column field="username" header="用户">
|
||||
<template #body="{ data }">
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="avatar">
|
||||
<div class="mask mask-squircle w-12 h-12">
|
||||
<img :src="data.avatar" :alt="data.username" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-bold">{{ data.username }}</div>
|
||||
<div class="text-xs text-gray-500">ID: {{ data.user_id }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Column>
|
||||
|
||||
<Column field="phone" header="手机号" />
|
||||
|
||||
<Column field="price" header="价格">
|
||||
<template #body="{ data }">
|
||||
{{ formatBuyerPrice(data.price) }}
|
||||
</template>
|
||||
</Column>
|
||||
|
||||
<Column field="bought_at" header="购买时间">
|
||||
<template #body="{ data }">
|
||||
{{ formatDate(data.bought_at) }}
|
||||
</template>
|
||||
</Column>
|
||||
</DataTable>
|
||||
</div>
|
||||
<template #footer>
|
||||
<Button label="关闭" icon="pi pi-times" @click="buyersDialogVisible = false" class="p-button-text" />
|
||||
</template>
|
||||
</Dialog>
|
||||
|
||||
<div class="w-full">
|
||||
<div class="flex justify-between items-center mb-6 gap-4">
|
||||
<h1 class="text-2xl font-semibold text-gray-800 text-nowrap">曲谱列表</h1>
|
||||
@@ -418,9 +527,9 @@ const handleSendConfirm = async () => {
|
||||
|
||||
<Column field="bought_count" header="销售数量" sortable>
|
||||
<template #body="{ data }">
|
||||
<div class="flex flex-col">
|
||||
<span class="text-gray-500">{{ data.bought_count }}</span>
|
||||
</div>
|
||||
<Button v-if="data.bought_count > 0" text severity="info" class="p-0"
|
||||
:label="data.bought_count.toString()" @click="openBuyers(data)" />
|
||||
<span v-else class="text-gray-500">{{ data.bought_count }}</span>
|
||||
</template>
|
||||
</Column>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user