完善号主订单交接待办入口
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user