新增:取消订单
This commit is contained in:
parent
b73a910b43
commit
8d103e2d98
@ -37,6 +37,26 @@ export async function pmOrderPlace(
|
||||
return post<ApiResponse>('/clob/gateway/submitOrder', data, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订单请求体(/clob/gateway/cancelOrder)
|
||||
*/
|
||||
export interface ClobCancelOrderRequest {
|
||||
orderID: number
|
||||
tokenID: string
|
||||
userID: number
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /clob/gateway/cancelOrder
|
||||
* 取消订单,需鉴权
|
||||
*/
|
||||
export async function pmCancelOrder(
|
||||
data: ClobCancelOrderRequest,
|
||||
config?: { headers?: Record<string, string> }
|
||||
): Promise<ApiResponse> {
|
||||
return post<ApiResponse>('/clob/gateway/cancelOrder', data, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Split 请求体(/PmMarket/split)
|
||||
* 用 USDC 兑换该市场的 Yes+No 份额(1 USDC ≈ 1 Yes + 1 No)
|
||||
|
||||
@ -260,7 +260,7 @@
|
||||
<div class="order-mobile-price">{{ ord.price }} • {{ ord.total }}</div>
|
||||
</div>
|
||||
<div class="order-mobile-right">
|
||||
<v-btn icon variant="text" size="small" class="order-cancel-icon" color="error" @click.stop="cancelOrder(ord.id)">
|
||||
<v-btn icon variant="text" size="small" class="order-cancel-icon" color="error" :disabled="cancelOrderLoading" @click.stop="cancelOrder(ord)">
|
||||
<v-icon size="20">mdi-close</v-icon>
|
||||
</v-btn>
|
||||
<div class="order-mobile-filled">{{ ord.filledDisplay || ord.filled }}</div>
|
||||
@ -297,7 +297,7 @@
|
||||
<td>{{ ord.total }}</td>
|
||||
<td>{{ ord.expiration }}</td>
|
||||
<td class="text-right">
|
||||
<v-btn variant="text" size="small" color="error" @click="cancelOrder(ord.id)">Cancel</v-btn>
|
||||
<v-btn variant="text" size="small" color="error" :disabled="cancelOrderLoading" @click="cancelOrder(ord)">Cancel</v-btn>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@ -442,6 +442,10 @@
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<v-snackbar v-model="showCancelError" color="error" :timeout="4000">
|
||||
{{ cancelOrderError }}
|
||||
</v-snackbar>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
@ -453,6 +457,7 @@ import type { ECharts } from 'echarts'
|
||||
import DepositDialog from '../components/DepositDialog.vue'
|
||||
import WithdrawDialog from '../components/WithdrawDialog.vue'
|
||||
import { useUserStore } from '../stores/user'
|
||||
import { pmCancelOrder } from '../api/market'
|
||||
|
||||
const { mobile } = useDisplay()
|
||||
const userStore = useUserStore()
|
||||
@ -521,6 +526,9 @@ interface OpenOrder {
|
||||
filledDisplay?: string
|
||||
iconChar?: string
|
||||
iconClass?: string
|
||||
/** 取消订单 API 用 */
|
||||
orderID?: number
|
||||
tokenID?: string
|
||||
}
|
||||
interface HistoryItem {
|
||||
id: string
|
||||
@ -597,6 +605,7 @@ const positions = ref<Position[]>([
|
||||
outcomeWord: 'Yes',
|
||||
},
|
||||
])
|
||||
const MOCK_TOKEN_ID = '59966088656508531737144108943848781534186324373509174641856486864137458635937'
|
||||
const openOrders = ref<OpenOrder[]>([
|
||||
{
|
||||
id: 'o1',
|
||||
@ -611,9 +620,33 @@ const openOrders = ref<OpenOrder[]>([
|
||||
filledDisplay: '0/5',
|
||||
iconChar: '₿',
|
||||
iconClass: 'position-icon-btc',
|
||||
orderID: 5,
|
||||
tokenID: MOCK_TOKEN_ID,
|
||||
},
|
||||
{
|
||||
id: 'o2',
|
||||
market: 'Will Bitcoin hit $100k by end of 2025?',
|
||||
side: 'Yes',
|
||||
outcome: 'Yes',
|
||||
price: '70¢',
|
||||
filled: '0',
|
||||
total: '$70',
|
||||
expiration: 'Dec 31, 2025',
|
||||
orderID: 5,
|
||||
tokenID: MOCK_TOKEN_ID,
|
||||
},
|
||||
{
|
||||
id: 'o3',
|
||||
market: 'Will ETH merge complete by Q3?',
|
||||
side: 'No',
|
||||
outcome: 'No',
|
||||
price: '52¢',
|
||||
filled: '25',
|
||||
total: '$26',
|
||||
expiration: 'Sep 30, 2025',
|
||||
orderID: 5,
|
||||
tokenID: MOCK_TOKEN_ID,
|
||||
},
|
||||
{ id: 'o2', market: 'Will Bitcoin hit $100k by end of 2025?', side: 'Yes', outcome: 'Yes', price: '70¢', filled: '0', total: '$70', expiration: 'Dec 31, 2025' },
|
||||
{ id: 'o3', market: 'Will ETH merge complete by Q3?', side: 'No', outcome: 'No', price: '52¢', filled: '25', total: '$26', expiration: 'Sep 30, 2025' },
|
||||
])
|
||||
const history = ref<HistoryItem[]>([
|
||||
{
|
||||
@ -707,8 +740,42 @@ function onPageChange() {
|
||||
// 可选:翻页后滚动到表格顶部
|
||||
}
|
||||
|
||||
function cancelOrder(id: string) {
|
||||
openOrders.value = openOrders.value.filter((o) => o.id !== id)
|
||||
const cancelOrderLoading = ref(false)
|
||||
const cancelOrderError = ref('')
|
||||
const showCancelError = ref(false)
|
||||
async function cancelOrder(ord: OpenOrder) {
|
||||
const orderID = ord.orderID ?? 5
|
||||
const tokenID = ord.tokenID ?? MOCK_TOKEN_ID
|
||||
const uid = userStore.user?.id ?? userStore.user?.ID
|
||||
const userID = uid != null ? Number(uid) : 0
|
||||
if (!Number.isFinite(userID) || userID <= 0) {
|
||||
cancelOrderError.value = '请先登录'
|
||||
showCancelError.value = true
|
||||
return
|
||||
}
|
||||
const headers = userStore.getAuthHeaders()
|
||||
if (!headers) {
|
||||
cancelOrderError.value = '请先登录'
|
||||
showCancelError.value = true
|
||||
return
|
||||
}
|
||||
cancelOrderLoading.value = true
|
||||
cancelOrderError.value = ''
|
||||
try {
|
||||
const res = await pmCancelOrder({ orderID, tokenID, userID }, { headers })
|
||||
if (res.code === 0 || res.code === 200) {
|
||||
openOrders.value = openOrders.value.filter((o) => o.id !== ord.id)
|
||||
userStore.fetchUsdcBalance()
|
||||
} else {
|
||||
cancelOrderError.value = res.msg || '取消失败'
|
||||
showCancelError.value = true
|
||||
}
|
||||
} catch (e) {
|
||||
cancelOrderError.value = e instanceof Error ? e.message : 'Request failed'
|
||||
showCancelError.value = true
|
||||
} finally {
|
||||
cancelOrderLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function cancelAllOrders() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user