From 89ba32bdbcd36a0262f1c8d11af78a7de2e96c40 Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 14 Feb 2026 13:22:18 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9A=E9=99=90=E4=BB=B7?= =?UTF-8?q?=E5=8D=95=E6=8C=89=E8=A7=84=E5=88=99=E5=8F=AA=E5=8F=96135?= =?UTF-8?q?=E4=B8=AA=E6=A1=A3=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TradeComponent.vue | 60 +++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/src/components/TradeComponent.vue b/src/components/TradeComponent.vue index 3c5e2f7..0795286 100644 --- a/src/components/TradeComponent.vue +++ b/src/components/TradeComponent.vue @@ -182,6 +182,7 @@ hide-details density="compact" @update:model-value="onLimitPriceInput" + @blur="onLimitPriceBlur" @keydown="onLimitPriceKeydown" @paste="onLimitPricePaste" > @@ -439,6 +440,7 @@ hide-details density="compact" @update:model-value="onLimitPriceInput" + @blur="onLimitPriceBlur" @keydown="onLimitPriceKeydown" @paste="onLimitPricePaste" > @@ -936,6 +938,42 @@ import { OrderType, Side } from '../api/constants' const { mobile } = useDisplay() const userStore = useUserStore() +/** 限价单允许的 135 个价格档位(0–1 区间),规则:1–9/10–90/100–9900/9910–9990/9991–9999 */ +function buildAllowedLimitPrices(): number[] { + const list: number[] = [] + for (let i = 1; i <= 9; i++) list.push(i / 10000) + for (let i = 10; i <= 90; i += 10) list.push(i / 10000) + for (let i = 100; i <= 9900; i += 100) list.push(i / 10000) + for (let i = 9910; i <= 9990; i += 10) list.push(i / 10000) + for (let i = 9991; i <= 9999; i++) list.push(i / 10000) + return list +} +const ALLOWED_LIMIT_PRICES = buildAllowedLimitPrices() + +/** 将限价吸附到最近的允许档位 */ +function snapToAllowedPrice(v: number): number { + const clamped = Math.min(1, Math.max(0, Number.isFinite(v) ? v : 0)) + const list = ALLOWED_LIMIT_PRICES + if (list.length === 0) return clamped + let nearest = list[0] as number + let minDiff = Math.abs(clamped - nearest) + for (const p of list) { + const d = Math.abs(clamped - p) + if (d < minDiff) { + minDiff = d + nearest = p + } + } + return nearest +} + +/** 获取当前价格在允许列表中的索引,-1 表示不在列表中 */ +function indexOfAllowedPrice(v: number): number { + const snapped = snapToAllowedPrice(v) + const idx = ALLOWED_LIMIT_PRICES.findIndex((p) => Math.abs(p - snapped) < 1e-9) + return idx >= 0 ? idx : 0 +} + export interface TradeMarketPayload { marketId?: string yesPrice: number @@ -1089,8 +1127,9 @@ function applyInitialOption(option: 'yes' | 'no') { syncLimitPriceFromMarket() } +/** 限价限制到 [0,1] 并吸附到 135 个允许档位之一 */ function clampLimitPrice(v: number): number { - return Math.min(1, Math.max(0, Number.isFinite(v) ? v : 0)) + return snapToAllowedPrice(Math.min(1, Math.max(0, Number.isFinite(v) ? v : 0))) } /** 根据当前 props.market 与 selectedOption 同步 limitPrice(组件显示或 market 更新时调用) */ @@ -1133,11 +1172,16 @@ const handleOptionChange = (option: 'yes' | 'no') => { emit('optionChange', option) } -/** 仅在值在 [0,1] 且为有效数字时更新,否则保持原值不变 */ +/** 仅接受 135 个允许档位:输入值吸附到最近档位,非法值忽略 */ function onLimitPriceInput(v: unknown) { const num = v == null ? NaN : Number(v) if (!Number.isFinite(num) || num < 0 || num > 1) return - limitPrice.value = num + limitPrice.value = snapToAllowedPrice(num) +} + +/** 失焦时吸附到允许档位 */ +function onLimitPriceBlur() { + limitPrice.value = snapToAllowedPrice(limitPrice.value) } /** 只允许数字和小数点输入 */ @@ -1162,13 +1206,17 @@ function onLimitPricePaste(e: ClipboardEvent) { } } -// 限价调整方法(0–1 区间) +// 限价调整方法:在 135 个允许档位间上下切换 const decreasePrice = () => { - limitPrice.value = clampLimitPrice(limitPrice.value - 0.01) + const idx = indexOfAllowedPrice(limitPrice.value) + const nextIdx = Math.max(0, idx - 1) + limitPrice.value = ALLOWED_LIMIT_PRICES[nextIdx] ?? limitPrice.value } const increasePrice = () => { - limitPrice.value = clampLimitPrice(limitPrice.value + 0.01) + const idx = indexOfAllowedPrice(limitPrice.value) + const nextIdx = Math.min(ALLOWED_LIMIT_PRICES.length - 1, idx + 1) + limitPrice.value = ALLOWED_LIMIT_PRICES[nextIdx] ?? limitPrice.value } /** 将 shares 限制为正整数(>= 1) */