新增:取消订单

This commit is contained in:
ivan 2026-02-11 21:51:12 +08:00
parent b73a910b43
commit 8d103e2d98
2 changed files with 93 additions and 6 deletions

View File

@ -37,6 +37,26 @@ export async function pmOrderPlace(
return post<ApiResponse>('/clob/gateway/submitOrder', data, config) 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 * Split /PmMarket/split
* USDC Yes+No 1 USDC 1 Yes + 1 No * USDC Yes+No 1 USDC 1 Yes + 1 No

View File

@ -260,7 +260,7 @@
<div class="order-mobile-price">{{ ord.price }} {{ ord.total }}</div> <div class="order-mobile-price">{{ ord.price }} {{ ord.total }}</div>
</div> </div>
<div class="order-mobile-right"> <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-icon size="20">mdi-close</v-icon>
</v-btn> </v-btn>
<div class="order-mobile-filled">{{ ord.filledDisplay || ord.filled }}</div> <div class="order-mobile-filled">{{ ord.filledDisplay || ord.filled }}</div>
@ -297,7 +297,7 @@
<td>{{ ord.total }}</td> <td>{{ ord.total }}</td>
<td>{{ ord.expiration }}</td> <td>{{ ord.expiration }}</td>
<td class="text-right"> <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> </td>
</tr> </tr>
</tbody> </tbody>
@ -442,6 +442,10 @@
</v-card-actions> </v-card-actions>
</v-card> </v-card>
</v-dialog> </v-dialog>
<v-snackbar v-model="showCancelError" color="error" :timeout="4000">
{{ cancelOrderError }}
</v-snackbar>
</v-container> </v-container>
</template> </template>
@ -453,6 +457,7 @@ import type { ECharts } from 'echarts'
import DepositDialog from '../components/DepositDialog.vue' import DepositDialog from '../components/DepositDialog.vue'
import WithdrawDialog from '../components/WithdrawDialog.vue' import WithdrawDialog from '../components/WithdrawDialog.vue'
import { useUserStore } from '../stores/user' import { useUserStore } from '../stores/user'
import { pmCancelOrder } from '../api/market'
const { mobile } = useDisplay() const { mobile } = useDisplay()
const userStore = useUserStore() const userStore = useUserStore()
@ -521,6 +526,9 @@ interface OpenOrder {
filledDisplay?: string filledDisplay?: string
iconChar?: string iconChar?: string
iconClass?: string iconClass?: string
/** 取消订单 API 用 */
orderID?: number
tokenID?: string
} }
interface HistoryItem { interface HistoryItem {
id: string id: string
@ -597,6 +605,7 @@ const positions = ref<Position[]>([
outcomeWord: 'Yes', outcomeWord: 'Yes',
}, },
]) ])
const MOCK_TOKEN_ID = '59966088656508531737144108943848781534186324373509174641856486864137458635937'
const openOrders = ref<OpenOrder[]>([ const openOrders = ref<OpenOrder[]>([
{ {
id: 'o1', id: 'o1',
@ -611,9 +620,33 @@ const openOrders = ref<OpenOrder[]>([
filledDisplay: '0/5', filledDisplay: '0/5',
iconChar: '₿', iconChar: '₿',
iconClass: 'position-icon-btc', 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[]>([ const history = ref<HistoryItem[]>([
{ {
@ -707,8 +740,42 @@ function onPageChange() {
// //
} }
function cancelOrder(id: string) { const cancelOrderLoading = ref(false)
openOrders.value = openOrders.value.filter((o) => o.id !== id) 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() { function cancelAllOrders() {