新增商品编号搜索
This commit is contained in:
@@ -4,6 +4,7 @@ import type { ListingReviewStatus, ListingStatus } from '@/shared/types/status'
|
||||
|
||||
export interface Listing {
|
||||
id: number
|
||||
listing_no: string
|
||||
account_id: number
|
||||
owner_id: number
|
||||
owner_phone?: string
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
getCoinWan,
|
||||
getDailyLoss,
|
||||
getListingDisplayPrice,
|
||||
formatListingCode,
|
||||
getListingResources,
|
||||
getListingTitle,
|
||||
getLoginMethod,
|
||||
@@ -100,7 +101,10 @@ function formatStatNumber(value: number) {
|
||||
<div class="card-details">
|
||||
<div class="card-title-row">
|
||||
<h3>{{ getListingTitle(listing) }}</h3>
|
||||
<span v-if="dailyLoss" class="daily-loss">日耗 {{ dailyLoss }}</span>
|
||||
<div class="card-title-meta">
|
||||
<span class="listing-no">编号 {{ formatListingCode(listing) }}</span>
|
||||
<span v-if="dailyLoss" class="daily-loss">日耗 {{ dailyLoss }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-panel">
|
||||
@@ -252,6 +256,23 @@ function formatStatNumber(value: number) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.card-title-meta {
|
||||
display: inline-flex;
|
||||
flex: 0 0 auto;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.listing-no {
|
||||
padding: 4px 10px;
|
||||
border: 1px solid #dbeafe;
|
||||
border-radius: 6px;
|
||||
background: #eff6ff;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
color: #2563eb;
|
||||
}
|
||||
|
||||
.daily-loss {
|
||||
flex: 0 0 auto;
|
||||
padding: 4px 10px;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import {
|
||||
defaultHomeAnnouncements,
|
||||
defaultHomeBanners,
|
||||
@@ -24,6 +25,8 @@ const banners = ref<HomeBannerSlide[]>(defaultHomeBanners)
|
||||
const publishOptions = ref<ListingPublishOptions>(emptyListingPublishOptions)
|
||||
const sortBy = ref('recommended')
|
||||
const activeZone = ref('all')
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const {
|
||||
filters,
|
||||
@@ -40,6 +43,8 @@ const {
|
||||
computed(() => listings.value)
|
||||
)
|
||||
|
||||
filters.keyword = routeKeyword()
|
||||
|
||||
const {
|
||||
loading,
|
||||
loadingMore,
|
||||
@@ -50,6 +55,13 @@ const {
|
||||
zoneCount,
|
||||
} = useListingQuery(filters, sortBy, activeZone)
|
||||
|
||||
watch(
|
||||
() => route.query.keyword,
|
||||
() => {
|
||||
filters.keyword = routeKeyword()
|
||||
}
|
||||
)
|
||||
|
||||
const statCards = computed(() => [
|
||||
{ label: '可租账号', value: `${totalListings.value}`, hint: '当前筛选结果' },
|
||||
{
|
||||
@@ -127,6 +139,19 @@ function handleResetFilters() {
|
||||
resetFilters()
|
||||
activeZone.value = 'all'
|
||||
sortBy.value = 'recommended'
|
||||
router.replace({
|
||||
path: '/',
|
||||
query: {
|
||||
...route.query,
|
||||
keyword: undefined,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function routeKeyword() {
|
||||
const keyword = route.query.keyword
|
||||
if (Array.isArray(keyword)) return String(keyword[0] || '')
|
||||
return typeof keyword === 'string' ? keyword : ''
|
||||
}
|
||||
|
||||
loadHome()
|
||||
|
||||
@@ -323,6 +323,18 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mobile-listing-no {
|
||||
display: inline-flex;
|
||||
width: fit-content;
|
||||
margin-top: 6px;
|
||||
padding: 3px 7px;
|
||||
border-radius: 999px;
|
||||
background: #eff6ff;
|
||||
color: #2563eb;
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.card-subtitle {
|
||||
margin: 6px 0 10px;
|
||||
color: #64748b;
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
getListingDisplayPrice,
|
||||
getListingSubtitle,
|
||||
getListingTitle,
|
||||
formatListingCode,
|
||||
getLoginMethod,
|
||||
getServerRegion,
|
||||
hasAcceleratedSaleRatio,
|
||||
@@ -377,7 +378,7 @@ function uniqueOptions(values: string[]) {
|
||||
<van-search
|
||||
v-model="searchValue"
|
||||
shape="round"
|
||||
placeholder="搜区服 / 段位"
|
||||
placeholder="搜编号 / 区服 / 段位"
|
||||
class="home-search"
|
||||
/>
|
||||
<button
|
||||
@@ -510,6 +511,7 @@ function uniqueOptions(values: string[]) {
|
||||
<div class="card-title-row">
|
||||
<h2>{{ getListingTitle(item) }}</h2>
|
||||
</div>
|
||||
<div class="mobile-listing-no">编号 {{ formatListingCode(item) }}</div>
|
||||
<p class="card-subtitle">{{ getListingSubtitle(item) }}</p>
|
||||
<div class="card-badges-row">
|
||||
<span class="server-badge">{{ getServerRegion(item) }}</span>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {
|
||||
ArrowDown,
|
||||
@@ -28,6 +28,7 @@ import { useSessionStore } from '@/stores/session'
|
||||
|
||||
const session = useSessionStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const navItems = [
|
||||
{ label: '首页', to: '/', icon: House },
|
||||
@@ -50,6 +51,7 @@ const sellerServiceItems = [
|
||||
|
||||
const showUserDropdown = ref(false)
|
||||
const supportLoading = ref(false)
|
||||
const topSearchKeyword = ref('')
|
||||
|
||||
const realnameBadge = computed(() => {
|
||||
switch (session.realnameStatus) {
|
||||
@@ -64,6 +66,33 @@ const realnameBadge = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => [route.path, route.query.keyword],
|
||||
() => {
|
||||
if (route.path !== '/') return
|
||||
topSearchKeyword.value = normalizeRouteKeyword(route.query.keyword)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
function normalizeRouteKeyword(value: unknown) {
|
||||
if (Array.isArray(value)) return String(value[0] || '')
|
||||
return typeof value === 'string' ? value : ''
|
||||
}
|
||||
|
||||
function handleTopSearchInput(event: Event) {
|
||||
const value = (event.target as HTMLInputElement).value
|
||||
topSearchKeyword.value = value
|
||||
const keyword = value.trim()
|
||||
router.replace({
|
||||
path: '/',
|
||||
query: {
|
||||
...route.query,
|
||||
keyword: keyword || undefined,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function handleLogout() {
|
||||
session.logout()
|
||||
showUserDropdown.value = false
|
||||
@@ -108,7 +137,11 @@ async function handleSupportClick() {
|
||||
|
||||
<div class="pc-search">
|
||||
<el-icon><Search /></el-icon>
|
||||
<input placeholder="搜索区服 / 段位 / 哈夫币数量 / 皮肤" />
|
||||
<input
|
||||
:value="topSearchKeyword"
|
||||
placeholder="搜索编号 / 区服 / 段位 / 哈夫币数量 / 皮肤"
|
||||
@input="handleTopSearchInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="pc-user-actions">
|
||||
|
||||
@@ -23,6 +23,7 @@ export function getCoinM(item: Listing) {
|
||||
}
|
||||
|
||||
export function formatListingCode(item: Listing) {
|
||||
if (item.listing_no) return item.listing_no
|
||||
return `SP${String(item.id).padStart(6, '0')}`
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
.filter-header {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
@@ -23,6 +23,7 @@ export function getCoinM(item: Listing) {
|
||||
}
|
||||
|
||||
export function formatListingCode(item: Listing) {
|
||||
if (item.listing_no) return item.listing_no
|
||||
return `SP${String(item.id).padStart(6, '0')}`
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tsbuildinfo",
|
||||
"noEmit": true,
|
||||
"types": ["vite/client"],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
|
||||
Reference in New Issue
Block a user