贯通商品编号全流程
This commit is contained in:
@@ -24,6 +24,7 @@ import {
|
||||
import { useSessionStore } from '@/stores/session'
|
||||
import { handoffStatusLabel, orderStatusLabel } from '@/utils/statusLabels'
|
||||
import { formatDateTime } from '@/utils/time'
|
||||
import { formatListingNo } from '@/utils/listingDisplay'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@@ -43,6 +44,9 @@ const uploadingEvidence = ref(false)
|
||||
const openingChat = ref(false)
|
||||
const order = ref<Order | null>(null)
|
||||
const handoffRecords = ref<HandoffRecord[]>([])
|
||||
const listingCode = computed(() =>
|
||||
order.value ? formatListingNo(order.value.listing_no, order.value.listing_id) : '-'
|
||||
)
|
||||
const handoffContent = ref('')
|
||||
const checkoutForm = ref({
|
||||
content: '',
|
||||
@@ -600,6 +604,16 @@ function getStatusTagType(status: string) {
|
||||
if (['cancelled', 'closed'].includes(status)) return 'danger'
|
||||
return 'danger'
|
||||
}
|
||||
|
||||
async function copyListingCode() {
|
||||
if (!order.value) return
|
||||
try {
|
||||
await navigator.clipboard.writeText(listingCode.value)
|
||||
showToast({ message: '商品编号已复制', icon: 'passed' })
|
||||
} catch {
|
||||
showToast({ message: '复制失败', icon: 'cross' })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -634,6 +648,9 @@ function getStatusTagType(status: string) {
|
||||
{{ orderStatusLabel(order.status) }}
|
||||
</van-tag>
|
||||
</div>
|
||||
<button class="listing-code-chip" type="button" @click="copyListingCode">
|
||||
商品编号 {{ listingCode }}
|
||||
</button>
|
||||
<h2 class="order-title">{{ order.title }}</h2>
|
||||
<div class="order-meta-grid">
|
||||
<div class="meta-item">
|
||||
@@ -762,7 +779,7 @@ function getStatusTagType(status: string) {
|
||||
|
||||
<!-- Handoff Records list -->
|
||||
<section class="card-section">
|
||||
<h3 class="section-title">交接日志</h3>
|
||||
<h3 class="section-title">交接日志 · 商品编号 {{ listingCode }}</h3>
|
||||
<van-empty
|
||||
v-if="handoffRecords.length === 0"
|
||||
image="search"
|
||||
@@ -1276,6 +1293,17 @@ function getStatusTagType(status: string) {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.listing-code-chip {
|
||||
margin-bottom: 10px;
|
||||
padding: 4px 9px;
|
||||
border: 1px solid #dbeafe;
|
||||
border-radius: 999px;
|
||||
background: #eff6ff;
|
||||
color: #2563eb;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.order-title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
} from '@/features/orders/api/orders'
|
||||
import { useSessionStore } from '@/stores/session'
|
||||
import { formatDateMinute } from '@/utils/time'
|
||||
import { formatListingNo } from '@/utils/listingDisplay'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
@@ -139,6 +140,19 @@ function ownerActualIncome(order: Order) {
|
||||
const value = order.checkout?.owner_income_amount
|
||||
return typeof value === 'number' ? value : null
|
||||
}
|
||||
|
||||
function formatListingCode(order: Order) {
|
||||
return formatListingNo(order.listing_no, order.listing_id)
|
||||
}
|
||||
|
||||
async function copyListingCode(order: Order) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(formatListingCode(order))
|
||||
showToast({ message: '商品编号已复制', icon: 'passed' })
|
||||
} catch {
|
||||
showToast({ message: '复制失败', icon: 'cross' })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -197,6 +211,9 @@ function ownerActualIncome(order: Order) {
|
||||
|
||||
<!-- 卡片体:关键信息 -->
|
||||
<div class="card-body">
|
||||
<button class="listing-code-chip" type="button" @click.stop="copyListingCode(order)">
|
||||
商品编号 {{ formatListingCode(order) }}
|
||||
</button>
|
||||
<h3 class="order-title">{{ order.title }}</h3>
|
||||
<div class="tag-row">
|
||||
<span class="info-tag">{{ order.server_region }}</span>
|
||||
@@ -370,6 +387,17 @@ function ownerActualIncome(order: Order) {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.listing-code-chip {
|
||||
margin-bottom: 8px;
|
||||
padding: 4px 9px;
|
||||
border: 1px solid #dbeafe;
|
||||
border-radius: 999px;
|
||||
background: #eff6ff;
|
||||
color: #2563eb;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
/* 状态徽章颜色 - 现代轻量化配色 */
|
||||
.badge-pending_payment {
|
||||
color: #ff6a00;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { ChatDotRound, Loading } from '@element-plus/icons-vue'
|
||||
import { ChatDotRound, CopyDocument, Loading } from '@element-plus/icons-vue'
|
||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import QRCode from 'qrcode'
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
import { useSessionStore } from '@/stores/session'
|
||||
import { handoffStatusLabel, orderStatusLabel } from '@/utils/statusLabels'
|
||||
import { formatDateTime } from '@/utils/time'
|
||||
import { formatListingNo } from '@/utils/listingDisplay'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@@ -48,6 +49,10 @@ const handoffRecords = ref<HandoffRecord[]>([])
|
||||
const handoffContent = ref('')
|
||||
const paymentDialogVisible = ref(false)
|
||||
const activePayment = ref<PaymentOrder | null>(null)
|
||||
|
||||
const listingCode = computed(() =>
|
||||
order.value ? formatListingNo(order.value.listing_no, order.value.listing_id) : '-'
|
||||
)
|
||||
const paymentQRCodeURL = ref('')
|
||||
const qrGenerating = ref(false)
|
||||
const checkingPayment = ref(false)
|
||||
@@ -675,6 +680,16 @@ function formatHandoffRecordType(type: string) {
|
||||
}
|
||||
return typeMap[type] || type
|
||||
}
|
||||
|
||||
async function copyListingCode() {
|
||||
if (!order.value) return
|
||||
try {
|
||||
await navigator.clipboard.writeText(listingCode.value)
|
||||
ElMessage.success('商品编号已复制')
|
||||
} catch {
|
||||
ElMessage.error('复制失败')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -685,6 +700,9 @@ function formatHandoffRecordType(type: string) {
|
||||
<p class="eyebrow">订单号:{{ order.order_no }}</p>
|
||||
<h1>{{ order.title }}</h1>
|
||||
<p class="order-meta">{{ order.server_region }} / {{ order.login_platform }}</p>
|
||||
<el-button size="small" plain :icon="CopyDocument" @click="copyListingCode">
|
||||
商品编号 {{ listingCode }}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button type="primary" :loading="openingChat" @click="openOrderChat">
|
||||
<el-icon style="margin-right: 4px"><ChatDotRound /></el-icon>
|
||||
@@ -793,6 +811,7 @@ function formatHandoffRecordType(type: string) {
|
||||
<div v-if="order" class="timeline-section">
|
||||
<div class="section-header">
|
||||
<h2>交接记录</h2>
|
||||
<span>商品编号 {{ listingCode }}</span>
|
||||
</div>
|
||||
<el-empty v-if="handoffRecords.length === 0" description="暂无交接记录" />
|
||||
<el-timeline v-else>
|
||||
|
||||
@@ -8,6 +8,7 @@ import { fetchOrders, type Order } from '@/features/orders'
|
||||
import { useSessionStore } from '@/stores/session'
|
||||
import { orderStatusLabel } from '@/utils/statusLabels'
|
||||
import { formatDateTime } from '@/utils/time'
|
||||
import { formatListingNo } from '@/utils/listingDisplay'
|
||||
|
||||
const loading = ref(false)
|
||||
const orders = ref<Order[]>([])
|
||||
@@ -40,6 +41,9 @@ const displayOrders = computed(() => {
|
||||
filtered = filtered.filter(
|
||||
order =>
|
||||
order.order_no.toLowerCase().includes(keyword) ||
|
||||
formatListingCode(order).toLowerCase().includes(keyword) ||
|
||||
String(order.listing_id).includes(keyword) ||
|
||||
String(order.account_id).includes(keyword) ||
|
||||
order.title.toLowerCase().includes(keyword)
|
||||
)
|
||||
}
|
||||
@@ -152,6 +156,19 @@ async function copyOrderNo(orderNo: string) {
|
||||
}
|
||||
}
|
||||
|
||||
function formatListingCode(order: Order) {
|
||||
return formatListingNo(order.listing_no, order.listing_id)
|
||||
}
|
||||
|
||||
async function copyListingCode(order: Order) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(formatListingCode(order))
|
||||
ElMessage.success('商品编号已复制')
|
||||
} catch {
|
||||
ElMessage.error('复制失败')
|
||||
}
|
||||
}
|
||||
|
||||
function getPaymentDeadline(order: Order) {
|
||||
if (order.status !== 'pending_payment' || !order.created_at) return null
|
||||
if (order.payment_deadline_at) {
|
||||
@@ -182,7 +199,7 @@ function getCountdownMinutes(order: Order) {
|
||||
<div class="orders-toolbar">
|
||||
<el-input
|
||||
v-model="searchKeyword"
|
||||
placeholder="搜索订单号 / 账号 / 起始数字"
|
||||
placeholder="搜索订单号 / 商品编号 / 账号"
|
||||
:prefix-icon="Search"
|
||||
clearable
|
||||
class="search-input"
|
||||
@@ -220,6 +237,16 @@ function getCountdownMinutes(order: Order) {
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="商品编号" width="150">
|
||||
<template #default="{ row }">
|
||||
<div class="order-no-cell">
|
||||
<span class="order-no-text">{{ formatListingCode(row) }}</span>
|
||||
<el-icon class="copy-icon" @click="copyListingCode(row)">
|
||||
<CopyDocument />
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="title" label="账号" min-width="180" />
|
||||
<el-table-column label="金额" width="132">
|
||||
<template #default="{ row }">
|
||||
@@ -299,6 +326,10 @@ function getCountdownMinutes(order: Order) {
|
||||
{{ orderRole(order) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<button class="listing-code-line" type="button" @click.stop="copyListingCode(order)">
|
||||
商品编号 {{ formatListingCode(order) }}
|
||||
<el-icon><CopyDocument /></el-icon>
|
||||
</button>
|
||||
<div class="card-title">{{ order.title }}</div>
|
||||
<div class="card-meta">
|
||||
<div class="meta-row">
|
||||
@@ -425,6 +456,22 @@ function getCountdownMinutes(order: Order) {
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
.listing-code-line {
|
||||
display: inline-flex;
|
||||
width: fit-content;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
margin-top: 10px;
|
||||
padding: 4px 9px;
|
||||
border: 1px solid #dbeafe;
|
||||
border-radius: 999px;
|
||||
background: #eff6ff;
|
||||
color: #2563eb;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.copy-icon {
|
||||
cursor: pointer;
|
||||
color: #9ca3af;
|
||||
|
||||
Reference in New Issue
Block a user