修改:增加close市场过滤

This commit is contained in:
马丁 2026-07-04 21:35:07 +08:00
parent 18ac89a0df
commit 537f3030e7
3 changed files with 29 additions and 77 deletions

View File

@ -74,6 +74,13 @@ export function isPmMarketClosed(m: PmEventMarketItem | null | undefined): boole
return m?.closed === true
}
/** 过滤掉已关闭的子市场(服务端公开接口已过滤,保留供本地兜底) */
export function filterOpenMarkets(
markets: PmEventMarketItem[] | undefined,
): PmEventMarketItem[] {
return (markets ?? []).filter((m) => !isPmMarketClosed(m))
}
/**
* outcomePrices outcomes 01 1100
*/
@ -430,8 +437,20 @@ function mapMarketToOutcome(m: PmEventMarketItem): EventCardOutcome {
*/
export function mapEventItemToCard(item: PmEventListItem): EventCardItem {
const markets = item.markets ?? []
if (markets.length === 0) {
return buildEventCardItem(item, markets, false, undefined)
}
const multi = markets.length > 1
const firstMarket = markets[0]
return buildEventCardItem(item, markets, multi, firstMarket)
}
function buildEventCardItem(
item: PmEventListItem,
markets: PmEventMarketItem[],
multi: boolean,
firstMarket: PmEventMarketItem | undefined,
): EventCardItem {
const firstPrices = firstMarket ? parseOutcomePrices(firstMarket) : { yesPrice: 0.5, noPrice: 0.5 }
return {

View File

@ -118,14 +118,14 @@
<!-- 可交易市场列表 -->
<v-card
v-if="activeMarkets.length > 0"
v-if="markets.length > 0"
class="markets-list-card"
elevation="0"
rounded="lg"
>
<div class="markets-list">
<div
v-for="(market, index) in activeMarkets"
v-for="(market, index) in markets"
:key="market.ID ?? market.id ?? index"
class="market-row"
:class="{ selected: selectedMarketIndex === index }"
@ -161,46 +161,11 @@
</div>
</div>
</v-card>
<!-- 已结算子市场 design vb1xr 一致标题 + 行内结果角标 -->
<v-card
v-if="closedMarkets.length > 0"
class="markets-settled-card"
elevation="0"
rounded="lg"
>
<div class="markets-settled-head">
{{ t('eventMarkets.settledSubMarketsTitle') }}
</div>
<div class="markets-settled-list">
<div
v-for="(market, index) in closedMarkets"
:key="market.ID ?? market.id ?? `c-${index}`"
class="markets-settled-row"
@click="goToTradeDetail(market)"
>
<div class="markets-settled-row-text">
<span class="markets-settled-question">{{
market.question || t('eventMarkets.marketPlaceholder')
}}</span>
<span class="markets-settled-vol">{{ formatVolumeLine(market.volume) }}</span>
</div>
<span
v-if="settledWinnerPill(market)"
class="markets-settled-pill"
:class="settledPillClass(market)"
>
{{ settledWinnerPill(market)!.label }}
</span>
<v-icon class="markets-settled-chevron" size="18">mdi-chevron-right</v-icon>
</div>
</div>
</v-card>
</v-col>
<!-- 右侧购买组件桌面端显示移动端用底部栏+弹窗 -->
<v-col v-if="!isMobile" cols="12" class="trade-col">
<div v-if="activeMarkets.length > 0" class="trade-sidebar">
<div v-if="markets.length > 0" class="trade-sidebar">
<TradeComponent
:market="tradeMarketPayload"
:initial-option="tradeInitialOption"
@ -210,7 +175,7 @@
</v-row>
<!-- 移动端 market 时显示固定底部 Yes/No + 三点菜单Merge/Split -->
<template v-if="isMobile && activeMarkets.length === 1">
<template v-if="isMobile && markets.length === 1">
<div class="mobile-trade-bar-spacer" aria-hidden="true"></div>
<div class="mobile-trade-bar">
<v-btn
@ -261,7 +226,7 @@
</div>
</template>
<!-- 移动端交易弹窗 market 与多 market 均需 market 时通过列表 Buy Yes/No 打开 -->
<template v-if="isMobile && activeMarkets.length > 0">
<template v-if="isMobile && markets.length > 0">
<v-bottom-sheet v-model="tradeSheetOpen" content-class="event-markets-trade-sheet">
<TradeComponent
v-if="tradeSheetRenderContent"
@ -297,8 +262,6 @@ import {
findPmEvent,
getMarketId,
getClobTokenId,
getPmMarketSettledWinner,
isPmMarketClosed,
type FindPmEventParams,
type PmEventListItem,
type PmEventMarketItem,
@ -340,14 +303,7 @@ const pendingMergeSplitDialog = ref<'merge' | 'split' | null>(null)
const mobileMenuOpen = ref(false)
/** TradeComponent 引用,用于从底部栏触发 Merge/Split */
const tradeComponentRef = ref<InstanceType<typeof TradeComponent> | null>(null)
const markets = computed(() => {
const list = eventDetail.value?.markets ?? []
return list.length > 0 ? list : []
})
/** 仍可交易的市场closed !== true */
const activeMarkets = computed(() => markets.value.filter((m) => !isPmMarketClosed(m)))
/** 已结算/已关闭的子市场 */
const closedMarkets = computed(() => markets.value.filter((m) => isPmMarketClosed(m)))
const markets = computed(() => eventDetail.value?.markets ?? [])
/** 多市场时描述默认折叠,避免首屏过长 */
const isMultiMarket = computed(() => markets.value.length > 1)
const RULES_DESC_COLLAPSE_MIN_LEN = 80
@ -357,9 +313,9 @@ const rulesDescriptionCollapsible = computed(() => {
const d = eventDetail.value?.description?.trim() ?? ''
return d.length > RULES_DESC_COLLAPSE_MIN_LEN
})
const selectedMarket = computed(() => activeMarkets.value[selectedMarketIndex.value] ?? null)
const selectedMarket = computed(() => markets.value[selectedMarketIndex.value] ?? null)
/** 移动端底部栏显示的市场(选中项或首个),仅在有可交易市场时使用 */
const barMarket = computed(() => selectedMarket.value ?? activeMarkets.value[0])
const barMarket = computed(() => selectedMarket.value ?? markets.value[0])
/** 传给购买组件的市场数据(当前选中的市场) */
const tradeMarketPayload = computed(() => {
const m = selectedMarket.value
@ -391,26 +347,6 @@ function formatVolume(volume: number | undefined): string {
return `$${Math.round(volume)} Vol.`
}
/** 已结算列表 secondary 行Vol. $12.4M / k与设计稿一致 */
function formatVolumeLine(volume: number | undefined): string {
if (volume == null || !Number.isFinite(volume)) return 'Vol. —'
if (volume >= 1_000_000) return `Vol. $${(volume / 1_000_000).toFixed(1)}M`
if (volume >= 1000) return `Vol. $${(volume / 1000).toFixed(1)}k`
return `Vol. $${Math.round(volume)}`
}
function settledWinnerPill(market: PmEventMarketItem) {
return getPmMarketSettledWinner(market)
}
function settledPillClass(market: PmEventMarketItem): string {
const w = getPmMarketSettledWinner(market)
if (!w) return 'markets-settled-pill--neutral'
if (w.winnerIndex === 0) return 'markets-settled-pill--yes'
if (w.winnerIndex === 1) return 'markets-settled-pill--no'
return 'markets-settled-pill--neutral'
}
function formatExpiresAt(endDate: string | undefined): string {
if (!endDate) return ''
try {
@ -710,7 +646,7 @@ async function loadEventDetail() {
}
watch(
activeMarkets,
markets,
(list) => {
if (selectedMarketIndex.value >= list.length) {
selectedMarketIndex.value = Math.max(0, list.length - 1)

View File

@ -517,10 +517,7 @@ function setChartMode(mode: 'yesno' | 'crypto') {
}
/** 当前市场(用于交易组件与 Split 拆单):取接口返回的第一个市场 */
const currentMarket = computed(() => {
const list = eventDetail.value?.markets ?? []
return list[0] ?? null
})
const currentMarket = computed(() => eventDetail.value?.markets?.[0] ?? null)
const currentMarketClosed = computed(() => isPmMarketClosed(currentMarket.value))