feat(orders): 号主可从自己的列表隐藏已结束订单

只写入隐藏时间,订单和款项仍保留给租客与后台。详情按钮固定对齐,删除跟在后面。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yml2213
2026-10-01 16:22:55 +08:00
co-authored by Cursor
parent a1008f7e6a
commit e5cd7b5c34
15 changed files with 499 additions and 15 deletions
@@ -94,6 +94,7 @@ export interface UserOrderListItem {
deposit_waived_amount_cent: number
status: OrderStatus
handoff_status: HandoffStatus
can_hide?: boolean
payment_deadline_at?: string
created_at: string
}
@@ -385,6 +386,11 @@ export async function cancelOrder(id: number) {
return data.data
}
export async function hideOwnerOrder(id: number) {
const { data } = await apiClient.post<ApiResponse<{ hidden: boolean }>>(`/orders/${id}/hide`)
return data.data
}
export async function submitHandoff(id: number, content: string) {
const { data } = await apiClient.post<ApiResponse<HandoffRecord>>(`/orders/${id}/handoff`, {
content,
@@ -2,11 +2,12 @@
import { readError } from '@/shared/utils/error'
import { onMounted, ref, computed, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { showToast } from 'vant'
import { showConfirmDialog, showToast } from 'vant'
import MobileBottomNav from '@/components/MobileBottomNav.vue'
import {
fetchOrders,
hideOwnerOrder,
startOrderPayment,
type UserOrderListItem,
} from '@/features/orders/api/orders'
@@ -51,6 +52,7 @@ const rentalOrders = ref<UserOrderListItem[]>([])
const crashOrders = ref<MohongOrder[]>([])
const activeTab = ref('all')
const payingOrderId = ref<number | null>(null)
const hidingOrderId = ref<number | null>(null)
const rentalTotal = ref(0)
const rentalPage = ref(1)
const rentalPageSize = 20
@@ -213,6 +215,32 @@ function goDetail(item: UnifiedOrderItem) {
router.push(`/m/orders/${item.id}`)
}
async function handleHideOwnerOrder(order: UserOrderListItem) {
try {
await showConfirmDialog({
title: '删除这条历史订单',
message: '只从你的订单列表移除,订单和款项记录仍会保留。',
confirmButtonText: '删除',
cancelButtonText: '取消',
})
} catch {
return
}
hidingOrderId.value = order.id
try {
await hideOwnerOrder(order.id)
showToast({ message: '已从你的订单列表移除', icon: 'passed' })
if (rentalOrders.value.filter(item => item.id !== order.id).length === 0 && rentalPage.value > 1) {
rentalPage.value -= 1
}
await loadOrders()
} catch (error) {
showToast({ message: readError(error, '删除失败'), icon: 'cross' })
} finally {
hidingOrderId.value = null
}
}
async function handlePay(order: UserOrderListItem) {
const payWay = await selectPayWay()
if (!payWay) return
@@ -378,6 +406,18 @@ async function copyListingCode(order: UserOrderListItem) {
<span class="order-time">{{ formatDateMinute(item.createdAt) }}</span>
</div>
<div class="footer-action">
<van-button
v-if="item.rental.can_hide"
size="small"
plain
hairline
type="danger"
class="hide-btn"
:loading="hidingOrderId === item.rental.id"
@click.stop="handleHideOwnerOrder(item.rental)"
>
删除
</van-button>
<van-button
v-if="item.rental.status === 'pending_payment' && item.rental.role === 'renter'"
size="small"
@@ -869,6 +909,18 @@ async function copyListingCode(order: UserOrderListItem) {
color: #ff5f00;
}
.hide-btn {
height: 28px;
padding: 0 12px;
font-size: 12px;
}
.footer-action {
display: flex;
align-items: center;
gap: 8px;
}
.pay-btn {
height: 28px !important;
padding: 0 16px !important;
@@ -467,18 +467,31 @@
font-weight: 600;
}
/* 操作区按钮 */
/* 操作区:详情固定在左侧对齐,删除或去支付跟在后面 */
.action-buttons {
display: flex;
align-items: center;
gap: 8px;
justify-content: flex-start;
gap: 10px;
}
.action-buttons :deep(.el-button) {
.action-buttons :deep(.el-button:not(.is-link)) {
font-weight: 700;
padding: 7px 16px;
}
.action-buttons :deep(.el-button:first-child:not(.is-link)) {
flex: 0 0 72px;
padding: 7px 0;
}
.action-buttons :deep(.el-button.is-link) {
flex: 0 0 auto;
height: auto;
padding: 0;
font-weight: 600;
}
.muted {
color: #94a3b8;
font-size: 13px;
@@ -1,11 +1,11 @@
<script setup lang="ts">
import { readError } from '@/shared/utils/error'
import { computed, onMounted, ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { CopyDocument, Search } from '@element-plus/icons-vue'
import { fetchOrders, type UserOrderListItem } from '@/features/orders'
import { fetchOrders, hideOwnerOrder, type UserOrderListItem } from '@/features/orders'
import {
fetchMyMohongOrders,
mohongOrderStatusLabel,
@@ -39,6 +39,7 @@ const loading = ref(false)
const rentalOrders = ref<UserOrderListItem[]>([])
const crashOrders = ref<MohongOrder[]>([])
const payingOrderId = ref<number | null>(null)
const hidingOrderId = ref<number | null>(null)
const route = useRoute()
const router = useRouter()
const searchKeyword = ref('')
@@ -194,6 +195,31 @@ function goDetail(item: UnifiedOrderItem) {
router.push(`/orders/${item.id}`)
}
async function handleHideOwnerOrder(order: UserOrderListItem) {
try {
await ElMessageBox.confirm(
'只从你的订单列表移除,订单和款项记录仍会保留。',
'删除这条历史订单',
{ type: 'warning', confirmButtonText: '删除', cancelButtonText: '取消' }
)
} catch {
return
}
hidingOrderId.value = order.id
try {
await hideOwnerOrder(order.id)
ElMessage.success('已从你的订单列表移除')
if (rentalOrders.value.filter(item => item.id !== order.id).length === 0 && rentalPage.value > 1) {
rentalPage.value -= 1
}
await loadOrders()
} catch (error) {
ElMessage.error(readError(error, '删除失败'))
} finally {
hidingOrderId.value = null
}
}
async function handlePay(order: UserOrderListItem) {
payingOrderId.value = order.id
try {
@@ -464,6 +490,7 @@ function bizTypeLabel(bizType: BizType) {
<el-table-column label="操作" width="160" fixed="right">
<template #default="{ row }">
<div class="action-buttons">
<el-button size="small" round @click="goDetail(row)">详情</el-button>
<el-button
v-if="
row.bizType === 'rental' && row.rental && row.rental.status === 'pending_payment'
@@ -477,7 +504,16 @@ function bizTypeLabel(bizType: BizType) {
>
去支付
</el-button>
<el-button size="small" round @click="goDetail(row)">详情</el-button>
<el-button
v-else-if="row.bizType === 'rental' && row.rental?.can_hide"
size="small"
link
type="danger"
:loading="hidingOrderId === row.rental.id"
@click="handleHideOwnerOrder(row.rental)"
>
删除
</el-button>
</div>
</template>
</el-table-column>
@@ -550,6 +586,16 @@ function bizTypeLabel(bizType: BizType) {
{{ getCountdownMinutes(item.rental) }}分钟后超时
</span>
</div>
<el-button
v-if="item.rental.can_hide"
size="small"
link
type="danger"
:loading="hidingOrderId === item.rental.id"
@click.stop="handleHideOwnerOrder(item.rental)"
>
删除
</el-button>
<el-button
v-if="item.rental.status === 'pending_payment' && isRenter(item.rental)"
size="small"