优化后台列表搜索
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { readError } from '@/shared/utils/error'
|
||||
import { Search } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
|
||||
@@ -28,16 +29,10 @@ const amount = ref<number | undefined>()
|
||||
const currentPage = ref(1)
|
||||
const currentPageSize = ref(20)
|
||||
const total = ref(0)
|
||||
const keywordFilter = ref('')
|
||||
const statusFilter = ref('')
|
||||
const typeFilter = ref('')
|
||||
const isPartialRefund = computed(() => result.value === 'partial_refund')
|
||||
const filteredDisputes = computed(() => {
|
||||
return disputes.value.filter(item => {
|
||||
if (statusFilter.value && item.status !== statusFilter.value) return false
|
||||
if (typeFilter.value && item.type !== typeFilter.value) return false
|
||||
return true
|
||||
})
|
||||
})
|
||||
const pendingCount = computed(
|
||||
() => disputes.value.filter(item => ['open', 'processing'].includes(item.status)).length
|
||||
)
|
||||
@@ -117,7 +112,11 @@ onMounted(loadDisputes)
|
||||
async function loadDisputes() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await fetchAdminDisputes(currentPage.value, currentPageSize.value)
|
||||
const res = await fetchAdminDisputes(currentPage.value, currentPageSize.value, {
|
||||
keyword: keywordFilter.value.trim() || undefined,
|
||||
status: statusFilter.value || undefined,
|
||||
type: typeFilter.value || undefined,
|
||||
})
|
||||
disputes.value = res.items
|
||||
total.value = res.total
|
||||
} finally {
|
||||
@@ -129,6 +128,11 @@ async function handlePageChange() {
|
||||
await loadDisputes()
|
||||
}
|
||||
|
||||
async function queryDisputes() {
|
||||
currentPage.value = 1
|
||||
await loadDisputes()
|
||||
}
|
||||
|
||||
function openArbitration(row: Dispute) {
|
||||
if (!canArbitrate(row)) return
|
||||
activeDispute.value = row
|
||||
@@ -138,8 +142,10 @@ function openArbitration(row: Dispute) {
|
||||
}
|
||||
|
||||
function resetFilters() {
|
||||
keywordFilter.value = ''
|
||||
statusFilter.value = ''
|
||||
typeFilter.value = ''
|
||||
void queryDisputes()
|
||||
}
|
||||
|
||||
function evidenceItems(row: Dispute | null) {
|
||||
@@ -312,14 +318,34 @@ async function handleArbitrate() {
|
||||
</div>
|
||||
|
||||
<div class="filter-panel">
|
||||
<el-select v-model="statusFilter" clearable placeholder="全部状态" class="filter-control">
|
||||
<el-input
|
||||
v-model="keywordFilter"
|
||||
clearable
|
||||
placeholder="订单号 / 商品编号 / 手机号"
|
||||
class="filter-control keyword-filter"
|
||||
@keyup.enter="queryDisputes"
|
||||
@clear="queryDisputes"
|
||||
/>
|
||||
<el-select
|
||||
v-model="statusFilter"
|
||||
clearable
|
||||
placeholder="全部状态"
|
||||
class="filter-control"
|
||||
@change="queryDisputes"
|
||||
>
|
||||
<el-option label="待处理" value="open" />
|
||||
<el-option label="处理中" value="processing" />
|
||||
<el-option label="已处理" value="resolved" />
|
||||
<el-option label="已关闭" value="closed" />
|
||||
<el-option label="已取消" value="cancelled" />
|
||||
</el-select>
|
||||
<el-select v-model="typeFilter" clearable placeholder="全部类型" class="filter-control">
|
||||
<el-select
|
||||
v-model="typeFilter"
|
||||
clearable
|
||||
placeholder="全部类型"
|
||||
class="filter-control"
|
||||
@change="queryDisputes"
|
||||
>
|
||||
<el-option label="无法登录" value="cannot_login" />
|
||||
<el-option label="描述不符" value="false_description" />
|
||||
<el-option label="账号封禁" value="account_banned" />
|
||||
@@ -329,10 +355,11 @@ async function handleArbitrate() {
|
||||
<el-option label="归还超时" value="return_timeout" />
|
||||
<el-option label="结账争议" value="checkout_dispute" />
|
||||
</el-select>
|
||||
<el-button type="primary" :icon="Search" @click="queryDisputes">查询</el-button>
|
||||
<el-button @click="resetFilters">重置</el-button>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" class="table-panel dispute-table" :data="filteredDisputes">
|
||||
<el-table v-loading="loading" class="table-panel dispute-table" :data="disputes">
|
||||
<el-table-column label="商品编号" width="140">
|
||||
<template #default="{ row }">{{ formatListingNo(row.listing_no) }}</template>
|
||||
</el-table-column>
|
||||
@@ -604,6 +631,10 @@ async function handleArbitrate() {
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.keyword-filter {
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
.main-cell,
|
||||
.party-cell {
|
||||
display: grid;
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
} from '@/shared/utils/listingDisplay'
|
||||
|
||||
const filters = reactive<AdminListingQuery>({
|
||||
keyword: '',
|
||||
owner_id: '',
|
||||
status: '',
|
||||
review_status: '',
|
||||
@@ -97,6 +98,7 @@ async function queryListings() {
|
||||
}
|
||||
|
||||
function resetFilters() {
|
||||
filters.keyword = ''
|
||||
filters.owner_id = ''
|
||||
filters.status = ''
|
||||
filters.review_status = ''
|
||||
@@ -442,6 +444,16 @@ function formatQuantity(value: number) {
|
||||
<!-- 筛选和操作行 -->
|
||||
<div class="listing-filter-row">
|
||||
<el-form class="listing-filter-bar" inline>
|
||||
<el-form-item label="编号">
|
||||
<el-input
|
||||
v-model="filters.keyword"
|
||||
clearable
|
||||
placeholder="商品编号 / 订单编号"
|
||||
style="width: 210px"
|
||||
@keyup.enter="queryListings"
|
||||
@clear="queryListings"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="号主 ID">
|
||||
<el-input
|
||||
v-model="filters.owner_id"
|
||||
|
||||
@@ -35,6 +35,12 @@ export interface Dispute {
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
export interface AdminDisputeQuery {
|
||||
keyword?: string
|
||||
status?: string
|
||||
type?: string
|
||||
}
|
||||
|
||||
export async function createDispute(
|
||||
orderId: number,
|
||||
payload: { type: string; description: string; evidence_urls?: string[] }
|
||||
@@ -60,9 +66,9 @@ export async function fetchDisputes(page = 1, pageSize = 20) {
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function fetchAdminDisputes(page = 1, pageSize = 20) {
|
||||
export async function fetchAdminDisputes(page = 1, pageSize = 20, query: AdminDisputeQuery = {}) {
|
||||
const { data } = await apiClient.get<ApiResponse<PaginatedResult<Dispute>>>('/admin/disputes', {
|
||||
params: { page, page_size: pageSize },
|
||||
params: { page, page_size: pageSize, ...query },
|
||||
})
|
||||
return data.data
|
||||
}
|
||||
|
||||
@@ -162,6 +162,7 @@ export async function fetchPendingReviewListings() {
|
||||
}
|
||||
|
||||
export interface AdminListingQuery {
|
||||
keyword?: string
|
||||
owner_id?: string
|
||||
status?: ListingStatus | ''
|
||||
review_status?: ListingReviewStatus | ''
|
||||
|
||||
Reference in New Issue
Block a user