feat: 更新订单面板样式,优化订单列表和空状态展示;添加用户界面菜单按钮
This commit is contained in:
@@ -189,5 +189,5 @@ html.ion-palette-dark {
|
|||||||
--ui-input-background: #1e1e1e;
|
--ui-input-background: #1e1e1e;
|
||||||
--ui-input-color: #ffffff;
|
--ui-input-color: #ffffff;
|
||||||
|
|
||||||
--ion-color-faint: #626262;
|
--ion-color-faint: #1b1b1b;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ const qrcode = useQRCode(url, {
|
|||||||
@apply flex flex-col items-center gap-2 text-[text-500] font-medium;
|
@apply flex flex-col items-center gap-2 text-[text-500] font-medium;
|
||||||
}
|
}
|
||||||
.icon {
|
.icon {
|
||||||
@apply p-2.5 bg-(--ion-text-color-step-700) rounded-full;
|
@apply p-2.5 bg-(--ion-color-faint) rounded-full;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text {
|
.text {
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ async function cancelOrder(orderId: string) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="orders-panel">
|
<div class="flex flex-col h-full bg-(--ion-background-color)">
|
||||||
<!-- Tab切换 -->
|
<!-- Tab切换 -->
|
||||||
<ui-tabs v-model="activeTab" size="small">
|
<ui-tabs v-model="activeTab" size="small">
|
||||||
<ui-tab-pane
|
<ui-tab-pane
|
||||||
@@ -132,194 +132,67 @@ async function cancelOrder(orderId: string) {
|
|||||||
</ui-tabs>
|
</ui-tabs>
|
||||||
|
|
||||||
<!-- 订单列表 -->
|
<!-- 订单列表 -->
|
||||||
<div class="orders-list">
|
<div class="flex-1 overflow-y-auto">
|
||||||
<div v-if="displayOrders.length === 0" class="empty-state">
|
<div v-if="displayOrders.length === 0" class="flex items-center justify-center py-10 px-5">
|
||||||
<div class="text-text-500 text-sm">
|
<div class="text-(--ion-text-color-step-500) text-sm">
|
||||||
{{ activeTab === 'current' ? '暂无当前委托' : '暂无历史记录' }}
|
{{ activeTab === 'current' ? '暂无当前委托' : '暂无历史记录' }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else class="orders-content">
|
<div v-else class="space-y-3">
|
||||||
<div
|
<div
|
||||||
v-for="order in displayOrders"
|
v-for="order in displayOrders"
|
||||||
:key="order.id"
|
:key="order.id"
|
||||||
class="order-item"
|
class="bg-faint rounded-xl p-3"
|
||||||
>
|
>
|
||||||
<div class="order-header">
|
<div class="flex justify-between items-center mb-3">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span
|
<span
|
||||||
class="side-badge"
|
class="px-2 py-0.5 rounded text-[11px] font-semibold"
|
||||||
:class="order.side === 'buy' ? 'buy' : 'sell'"
|
:class="order.side === 'buy'
|
||||||
|
? 'bg-success/10 text-(--ion-color-success)'
|
||||||
|
: 'bg-danger/10 text-(--ion-color-danger)'"
|
||||||
>
|
>
|
||||||
{{ order.side === 'buy' ? '买入' : '卖出' }}
|
{{ order.side === 'buy' ? '买入' : '卖出' }}
|
||||||
</span>
|
</span>
|
||||||
<span class="text-sm font-medium">{{ order.symbol }}</span>
|
<span class="text-sm font-medium">{{ order.symbol }}</span>
|
||||||
<ion-badge :color="getStatusColor(order.status)" class="status-badge">
|
<ion-badge :color="getStatusColor(order.status)" class="text-[10px] px-1.5 py-0.5">
|
||||||
{{ getStatusText(order.status) }}
|
{{ getStatusText(order.status) }}
|
||||||
</ion-badge>
|
</ion-badge>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
v-if="activeTab === 'current' && order.status !== 'filled'"
|
v-if="activeTab === 'current' && order.status !== 'filled'"
|
||||||
class="cancel-btn"
|
class="px-3 py-1 bg-transparent border border-(--ion-color-danger) text-(--ion-color-danger) rounded-md text-xs transition-all active:bg-(--ion-color-danger) active:text-white"
|
||||||
@click="cancelOrder(order.id)"
|
@click="cancelOrder(order.id)"
|
||||||
>
|
>
|
||||||
撤单
|
撤单
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="order-details">
|
<div class="grid grid-cols-2 gap-2 mb-2">
|
||||||
<div class="detail-row">
|
<div class="flex justify-between text-xs">
|
||||||
<span class="label">{{ order.type === 'limit' ? '价格' : '市价' }}</span>
|
<span class="text-(--ion-text-color-step-400)">{{ order.type === 'limit' ? '价格' : '市价' }}</span>
|
||||||
<span class="value">{{ order.type === 'limit' ? order.price : '-' }}</span>
|
<span class="text-(--ion-text-color) font-medium">{{ order.type === 'limit' ? order.price : '-' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-row">
|
<div class="flex justify-between text-xs">
|
||||||
<span class="label">数量</span>
|
<span class="text-(--ion-text-color-step-400)">数量</span>
|
||||||
<span class="value">{{ order.amount }}</span>
|
<span class="text-(--ion-text-color) font-medium">{{ order.amount }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-row">
|
<div class="flex justify-between text-xs">
|
||||||
<span class="label">成交</span>
|
<span class="text-(--ion-text-color-step-400)">成交</span>
|
||||||
<span class="value">{{ order.filled }}</span>
|
<span class="text-(--ion-text-color) font-medium">{{ order.filled }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-row">
|
<div class="flex justify-between text-xs">
|
||||||
<span class="label">总额</span>
|
<span class="text-(--ion-text-color-step-400)">总额</span>
|
||||||
<span class="value">{{ order.total }} USDT</span>
|
<span class="text-(--ion-text-color) font-medium">{{ order.total }} USDT</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="order-footer">
|
<div class="pt-2">
|
||||||
<span class="time">{{ order.time }}</span>
|
<span class="text-[11px] text-(--ion-text-color-step-500)">{{ order.time }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.orders-panel {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
background: var(--ion-background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-header {
|
|
||||||
display: flex;
|
|
||||||
border-bottom: 1px solid var(--ion-border-color);
|
|
||||||
background: var(--ion-background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-header button {
|
|
||||||
flex: 1;
|
|
||||||
padding: 12px 0;
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
color: var(--ion-text-color-step-400);
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
border-bottom: 2px solid transparent;
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-header button.active {
|
|
||||||
color: var(--ion-color-primary);
|
|
||||||
border-bottom-color: var(--ion-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.orders-list {
|
|
||||||
flex: 1;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-state {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 40px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-item {
|
|
||||||
background: var(--ion-color-light);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 12px;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.side-badge {
|
|
||||||
padding: 2px 8px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.side-badge.buy {
|
|
||||||
background: rgba(34, 197, 94, 0.1);
|
|
||||||
color: var(--ion-color-success);
|
|
||||||
}
|
|
||||||
|
|
||||||
.side-badge.sell {
|
|
||||||
background: rgba(239, 68, 68, 0.1);
|
|
||||||
color: var(--ion-color-danger);
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-badge {
|
|
||||||
font-size: 10px;
|
|
||||||
padding: 2px 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cancel-btn {
|
|
||||||
padding: 4px 12px;
|
|
||||||
background: transparent;
|
|
||||||
border: 1px solid var(--ion-color-danger);
|
|
||||||
color: var(--ion-color-danger);
|
|
||||||
border-radius: 6px;
|
|
||||||
font-size: 12px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cancel-btn:active {
|
|
||||||
background: var(--ion-color-danger);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-details {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
gap: 8px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.detail-row {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.detail-row .label {
|
|
||||||
color: var(--ion-text-color-step-400);
|
|
||||||
}
|
|
||||||
|
|
||||||
.detail-row .value {
|
|
||||||
color: var(--ion-text-color);
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-footer {
|
|
||||||
padding-top: 8px;
|
|
||||||
border-top: 1px solid var(--ion-border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-footer .time {
|
|
||||||
font-size: 11px;
|
|
||||||
color: var(--ion-text-color-step-500);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { RefresherCustomEvent } from "@ionic/vue";
|
import type { RefresherCustomEvent } from "@ionic/vue";
|
||||||
import { notificationsOutline, scanOutline, settingsOutline } from "ionicons/icons";
|
import { notificationsOutline, scanOutline, settingsOutline } from "ionicons/icons";
|
||||||
|
import IconParkOutlineApplicationMenu from "~icons/icon-park-outline/application-menu";
|
||||||
import IconParkOutlineScanCode from "~icons/icon-park-outline/scan-code";
|
import IconParkOutlineScanCode from "~icons/icon-park-outline/scan-code";
|
||||||
import IconParkOutlineSettingOne from "~icons/icon-park-outline/setting-one";
|
import IconParkOutlineSettingOne from "~icons/icon-park-outline/setting-one";
|
||||||
import MaterialSymbolsNotificationsOutline from "~icons/material-symbols/notifications-outline";
|
import MaterialSymbolsNotificationsOutline from "~icons/material-symbols/notifications-outline";
|
||||||
@@ -42,6 +43,9 @@ async function handleScan() {
|
|||||||
<ion-page>
|
<ion-page>
|
||||||
<ion-header class="ion-no-border">
|
<ion-header class="ion-no-border">
|
||||||
<ion-toolbar class="ui-toolbar">
|
<ion-toolbar class="ui-toolbar">
|
||||||
|
<ion-button slot="start" fill="clear" class="z-1" @click="$router.push('/global-menu')">
|
||||||
|
<IconParkOutlineApplicationMenu slot="icon-only" />
|
||||||
|
</ion-button>
|
||||||
<div slot="end">
|
<div slot="end">
|
||||||
<ion-button fill="clear" @click="handleScan">
|
<ion-button fill="clear" @click="handleScan">
|
||||||
<IconParkOutlineScanCode slot="icon-only" />
|
<IconParkOutlineScanCode slot="icon-only" />
|
||||||
|
|||||||
Reference in New Issue
Block a user