完善号主订单交接待办入口

This commit is contained in:
yml
2026-05-24 19:18:27 +08:00
parent 2678597af4
commit 8c619b37c8
4 changed files with 137 additions and 6 deletions
+12
View File
@@ -3,11 +3,13 @@ import { onMounted, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { fetchOrders, payOrder, type Order } from '@/api/orders'
import { useSessionStore } from '@/stores/session'
import { orderStatusLabel } from '@/utils/statusLabels'
const loading = ref(false)
const orders = ref<Order[]>([])
const payingOrderId = ref<number | null>(null)
const session = useSessionStore()
onMounted(loadOrders)
@@ -40,6 +42,12 @@ function readError(error: unknown, fallback: string) {
}
return fallback
}
function orderRole(order: Order) {
if (order.renter_id === session.userId) return '买家'
if (order.owner_id === session.userId) return '号主'
return '-'
}
</script>
<template>
@@ -55,6 +63,9 @@ function readError(error: unknown, fallback: string) {
<el-table-column prop="title" label="账号" min-width="180" />
<el-table-column prop="rent_amount" label="订单金额" width="100" />
<el-table-column prop="deposit_amount" label="押金" width="100" />
<el-table-column label="身份" width="80">
<template #default="{ row }">{{ orderRole(row) }}</template>
</el-table-column>
<el-table-column label="状态" width="140">
<template #default="{ row }">{{ orderStatusLabel(row.status) }}</template>
</el-table-column>
@@ -64,6 +75,7 @@ function readError(error: unknown, fallback: string) {
v-if="row.status === 'pending_payment'"
size="small"
type="primary"
:disabled="row.renter_id !== session.userId"
:loading="payingOrderId === row.id"
@click="handlePay(row)"
>
@@ -4,10 +4,12 @@ import { useRouter, useRoute } from "vue-router";
import { showToast } from "vant";
import { fetchOrders, payOrder, type Order } from "@/api/orders";
import { useSessionStore } from "@/stores/session";
import { formatDateMinute } from "@/utils/time";
const router = useRouter();
const route = useRoute();
const session = useSessionStore();
const loading = ref(false);
const orders = ref<Order[]>([]);
const activeTab = ref("all");
@@ -188,7 +190,7 @@ function readError(error: unknown, fallback: string) {
<div class="card-footer">
<span class="order-time">{{ formatDateMinute(order.created_at) }}</span>
<van-button
v-if="order.status === 'pending_payment'"
v-if="order.status === 'pending_payment' && order.renter_id === session.userId"
size="mini"
type="primary"
:loading="payingOrderId === order.id"
@@ -1,9 +1,126 @@
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { fetchOrders, type Order } from '@/api/orders'
import { useSessionStore } from '@/stores/session'
import { handoffStatusLabel, orderStatusLabel } from '@/utils/statusLabels'
import { formatDateTime } from '@/utils/time'
const session = useSessionStore()
const loading = ref(false)
const orders = ref<Order[]>([])
const status = ref('')
const sellerOrders = computed(() => orders.value.filter((order) => order.owner_id === session.userId))
const todoOrders = computed(() =>
sellerOrders.value.filter((order) =>
[
'pending_handoff',
'renting',
'overdue',
'pending_checkout_confirm',
'pending_checkout_accept',
'checkout_disputing',
'disputing',
'abnormal',
].includes(order.status),
),
)
const displayOrders = computed(() => {
const source = todoOrders.value
if (!status.value) return source
return source.filter((order) => order.status === status.value)
})
const pendingHandoffCount = computed(
() => sellerOrders.value.filter((order) => order.status === 'pending_handoff' && order.handoff_status === 'pending_owner').length,
)
const pendingCheckoutCount = computed(
() => sellerOrders.value.filter((order) => order.status === 'pending_checkout_confirm').length,
)
const abnormalCount = computed(
() => sellerOrders.value.filter((order) => ['overdue', 'checkout_disputing', 'disputing', 'abnormal'].includes(order.status)).length,
)
onMounted(loadOrders)
async function loadOrders() {
loading.value = true
try {
orders.value = await fetchOrders()
} finally {
loading.value = false
}
}
function actionText(order: Order) {
if (order.status === 'pending_handoff' && order.handoff_status === 'pending_owner') return '提交交接'
if (order.status === 'pending_checkout_confirm') return '处理结账'
if (order.status === 'pending_checkout_accept') return '等待租客'
if (['overdue', 'checkout_disputing', 'disputing', 'abnormal'].includes(order.status)) return '查看处理'
return '详情'
}
</script>
<template>
<section class="page">
<div class="page-header">
<p class="eyebrow">Handoffs</p>
<h1>交接管理</h1>
<p>处理待交接待归还确认和超时订单</p>
<div class="page-header-row">
<div class="page-header">
<p class="eyebrow">Handoffs</p>
<h1>交接管理</h1>
<p>处理待交接租赁中待结账确认和异常订单</p>
</div>
<div class="toolbar-actions">
<el-select v-model="status" clearable placeholder="待办状态" style="width: 190px">
<el-option label="待交接" value="pending_handoff" />
<el-option label="使用中" value="renting" />
<el-option label="逾期中" value="overdue" />
<el-option label="待确认结账" value="pending_checkout_confirm" />
<el-option label="待租客确认修正" value="pending_checkout_accept" />
<el-option label="结账争议中" value="checkout_disputing" />
<el-option label="申诉中" value="disputing" />
<el-option label="异常" value="abnormal" />
</el-select>
<el-button @click="loadOrders">刷新</el-button>
</div>
</div>
<div class="metric-grid">
<div class="metric-card">
<span>待交接</span>
<strong>{{ pendingHandoffCount }} </strong>
</div>
<div class="metric-card">
<span>待结账</span>
<strong>{{ pendingCheckoutCount }} </strong>
</div>
<div class="metric-card">
<span>异常/争议</span>
<strong>{{ abnormalCount }} </strong>
</div>
</div>
<el-table v-loading="loading" class="table-panel" :data="displayOrders">
<el-table-column prop="order_no" label="订单号" min-width="220" />
<el-table-column prop="title" label="账号" min-width="180" />
<el-table-column label="金额" width="120">
<template #default="{ row }">¥{{ row.rent_amount }}</template>
</el-table-column>
<el-table-column label="订单状态" width="150">
<template #default="{ row }">{{ orderStatusLabel(row.status) }}</template>
</el-table-column>
<el-table-column label="交接状态" width="180">
<template #default="{ row }">{{ handoffStatusLabel(row.handoff_status) }}</template>
</el-table-column>
<el-table-column label="创建时间" min-width="180">
<template #default="{ row }">{{ formatDateTime(row.created_at) }}</template>
</el-table-column>
<el-table-column label="操作" width="120">
<template #default="{ row }">
<RouterLink :to="`/orders/${row.id}`">
<el-button size="small" type="primary">{{ actionText(row) }}</el-button>
</RouterLink>
</template>
</el-table-column>
</el-table>
</section>
</template>