优化:最大份额显示
This commit is contained in:
parent
ef4b0c8922
commit
af22e1a91c
@ -35,6 +35,11 @@ interface TradePositionItem {
|
|||||||
- **Buy 模式 Amount 区**:无论余额是否充足,均显示 Amount 标签、Balance、金额输入、+$1/+$20/+$100/Max 快捷按钮(桌面端、嵌入弹窗、移动端弹窗一致)
|
- **Buy 模式 Amount 区**:无论余额是否充足,均显示 Amount 标签、Balance、金额输入、+$1/+$20/+$100/Max 快捷按钮(桌面端、嵌入弹窗、移动端弹窗一致)
|
||||||
- 余额不足时 Buy 显示 Deposit 按钮
|
- 余额不足时 Buy 显示 Deposit 按钮
|
||||||
- 25%/50%/Max 快捷份额
|
- 25%/50%/Max 快捷份额
|
||||||
|
- **Sell 模式 UI 优化**:
|
||||||
|
- Shares 标签与 Max shares 提示同行显示(`max-shares-inline`)
|
||||||
|
- 输入框独占一行(`shares-input-wrapper`)
|
||||||
|
- 25%/50%/Max 按钮独立一行(`sell-shares-buttons`)
|
||||||
|
- 整体布局更清晰:`Shares Max: 2` → `[输入框]` → `[25%][50%][Max]`
|
||||||
- 调用 market API 下单、Split、Merge
|
- 调用 market API 下单、Split、Merge
|
||||||
- **合并/拆分成功后触发事件**:`mergeSuccess`、`splitSuccess`,父组件监听后可刷新持仓列表
|
- **合并/拆分成功后触发事件**:`mergeSuccess`、`splitSuccess`,父组件监听后可刷新持仓列表
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,8 @@ export interface ClobSubmitOrderRequest {
|
|||||||
taker: boolean
|
taker: boolean
|
||||||
tokenID: string
|
tokenID: string
|
||||||
userID: number
|
userID: number
|
||||||
|
/** 市场 ID */
|
||||||
|
marketID: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -77,26 +77,28 @@
|
|||||||
<!-- Sell Market: Shares input + 25%/50%/Max -->
|
<!-- Sell Market: Shares input + 25%/50%/Max -->
|
||||||
<template v-if="activeTab === 'sell'">
|
<template v-if="activeTab === 'sell'">
|
||||||
<div class="input-group shares-group">
|
<div class="input-group shares-group">
|
||||||
<div class="shares-header">
|
<div class="shares-header sell-shares-header">
|
||||||
<span class="label">{{ t('trade.shares') }}</span>
|
<span class="label">{{ t('trade.shares') }}</span>
|
||||||
<div class="shares-input">
|
<span class="max-shares-inline">{{ t('trade.maxShares') }}: {{ maxAvailableShares }}</span>
|
||||||
<v-text-field
|
|
||||||
:model-value="shares"
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
class="shares-input-field"
|
|
||||||
hide-details
|
|
||||||
density="compact"
|
|
||||||
@update:model-value="onSharesInput"
|
|
||||||
@keydown="onSharesKeydown"
|
|
||||||
@paste="onSharesPaste"
|
|
||||||
></v-text-field>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="shares-buttons">
|
<div class="shares-input-wrapper">
|
||||||
|
<v-text-field
|
||||||
|
:model-value="shares"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
class="shares-input-field"
|
||||||
|
hide-details
|
||||||
|
variant="outlined"
|
||||||
|
density="compact"
|
||||||
|
@update:model-value="onSharesInput"
|
||||||
|
@keydown="onSharesKeydown"
|
||||||
|
@paste="onSharesPaste"
|
||||||
|
></v-text-field>
|
||||||
|
</div>
|
||||||
|
<div class="shares-buttons sell-shares-buttons">
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(100)">{{ t('trade.max') }}</v-btn>
|
<v-btn class="share-btn" @click="setMaxShares">{{ t('trade.max') }}</v-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -212,26 +214,28 @@
|
|||||||
<!-- Sell: Shares + To receive + Avg. Price,只显示 Sell Yes/No(无 {{ t('trade.deposit') }}) -->
|
<!-- Sell: Shares + To receive + Avg. Price,只显示 Sell Yes/No(无 {{ t('trade.deposit') }}) -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="input-group shares-group">
|
<div class="input-group shares-group">
|
||||||
<div class="shares-header">
|
<div class="shares-header sell-shares-header">
|
||||||
<span class="label">{{ t('trade.shares') }}</span>
|
<span class="label">{{ t('trade.shares') }}</span>
|
||||||
<div class="shares-input">
|
<span class="max-shares-inline">{{ t('trade.maxShares') }}: {{ maxAvailableShares }}</span>
|
||||||
<v-text-field
|
|
||||||
:model-value="shares"
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
class="shares-input-field"
|
|
||||||
hide-details
|
|
||||||
density="compact"
|
|
||||||
@update:model-value="onSharesInput"
|
|
||||||
@keydown="onSharesKeydown"
|
|
||||||
@paste="onSharesPaste"
|
|
||||||
></v-text-field>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="shares-buttons">
|
<div class="shares-input-wrapper">
|
||||||
|
<v-text-field
|
||||||
|
:model-value="shares"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
variant="outlined"
|
||||||
|
class="shares-input-field"
|
||||||
|
hide-details
|
||||||
|
density="compact"
|
||||||
|
@update:model-value="onSharesInput"
|
||||||
|
@keydown="onSharesKeydown"
|
||||||
|
@paste="onSharesPaste"
|
||||||
|
></v-text-field>
|
||||||
|
</div>
|
||||||
|
<div class="shares-buttons sell-shares-buttons">
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(100)">{{ t('trade.max') }}</v-btn>
|
<v-btn class="share-btn" @click="setMaxShares">{{ t('trade.max') }}</v-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="total-section">
|
<div class="total-section">
|
||||||
@ -298,6 +302,7 @@
|
|||||||
min="0"
|
min="0"
|
||||||
max="100"
|
max="100"
|
||||||
step="0.01"
|
step="0.01"
|
||||||
|
variant="outlined"
|
||||||
class="price-input-field"
|
class="price-input-field"
|
||||||
hide-details
|
hide-details
|
||||||
density="compact"
|
density="compact"
|
||||||
@ -316,21 +321,23 @@
|
|||||||
|
|
||||||
<!-- Shares -->
|
<!-- Shares -->
|
||||||
<div class="input-group shares-group">
|
<div class="input-group shares-group">
|
||||||
<div class="shares-header">
|
<div class="shares-header sell-shares-header">
|
||||||
<span class="label">{{ t('trade.shares') }}</span>
|
<span class="label">{{ t('trade.shares') }}</span>
|
||||||
<div class="shares-input">
|
<span v-if="activeTab === 'sell'" class="max-shares-inline">{{ t('trade.maxShares') }}: {{ maxAvailableShares }}</span>
|
||||||
<v-text-field
|
</div>
|
||||||
:model-value="shares"
|
<div class="shares-input-wrapper">
|
||||||
type="number"
|
<v-text-field
|
||||||
min="1"
|
:model-value="shares"
|
||||||
class="shares-input-field"
|
type="number"
|
||||||
hide-details
|
min="1"
|
||||||
density="compact"
|
variant="outlined"
|
||||||
@update:model-value="onSharesInput"
|
class="shares-input-field"
|
||||||
@keydown="onSharesKeydown"
|
hide-details
|
||||||
@paste="onSharesPaste"
|
density="compact"
|
||||||
></v-text-field>
|
@update:model-value="onSharesInput"
|
||||||
</div>
|
@keydown="onSharesKeydown"
|
||||||
|
@paste="onSharesPaste"
|
||||||
|
></v-text-field>
|
||||||
</div>
|
</div>
|
||||||
<!-- Buy模式的份额调整按钮 -->
|
<!-- Buy模式的份额调整按钮 -->
|
||||||
<div v-if="activeTab === 'buy'" class="shares-buttons">
|
<div v-if="activeTab === 'buy'" class="shares-buttons">
|
||||||
@ -341,10 +348,10 @@
|
|||||||
<v-btn class="share-btn" @click="adjustShares(200)">+200</v-btn>
|
<v-btn class="share-btn" @click="adjustShares(200)">+200</v-btn>
|
||||||
</div>
|
</div>
|
||||||
<!-- Sell模式的份额调整按钮 -->
|
<!-- Sell模式的份额调整按钮 -->
|
||||||
<div v-else class="shares-buttons">
|
<div v-else class="shares-buttons sell-shares-buttons">
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(100)">{{ t('trade.max') }}</v-btn>
|
<v-btn class="share-btn" @click="setMaxShares">{{ t('trade.max') }}</v-btn>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="activeTab === 'buy'" class="matching-info">
|
<div v-if="activeTab === 'buy'" class="matching-info">
|
||||||
<v-icon size="14">mdi-information</v-icon>
|
<v-icon size="14">mdi-information</v-icon>
|
||||||
@ -483,26 +490,28 @@
|
|||||||
<!-- Sell Market: Shares input + 25%/50%/Max -->
|
<!-- Sell Market: Shares input + 25%/50%/Max -->
|
||||||
<template v-if="activeTab === 'sell'">
|
<template v-if="activeTab === 'sell'">
|
||||||
<div class="input-group shares-group">
|
<div class="input-group shares-group">
|
||||||
<div class="shares-header">
|
<div class="shares-header sell-shares-header">
|
||||||
<span class="label">{{ t('trade.shares') }}</span>
|
<span class="label">{{ t('trade.shares') }}</span>
|
||||||
<div class="shares-input">
|
<span class="max-shares-inline">{{ t('trade.maxShares') }}: {{ maxAvailableShares }}</span>
|
||||||
<v-text-field
|
|
||||||
:model-value="shares"
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
class="shares-input-field"
|
|
||||||
hide-details
|
|
||||||
density="compact"
|
|
||||||
@update:model-value="onSharesInput"
|
|
||||||
@keydown="onSharesKeydown"
|
|
||||||
@paste="onSharesPaste"
|
|
||||||
></v-text-field>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="shares-buttons">
|
<div class="shares-input-wrapper">
|
||||||
|
<v-text-field
|
||||||
|
:model-value="shares"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
class="shares-input-field"
|
||||||
|
hide-details
|
||||||
|
density="compact"
|
||||||
|
variant="outlined"
|
||||||
|
@update:model-value="onSharesInput"
|
||||||
|
@keydown="onSharesKeydown"
|
||||||
|
@paste="onSharesPaste"
|
||||||
|
></v-text-field>
|
||||||
|
</div>
|
||||||
|
<div class="shares-buttons sell-shares-buttons">
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(100)">{{ t('trade.max') }}</v-btn>
|
<v-btn class="share-btn" @click="setMaxShares">{{ t('trade.max') }}</v-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -598,26 +607,28 @@
|
|||||||
<!-- Sell: Shares + To receive + Avg. Price -->
|
<!-- Sell: Shares + To receive + Avg. Price -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="input-group shares-group">
|
<div class="input-group shares-group">
|
||||||
<div class="shares-header">
|
<div class="shares-header sell-shares-header">
|
||||||
<span class="label">{{ t('trade.shares') }}</span>
|
<span class="label">{{ t('trade.shares') }}</span>
|
||||||
<div class="shares-input">
|
<span class="max-shares-inline">{{ t('trade.maxShares') }}: {{ maxAvailableShares }}</span>
|
||||||
<v-text-field
|
|
||||||
:model-value="shares"
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
class="shares-input-field"
|
|
||||||
hide-details
|
|
||||||
density="compact"
|
|
||||||
@update:model-value="onSharesInput"
|
|
||||||
@keydown="onSharesKeydown"
|
|
||||||
@paste="onSharesPaste"
|
|
||||||
></v-text-field>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="shares-buttons">
|
<div class="shares-input-wrapper">
|
||||||
|
<v-text-field
|
||||||
|
:model-value="shares"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
class="shares-input-field"
|
||||||
|
hide-details
|
||||||
|
density="compact"
|
||||||
|
variant="outlined"
|
||||||
|
@update:model-value="onSharesInput"
|
||||||
|
@keydown="onSharesKeydown"
|
||||||
|
@paste="onSharesPaste"
|
||||||
|
></v-text-field>
|
||||||
|
</div>
|
||||||
|
<div class="shares-buttons sell-shares-buttons">
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(100)">{{ t('trade.max') }}</v-btn>
|
<v-btn class="share-btn" @click="setMaxShares">{{ t('trade.max') }}</v-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="total-section">
|
<div class="total-section">
|
||||||
@ -676,6 +687,7 @@
|
|||||||
min="0"
|
min="0"
|
||||||
max="100"
|
max="100"
|
||||||
step="0.01"
|
step="0.01"
|
||||||
|
variant="outlined"
|
||||||
class="price-input-field"
|
class="price-input-field"
|
||||||
hide-details
|
hide-details
|
||||||
density="compact"
|
density="compact"
|
||||||
@ -692,21 +704,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group shares-group">
|
<div class="input-group shares-group">
|
||||||
<div class="shares-header">
|
<div class="shares-header sell-shares-header">
|
||||||
<span class="label">{{ t('trade.shares') }}</span>
|
<span class="label">{{ t('trade.shares') }}</span>
|
||||||
<div class="shares-input">
|
<span v-if="activeTab === 'sell'" class="max-shares-inline">{{ t('trade.maxShares') }}: {{ maxAvailableShares }}</span>
|
||||||
<v-text-field
|
</div>
|
||||||
:model-value="shares"
|
<div class="shares-input-wrapper">
|
||||||
type="number"
|
<v-text-field
|
||||||
min="1"
|
:model-value="shares"
|
||||||
class="shares-input-field"
|
type="number"
|
||||||
hide-details
|
min="1"
|
||||||
density="compact"
|
class="shares-input-field"
|
||||||
@update:model-value="onSharesInput"
|
hide-details
|
||||||
@keydown="onSharesKeydown"
|
density="compact"
|
||||||
@paste="onSharesPaste"
|
variant="outlined"
|
||||||
></v-text-field>
|
@update:model-value="onSharesInput"
|
||||||
</div>
|
@keydown="onSharesKeydown"
|
||||||
|
@paste="onSharesPaste"
|
||||||
|
></v-text-field>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="activeTab === 'buy'" class="shares-buttons">
|
<div v-if="activeTab === 'buy'" class="shares-buttons">
|
||||||
<v-btn class="share-btn" @click="adjustShares(-100)">-100</v-btn>
|
<v-btn class="share-btn" @click="adjustShares(-100)">-100</v-btn>
|
||||||
@ -714,10 +728,10 @@
|
|||||||
<v-btn class="share-btn" @click="adjustShares(10)">+10</v-btn>
|
<v-btn class="share-btn" @click="adjustShares(10)">+10</v-btn>
|
||||||
<v-btn class="share-btn" @click="adjustShares(100)">+100</v-btn>
|
<v-btn class="share-btn" @click="adjustShares(100)">+100</v-btn>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="shares-buttons">
|
<div v-else class="shares-buttons sell-shares-buttons">
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(100)">{{ t('trade.max') }}</v-btn>
|
<v-btn class="share-btn" @click="setMaxShares">{{ t('trade.max') }}</v-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group expiration-group">
|
<div class="input-group expiration-group">
|
||||||
@ -872,26 +886,28 @@
|
|||||||
<!-- Sell Market: Shares input + 25%/50%/Max -->
|
<!-- Sell Market: Shares input + 25%/50%/Max -->
|
||||||
<template v-if="activeTab === 'sell'">
|
<template v-if="activeTab === 'sell'">
|
||||||
<div class="input-group shares-group">
|
<div class="input-group shares-group">
|
||||||
<div class="shares-header">
|
<div class="shares-header sell-shares-header">
|
||||||
<span class="label">{{ t('trade.shares') }}</span>
|
<span class="label">{{ t('trade.shares') }}</span>
|
||||||
<div class="shares-input">
|
<span class="max-shares-inline">{{ t('trade.maxShares') }}: {{ maxAvailableShares }}</span>
|
||||||
<v-text-field
|
|
||||||
:model-value="shares"
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
class="shares-input-field"
|
|
||||||
hide-details
|
|
||||||
density="compact"
|
|
||||||
@update:model-value="onSharesInput"
|
|
||||||
@keydown="onSharesKeydown"
|
|
||||||
@paste="onSharesPaste"
|
|
||||||
></v-text-field>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="shares-buttons">
|
<div class="shares-input-wrapper">
|
||||||
|
<v-text-field
|
||||||
|
:model-value="shares"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
class="shares-input-field"
|
||||||
|
hide-details
|
||||||
|
density="compact"
|
||||||
|
variant="outlined"
|
||||||
|
@update:model-value="onSharesInput"
|
||||||
|
@keydown="onSharesKeydown"
|
||||||
|
@paste="onSharesPaste"
|
||||||
|
></v-text-field>
|
||||||
|
</div>
|
||||||
|
<div class="shares-buttons sell-shares-buttons">
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(100)">{{ t('trade.max') }}</v-btn>
|
<v-btn class="share-btn" @click="setMaxShares">{{ t('trade.max') }}</v-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -988,26 +1004,28 @@
|
|||||||
<!-- Sell: Shares + To receive + Avg. Price -->
|
<!-- Sell: Shares + To receive + Avg. Price -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="input-group shares-group">
|
<div class="input-group shares-group">
|
||||||
<div class="shares-header">
|
<div class="shares-header sell-shares-header">
|
||||||
<span class="label">{{ t('trade.shares') }}</span>
|
<span class="label">{{ t('trade.shares') }}</span>
|
||||||
<div class="shares-input">
|
<span class="max-shares-inline">{{ t('trade.maxShares') }}: {{ maxAvailableShares }}</span>
|
||||||
<v-text-field
|
|
||||||
:model-value="shares"
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
class="shares-input-field"
|
|
||||||
hide-details
|
|
||||||
density="compact"
|
|
||||||
@update:model-value="onSharesInput"
|
|
||||||
@keydown="onSharesKeydown"
|
|
||||||
@paste="onSharesPaste"
|
|
||||||
></v-text-field>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="shares-buttons">
|
<div class="shares-input-wrapper">
|
||||||
|
<v-text-field
|
||||||
|
:model-value="shares"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
class="shares-input-field"
|
||||||
|
hide-details
|
||||||
|
variant="outlined"
|
||||||
|
density="compact"
|
||||||
|
@update:model-value="onSharesInput"
|
||||||
|
@keydown="onSharesKeydown"
|
||||||
|
@paste="onSharesPaste"
|
||||||
|
></v-text-field>
|
||||||
|
</div>
|
||||||
|
<div class="shares-buttons sell-shares-buttons">
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(100)">{{ t('trade.max') }}</v-btn>
|
<v-btn class="share-btn" @click="setMaxShares">{{ t('trade.max') }}</v-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="total-section">
|
<div class="total-section">
|
||||||
@ -1069,6 +1087,7 @@
|
|||||||
class="price-input-field"
|
class="price-input-field"
|
||||||
hide-details
|
hide-details
|
||||||
density="compact"
|
density="compact"
|
||||||
|
variant="outlined"
|
||||||
suffix="¢"
|
suffix="¢"
|
||||||
@update:model-value="onLimitPriceInput"
|
@update:model-value="onLimitPriceInput"
|
||||||
@blur="onLimitPriceBlur"
|
@blur="onLimitPriceBlur"
|
||||||
@ -1082,21 +1101,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group shares-group">
|
<div class="input-group shares-group">
|
||||||
<div class="shares-header">
|
<div class="shares-header sell-shares-header">
|
||||||
<span class="label">{{ t('trade.shares') }}</span>
|
<span class="label">{{ t('trade.shares') }}</span>
|
||||||
<div class="shares-input">
|
<span v-if="activeTab === 'sell'" class="max-shares-inline">{{ t('trade.maxShares') }}: {{ maxAvailableShares }}</span>
|
||||||
<v-text-field
|
</div>
|
||||||
:model-value="shares"
|
<div class="shares-input-wrapper">
|
||||||
type="number"
|
<v-text-field
|
||||||
min="1"
|
:model-value="shares"
|
||||||
class="shares-input-field"
|
type="number"
|
||||||
hide-details
|
min="1"
|
||||||
density="compact"
|
class="shares-input-field"
|
||||||
@update:model-value="onSharesInput"
|
hide-details
|
||||||
@keydown="onSharesKeydown"
|
density="compact"
|
||||||
@paste="onSharesPaste"
|
variant="outlined"
|
||||||
></v-text-field>
|
@update:model-value="onSharesInput"
|
||||||
</div>
|
@keydown="onSharesKeydown"
|
||||||
|
@paste="onSharesPaste"
|
||||||
|
></v-text-field>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="activeTab === 'buy'" class="shares-buttons">
|
<div v-if="activeTab === 'buy'" class="shares-buttons">
|
||||||
<v-btn class="share-btn" @click="adjustShares(-100)">-100</v-btn>
|
<v-btn class="share-btn" @click="adjustShares(-100)">-100</v-btn>
|
||||||
@ -1104,10 +1125,10 @@
|
|||||||
<v-btn class="share-btn" @click="adjustShares(10)">+10</v-btn>
|
<v-btn class="share-btn" @click="adjustShares(10)">+10</v-btn>
|
||||||
<v-btn class="share-btn" @click="adjustShares(100)">+100</v-btn>
|
<v-btn class="share-btn" @click="adjustShares(100)">+100</v-btn>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="shares-buttons">
|
<div v-else class="shares-buttons sell-shares-buttons">
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(25)">25%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
<v-btn class="share-btn" @click="setSharesPercentage(50)">50%</v-btn>
|
||||||
<v-btn class="share-btn" @click="setSharesPercentage(100)">{{ t('trade.max') }}</v-btn>
|
<v-btn class="share-btn" @click="setMaxShares">{{ t('trade.max') }}</v-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group expiration-group">
|
<div class="input-group expiration-group">
|
||||||
@ -1602,6 +1623,15 @@ watch(
|
|||||||
{ deep: true },
|
{ deep: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => activeTab.value,
|
||||||
|
(newTab) => {
|
||||||
|
if (newTab === 'sell') {
|
||||||
|
setMaxShares()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
const handleOptionChange = (option: 'yes' | 'no') => {
|
const handleOptionChange = (option: 'yes' | 'no') => {
|
||||||
selectedOption.value = option
|
selectedOption.value = option
|
||||||
@ -1609,6 +1639,11 @@ const handleOptionChange = (option: 'yes' | 'no') => {
|
|||||||
const noP = props.market?.noPrice ?? 0.82
|
const noP = props.market?.noPrice ?? 0.82
|
||||||
limitPrice.value = clampLimitPrice(option === 'yes' ? yesP : noP)
|
limitPrice.value = clampLimitPrice(option === 'yes' ? yesP : noP)
|
||||||
emit('optionChange', option)
|
emit('optionChange', option)
|
||||||
|
|
||||||
|
// Set max shares when option changes in sell mode
|
||||||
|
if (activeTab.value === 'sell') {
|
||||||
|
setMaxShares()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 输入为美分(0–100),与 Yes/No 按钮单位一致 */
|
/** 输入为美分(0–100),与 Yes/No 按钮单位一致 */
|
||||||
@ -1696,9 +1731,32 @@ const adjustShares = (amount: number) => {
|
|||||||
shares.value = clampShares(shares.value + amount)
|
shares.value = clampShares(shares.value + amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 计算当前选中选项的持仓份额 */
|
||||||
|
const currentOptionPositionShares = computed(() => {
|
||||||
|
const positions = props.positions ?? []
|
||||||
|
const currentOutcome = selectedOption.value === 'yes' ? 'Yes' : 'No'
|
||||||
|
let totalShares = 0
|
||||||
|
|
||||||
|
for (const pos of positions) {
|
||||||
|
if (pos.outcomeWord === currentOutcome) {
|
||||||
|
const num = pos.sharesNum ?? parseFloat(pos.shares?.replace(/[^0-9.]/g, ''))
|
||||||
|
if (Number.isFinite(num) && num > 0) {
|
||||||
|
totalShares += num
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalShares
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 最大可卖出份额 */
|
||||||
|
const maxAvailableShares = computed(() => {
|
||||||
|
return Math.floor(currentOptionPositionShares.value)
|
||||||
|
})
|
||||||
|
|
||||||
// 份额百分比调整方法(仅在Sell模式下使用)
|
// 份额百分比调整方法(仅在Sell模式下使用)
|
||||||
const setSharesPercentage = (percentage: number) => {
|
const setSharesPercentage = (percentage: number) => {
|
||||||
const maxShares = 100
|
const maxShares = currentOptionPositionShares.value || 100
|
||||||
shares.value = clampShares(Math.round((maxShares * percentage) / 100))
|
shares.value = clampShares(Math.round((maxShares * percentage) / 100))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1712,6 +1770,14 @@ const setMaxAmount = () => {
|
|||||||
amount.value = balance.value
|
amount.value = balance.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置最大份额(基于当前选项的持仓)
|
||||||
|
const setMaxShares = () => {
|
||||||
|
const maxShares = currentOptionPositionShares.value
|
||||||
|
if (maxShares > 0) {
|
||||||
|
shares.value = clampShares(maxShares)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Buy 模式:余额是否足够(>= 所需金额且不为 0)。cost:balance>0 时用 totalPrice,否则用 amount */
|
/** Buy 模式:余额是否足够(>= 所需金额且不为 0)。cost:balance>0 时用 totalPrice,否则用 amount */
|
||||||
const canAffordBuy = computed(() => {
|
const canAffordBuy = computed(() => {
|
||||||
const bal = balance.value
|
const bal = balance.value
|
||||||
@ -1808,6 +1874,7 @@ async function submitOrder() {
|
|||||||
taker: true,
|
taker: true,
|
||||||
tokenID: tokenId,
|
tokenID: tokenId,
|
||||||
userID: userIdNum,
|
userID: userIdNum,
|
||||||
|
marketID: marketId || '',
|
||||||
},
|
},
|
||||||
{ headers },
|
{ headers },
|
||||||
)
|
)
|
||||||
@ -2067,6 +2134,35 @@ async function submitOrder() {
|
|||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sell模式:Max shares行内提示样式(放在Shares标签右侧) */
|
||||||
|
.max-shares-inline {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #6b7280;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sell模式:输入框独占一行 */
|
||||||
|
.shares-input-wrapper {
|
||||||
|
margin: 4px 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shares-input-wrapper .v-field {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sell模式:shares区域布局优化 */
|
||||||
|
.sell-shares-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sell-shares-buttons {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.matching-info {
|
.matching-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@ -58,6 +58,7 @@
|
|||||||
"avgPrice": "Avg. Price",
|
"avgPrice": "Avg. Price",
|
||||||
"max": "Max",
|
"max": "Max",
|
||||||
"balanceLabel": "Balance",
|
"balanceLabel": "Balance",
|
||||||
|
"maxShares": "Max shares",
|
||||||
"pleaseLogin": "Please log in first",
|
"pleaseLogin": "Please log in first",
|
||||||
"pleaseSelectMarket": "Please select a market (with clobTokenIds)",
|
"pleaseSelectMarket": "Please select a market (with clobTokenIds)",
|
||||||
"userError": "User info error",
|
"userError": "User info error",
|
||||||
|
|||||||
@ -58,6 +58,7 @@
|
|||||||
"avgPrice": "平均価格",
|
"avgPrice": "平均価格",
|
||||||
"max": "最大",
|
"max": "最大",
|
||||||
"balanceLabel": "残高",
|
"balanceLabel": "残高",
|
||||||
|
"maxShares": "最大シェア",
|
||||||
"pleaseLogin": "先にログインしてください",
|
"pleaseLogin": "先にログインしてください",
|
||||||
"pleaseSelectMarket": "市場を選択してください(clobTokenIds が必要)",
|
"pleaseSelectMarket": "市場を選択してください(clobTokenIds が必要)",
|
||||||
"userError": "ユーザー情報エラー",
|
"userError": "ユーザー情報エラー",
|
||||||
|
|||||||
@ -58,6 +58,7 @@
|
|||||||
"avgPrice": "평균 가격",
|
"avgPrice": "평균 가격",
|
||||||
"max": "최대",
|
"max": "최대",
|
||||||
"balanceLabel": "잔액",
|
"balanceLabel": "잔액",
|
||||||
|
"maxShares": "최대 주식",
|
||||||
"pleaseLogin": "먼저 로그인하세요",
|
"pleaseLogin": "먼저 로그인하세요",
|
||||||
"pleaseSelectMarket": "시장을 선택하세요 (clobTokenIds 필요)",
|
"pleaseSelectMarket": "시장을 선택하세요 (clobTokenIds 필요)",
|
||||||
"userError": "사용자 정보 오류",
|
"userError": "사용자 정보 오류",
|
||||||
|
|||||||
@ -58,6 +58,7 @@
|
|||||||
"avgPrice": "平均价",
|
"avgPrice": "平均价",
|
||||||
"max": "最大",
|
"max": "最大",
|
||||||
"balanceLabel": "余额",
|
"balanceLabel": "余额",
|
||||||
|
"maxShares": "最大份额",
|
||||||
"pleaseLogin": "请先登录",
|
"pleaseLogin": "请先登录",
|
||||||
"pleaseSelectMarket": "请先选择市场(需包含 clobTokenIds)",
|
"pleaseSelectMarket": "请先选择市场(需包含 clobTokenIds)",
|
||||||
"userError": "用户信息异常",
|
"userError": "用户信息异常",
|
||||||
|
|||||||
@ -58,6 +58,7 @@
|
|||||||
"avgPrice": "平均價",
|
"avgPrice": "平均價",
|
||||||
"max": "最大",
|
"max": "最大",
|
||||||
"balanceLabel": "餘額",
|
"balanceLabel": "餘額",
|
||||||
|
"maxShares": "最大份額",
|
||||||
"pleaseLogin": "請先登入",
|
"pleaseLogin": "請先登入",
|
||||||
"pleaseSelectMarket": "請先選擇市場(需包含 clobTokenIds)",
|
"pleaseSelectMarket": "請先選擇市場(需包含 clobTokenIds)",
|
||||||
"userError": "用戶資訊異常",
|
"userError": "用戶資訊異常",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user