优化:多市场结算后的页面UI

This commit is contained in:
ivan 2026-04-07 11:36:28 +08:00
parent 76a512a2c7
commit b0c8ce8c4f
7 changed files with 125 additions and 9 deletions

View File

@ -111,7 +111,9 @@
"no": "No", "no": "No",
"priceZero": "0¢", "priceZero": "0¢",
"moreActions": "More actions", "moreActions": "More actions",
"settledSubMarketsTitle": "Sub-markets (settled)" "settledSubMarketsTitle": "Sub-markets (settled)",
"expandDescription": "Show more",
"collapseDescription": "Show less"
}, },
"searchPage": { "searchPage": {
"title": "Search", "title": "Search",

View File

@ -111,7 +111,9 @@
"no": "No", "no": "No",
"priceZero": "0¢", "priceZero": "0¢",
"moreActions": "その他の操作", "moreActions": "その他の操作",
"settledSubMarketsTitle": "サブマーケット(決済済み)" "settledSubMarketsTitle": "サブマーケット(決済済み)",
"expandDescription": "全文を表示",
"collapseDescription": "閉じる"
}, },
"searchPage": { "searchPage": {
"title": "検索", "title": "検索",

View File

@ -111,7 +111,9 @@
"no": "No", "no": "No",
"priceZero": "0¢", "priceZero": "0¢",
"moreActions": "더보기", "moreActions": "더보기",
"settledSubMarketsTitle": "하위 마켓(정산 완료)" "settledSubMarketsTitle": "하위 마켓(정산 완료)",
"expandDescription": "전체 보기",
"collapseDescription": "접기"
}, },
"searchPage": { "searchPage": {
"title": "검색", "title": "검색",

View File

@ -111,7 +111,9 @@
"no": "否", "no": "否",
"priceZero": "0¢", "priceZero": "0¢",
"moreActions": "更多操作", "moreActions": "更多操作",
"settledSubMarketsTitle": "子市场(已结算)" "settledSubMarketsTitle": "子市场(已结算)",
"expandDescription": "展开全文",
"collapseDescription": "收起"
}, },
"searchPage": { "searchPage": {
"title": "搜索", "title": "搜索",

View File

@ -111,7 +111,9 @@
"no": "否", "no": "否",
"priceZero": "0¢", "priceZero": "0¢",
"moreActions": "更多操作", "moreActions": "更多操作",
"settledSubMarketsTitle": "子市場(已結算)" "settledSubMarketsTitle": "子市場(已結算)",
"expandDescription": "展開全文",
"collapseDescription": "收起"
}, },
"searchPage": { "searchPage": {
"title": "搜尋", "title": "搜尋",

View File

@ -75,7 +75,29 @@
<div class="rules-pane"> <div class="rules-pane">
<div v-if="eventDetail?.description" class="rules-section"> <div v-if="eventDetail?.description" class="rules-section">
<h3 class="rules-title">{{ t('activity.rulesDescription') }}</h3> <h3 class="rules-title">{{ t('activity.rulesDescription') }}</h3>
<div class="rules-text">{{ eventDetail.description }}</div> <div
class="rules-text"
:class="{
'rules-text--multi-collapsed':
rulesDescriptionCollapsible && !rulesDescriptionExpanded,
}"
>
{{ eventDetail.description }}
</div>
<v-btn
v-if="rulesDescriptionCollapsible"
variant="text"
size="small"
density="compact"
class="rules-description-toggle"
@click="rulesDescriptionExpanded = !rulesDescriptionExpanded"
>
{{
rulesDescriptionExpanded
? t('eventMarkets.collapseDescription')
: t('eventMarkets.expandDescription')
}}
</v-btn>
</div> </div>
<div v-if="eventDetail?.resolutionSource" class="rules-section"> <div v-if="eventDetail?.resolutionSource" class="rules-section">
<h3 class="rules-title">{{ t('activity.rulesSource') }}</h3> <h3 class="rules-title">{{ t('activity.rulesSource') }}</h3>
@ -328,6 +350,15 @@ const markets = computed(() => {
const activeMarkets = computed(() => markets.value.filter((m) => !isPmMarketClosed(m))) const activeMarkets = computed(() => markets.value.filter((m) => !isPmMarketClosed(m)))
/** 已结算/已关闭的子市场 */ /** 已结算/已关闭的子市场 */
const closedMarkets = computed(() => markets.value.filter((m) => isPmMarketClosed(m))) const closedMarkets = computed(() => markets.value.filter((m) => isPmMarketClosed(m)))
/** 多市场时描述默认折叠,避免首屏过长 */
const isMultiMarket = computed(() => markets.value.length > 1)
const RULES_DESC_COLLAPSE_MIN_LEN = 80
const rulesDescriptionExpanded = ref(false)
const rulesDescriptionCollapsible = computed(() => {
if (!isMultiMarket.value) return false
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(() => activeMarkets.value[selectedMarketIndex.value] ?? null)
/** 移动端底部栏显示的市场(选中项或首个),仅在有可交易市场时使用 */ /** 移动端底部栏显示的市场(选中项或首个),仅在有可交易市场时使用 */
const barMarket = computed(() => selectedMarket.value ?? activeMarkets.value[0]) const barMarket = computed(() => selectedMarket.value ?? activeMarkets.value[0])
@ -777,7 +808,10 @@ watch(
) )
watch( watch(
() => route.params.id, () => route.params.id,
() => loadEventDetail(), () => {
rulesDescriptionExpanded.value = false
loadEventDetail()
},
) )
// //
@ -1010,6 +1044,9 @@ watch(
} }
.rules-card .rules-section { .rules-card .rules-section {
display: flex;
flex-direction: column;
align-items: stretch;
margin-bottom: 16px; margin-bottom: 16px;
} }
@ -1034,6 +1071,22 @@ watch(
word-break: break-word; word-break: break-word;
} }
.rules-text--multi-collapsed {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 4;
overflow: hidden;
}
.rules-description-toggle {
margin-top: 4px;
padding: 0 4px !important;
min-width: auto !important;
text-transform: none;
font-weight: 600;
align-self: flex-start;
}
.rules-card .rules-link { .rules-card .rules-link {
font-size: 14px; font-size: 14px;
color: #2563eb; color: #2563eb;

View File

@ -258,7 +258,29 @@
<template v-else> <template v-else>
<div v-if="eventDetail?.description" class="rules-section"> <div v-if="eventDetail?.description" class="rules-section">
<h3 class="rules-title">{{ t('activity.rulesDescription') }}</h3> <h3 class="rules-title">{{ t('activity.rulesDescription') }}</h3>
<div class="rules-text">{{ eventDetail.description }}</div> <div
class="rules-text"
:class="{
'rules-text--multi-collapsed':
rulesDescriptionCollapsible && !rulesDescriptionExpanded,
}"
>
{{ eventDetail.description }}
</div>
<v-btn
v-if="rulesDescriptionCollapsible"
variant="text"
size="small"
density="compact"
class="rules-description-toggle"
@click="rulesDescriptionExpanded = !rulesDescriptionExpanded"
>
{{
rulesDescriptionExpanded
? t('eventMarkets.collapseDescription')
: t('eventMarkets.expandDescription')
}}
</v-btn>
</div> </div>
<div v-if="eventDetail?.resolutionSource" class="rules-section"> <div v-if="eventDetail?.resolutionSource" class="rules-section">
<h3 class="rules-title">{{ t('activity.rulesSource') }}</h3> <h3 class="rules-title">{{ t('activity.rulesSource') }}</h3>
@ -648,6 +670,16 @@ const showSettledOutcomeBar = computed(
() => currentMarketClosed.value && Boolean((settledOutcomeLabel.value ?? '').trim()), () => currentMarketClosed.value && Boolean((settledOutcomeLabel.value ?? '').trim()),
) )
/** 详情页接口若含多个子市场,描述区首屏折叠 */
const isEventMultiMarket = computed(() => (eventDetail.value?.markets?.length ?? 0) > 1)
const RULES_DESC_COLLAPSE_MIN_LEN = 80
const rulesDescriptionExpanded = ref(false)
const rulesDescriptionCollapsible = computed(() => {
if (!isEventMultiMarket.value) return false
const d = eventDetail.value?.description?.trim() ?? ''
return d.length > RULES_DESC_COLLAPSE_MIN_LEN
})
// --- CLOB WebSocket 簿 --- // --- CLOB WebSocket 簿 ---
// token 0 = Yes1 = No // token 0 = Yes1 = No
type OrderBookRows = { price: number; shares: number; priceRaw?: number }[] type OrderBookRows = { price: number; shares: number; priceRaw?: number }[]
@ -1552,7 +1584,10 @@ const handleResize = () => {
watch( watch(
() => route.params.id, () => route.params.id,
() => loadEventDetail(), () => {
rulesDescriptionExpanded.value = false
loadEventDetail()
},
{ immediate: false }, { immediate: false },
) )
@ -2218,6 +2253,9 @@ onUnmounted(() => {
} }
.rules-section { .rules-section {
display: flex;
flex-direction: column;
align-items: stretch;
margin-bottom: 16px; margin-bottom: 16px;
} }
@ -2242,6 +2280,21 @@ onUnmounted(() => {
word-break: break-word; word-break: break-word;
} }
.rules-text--multi-collapsed {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 4;
overflow: hidden;
}
.rules-description-toggle {
margin-top: 4px;
padding: 0 4px !important;
min-width: auto !important;
text-transform: none;
font-weight: 600;
}
.rules-link { .rules-link {
font-size: 14px; font-size: 14px;
color: #2563eb; color: #2563eb;