|
@@ -3,24 +3,59 @@
|
|
|
<h1 class="page-title">物品审核</h1>
|
|
<h1 class="page-title">物品审核</h1>
|
|
|
|
|
|
|
|
<el-table v-loading="loading" :data="itemList" stripe style="width: 100%">
|
|
<el-table v-loading="loading" :data="itemList" stripe style="width: 100%">
|
|
|
- <el-table-column prop="title" label="标题" min-width="200" />
|
|
|
|
|
- <el-table-column prop="price" label="价格" width="100" />
|
|
|
|
|
- <el-table-column prop="sellerNickname" label="卖家" width="120" />
|
|
|
|
|
- <el-table-column prop="createdAt" label="发布时间" width="180" />
|
|
|
|
|
- <el-table-column label="操作" width="200">
|
|
|
|
|
|
|
+ <el-table-column label="图片" width="100" align="center">
|
|
|
<template #default="{ row }">
|
|
<template #default="{ row }">
|
|
|
- <el-button type="success" size="small" @click="handleApprove(row.id)">通过上架</el-button>
|
|
|
|
|
- <el-button type="danger" size="small" @click="handleReject(row.id)">驳回</el-button>
|
|
|
|
|
|
|
+ <el-image
|
|
|
|
|
+ v-if="row.images?.length"
|
|
|
|
|
+ :src="row.images[0]"
|
|
|
|
|
+ fit="cover"
|
|
|
|
|
+ style="width: 64px; height: 64px; border-radius: 4px; cursor: pointer"
|
|
|
|
|
+ @click="openImageDialog(row.images ?? [])"
|
|
|
|
|
+ />
|
|
|
|
|
+ <el-empty v-else description="无图" :image-size="40" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="标题 / 描述" min-width="280">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <div class="item-title">{{ row.title }}</div>
|
|
|
|
|
+ <div class="item-desc">{{ row.description || '暂无描述' }}</div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="分类" width="100" align="center">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <el-tag>{{ row.categoryName || '-' }}</el-tag>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="价格" width="100" align="center">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <span class="price">¥{{ row.price }}</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="交易方式" width="100" align="center">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ {{ tradeMethodLabel(row.tradeMethod) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column prop="sellerNickname" label="卖家" width="100" align="center" />
|
|
|
|
|
+ <el-table-column label="发布时间" width="160" align="center">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ {{ formatTime(row.createdAt) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="操作" width="210" align="center" fixed="right">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <el-button type="success" size="small" plain @click="handleApprove(row.id)">通过上架</el-button>
|
|
|
|
|
+ <el-button type="danger" size="small" plain @click="handleReject(row.id)">驳回</el-button>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
</el-table>
|
|
</el-table>
|
|
|
|
|
|
|
|
<el-pagination
|
|
<el-pagination
|
|
|
- v-if="total > pageSize"
|
|
|
|
|
|
|
+ v-if="total > 0"
|
|
|
v-model:current-page="pageNum"
|
|
v-model:current-page="pageNum"
|
|
|
:total="total"
|
|
:total="total"
|
|
|
:page-size="pageSize"
|
|
:page-size="pageSize"
|
|
|
- layout="prev, pager, next"
|
|
|
|
|
|
|
+ layout="total, prev, pager, next"
|
|
|
class="pagination"
|
|
class="pagination"
|
|
|
@current-change="loadItems"
|
|
@current-change="loadItems"
|
|
|
/>
|
|
/>
|
|
@@ -32,6 +67,25 @@
|
|
|
<el-button type="primary" @click="confirmReject">确认驳回</el-button>
|
|
<el-button type="primary" @click="confirmReject">确认驳回</el-button>
|
|
|
</template>
|
|
</template>
|
|
|
</el-dialog>
|
|
</el-dialog>
|
|
|
|
|
+
|
|
|
|
|
+ <el-dialog v-model="imageDialog.visible" title="物品图片" width="600" top="5vh" destroy-on-close>
|
|
|
|
|
+ <div class="image-grid">
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-for="(url, index) in imageDialog.images"
|
|
|
|
|
+ :key="index"
|
|
|
|
|
+ class="image-grid-item"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-image
|
|
|
|
|
+ :src="url"
|
|
|
|
|
+ fit="contain"
|
|
|
|
|
+ :preview-src-list="imageDialog.images"
|
|
|
|
|
+ :initial-index="index"
|
|
|
|
|
+ preview-teleported
|
|
|
|
|
+ style="width: 100%; height: 100%; cursor: pointer"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
@@ -53,6 +107,28 @@ const rejectDialog = reactive({
|
|
|
reason: '',
|
|
reason: '',
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
|
|
+const imageDialog = reactive({
|
|
|
|
|
+ visible: false,
|
|
|
|
|
+ images: [] as string[],
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const openImageDialog = (images: string[]) => {
|
|
|
|
|
+ imageDialog.images = images
|
|
|
|
|
+ imageDialog.visible = true
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const tradeMethodLabel = (method?: string) => {
|
|
|
|
|
+ const map: Record<string, string> = { PICKUP: '自提', DELIVERY: '送货' }
|
|
|
|
|
+ return map[method ?? ''] || method || '-'
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const formatTime = (iso?: string) => {
|
|
|
|
|
+ if (!iso) return '-'
|
|
|
|
|
+ const d = new Date(iso)
|
|
|
|
|
+ const pad = (n: number) => n.toString().padStart(2, '0')
|
|
|
|
|
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
const loadItems = async () => {
|
|
const loadItems = async () => {
|
|
|
loading.value = true
|
|
loading.value = true
|
|
|
try {
|
|
try {
|
|
@@ -112,9 +188,36 @@ const confirmReject = async () => {
|
|
|
font-size: 22px;
|
|
font-size: 22px;
|
|
|
margin-bottom: 20px;
|
|
margin-bottom: 20px;
|
|
|
}
|
|
}
|
|
|
|
|
+.item-title {
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ margin-bottom: 4px;
|
|
|
|
|
+}
|
|
|
|
|
+.item-desc {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ color: #909399;
|
|
|
|
|
+ display: -webkit-box;
|
|
|
|
|
+ -webkit-line-clamp: 2;
|
|
|
|
|
+ -webkit-box-orient: vertical;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+}
|
|
|
|
|
+.price {
|
|
|
|
|
+ color: #f56c6c;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+}
|
|
|
.pagination {
|
|
.pagination {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
justify-content: center;
|
|
justify-content: center;
|
|
|
padding: 20px 0;
|
|
padding: 20px 0;
|
|
|
}
|
|
}
|
|
|
|
|
+.image-grid {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: repeat(3, 1fr);
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+}
|
|
|
|
|
+.image-grid-item {
|
|
|
|
|
+ aspect-ratio: 1;
|
|
|
|
|
+ background: #f5f7fa;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|