Files
riwa-ionic/src/views/trade/index.vue

149 lines
4.8 KiB
Vue

<script setup lang="ts">
import type { ChartingLibraryWidgetOptions } from "#/charting_library";
import type { SpotOrderBody } from "@/api/types";
import type { TradingViewInst } from "@/tradingview/index";
import { modalController } from "@ionic/vue";
import { useRouteQuery } from "@vueuse/router";
import { caretDownOutline, ellipsisHorizontal } from "ionicons/icons";
import MaterialSymbolsCandlestickChartOutline from "~icons/material-symbols/candlestick-chart-outline";
import { client, safeClient } from "@/api";
import { TradeTypeEnum } from "@/api/enum";
import { TradingViewChart } from "@/tradingview/index";
import OrdersPanel from "./components/orders-panel.vue";
import TradePairsModal from "./components/trade-pairs-modal.vue";
import TradeSwitch from "./components/trade-switch.vue";
import TradeWay from "./components/trade-way.vue";
import { confirmOrderSchema, TradeWayValueEnum } from "./config";
const mode = useRouteQuery<TradeTypeEnum>("mode", TradeTypeEnum.BUY);
const symbol = useRouteQuery<string>("symbol", "BTCUSD");
const tradingviewOptions: Partial<ChartingLibraryWidgetOptions> = {
disabled_features: [
"create_volume_indicator_by_default",
],
};
const tradingViewInst = useTemplateRef<TradingViewInst>("tradingViewInst");
const [form] = useResetRef<SpotOrderBody>({
orderType: TradeWayValueEnum.LIMIT,
quantity: "",
side: mode.value,
symbol: symbol.value,
memo: "",
price: "",
});
async function openTradePairs() {
const modal = await modalController.create({
component: TradePairsModal,
breakpoints: [0, 0.95],
initialBreakpoint: 0.95,
handle: true,
});
await modal.present();
const { data: result } = await modal.onWillDismiss<string>();
if (result) {
symbol.value = result;
}
}
function handleSubmit() {
confirmOrderSchema.validate(form.value).then(() => {
console.log("submit successfully");
}).catch((err) => {
console.log("submit failed:", err);
});
}
</script>
<template>
<ion-page>
<ion-header>
<ion-toolbar class="ion-toolbar">
<div slot="start" class="flex items-center gap-1 px-4" @click="openTradePairs">
<div class="text-md font-bold">
{{ symbol }}
</div>
<ui-tag size="mini" type="tertiary">
现货
</ui-tag>
<ion-icon :icon="caretDownOutline" />
</div>
<ion-buttons slot="end">
<ion-button>
<MaterialSymbolsCandlestickChartOutline class="text-xl" />
</ion-button>
<ion-button>
<ion-icon :icon="ellipsisHorizontal" />
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true">
<TradingViewChart ref="tradingViewInst" class="mb-5" height="300px" :symbol="symbol" :options="tradingviewOptions" />
<div class="grid grid-cols-5 px-4">
<div class="col-span-3 space-y-2">
<TradeSwitch v-model:active="mode" @update:active="val => form.side = val" />
<TradeWay v-model="form" />
<template v-if="form.orderType === 'limit'">
<ion-input v-model="form.price" label="价格" class="count" inputmode="decimal" type="number" placeholder="请输入价格(USDT)" />
</template>
<ion-input v-model="form.quantity" label="数量" class="count" inputmode="decimal" type="number" placeholder="请输入交易数量">
<span slot="end">{{ symbol }}</span>
</ion-input>
<ion-input v-model="form.price" label="金额" class="count" inputmode="decimal" type="number" placeholder="请输入交易金额">
<span slot="end">USDT</span>
</ion-input>
<!-- <ion-range class="range" aria-label="Range with ticks" :pin="true" :ticks="true" :snaps="true" :min="0" :max="5" /> -->
<ion-button expand="block" size="small" shape="round" :color="mode === TradeTypeEnum.BUY ? 'success' : 'danger'" @click="handleSubmit">
{{ mode === TradeTypeEnum.BUY ? '买入' : '卖出' }}
</ion-button>
</div>
<div class="col-span-2" />
</div>
<div class="mt-6 px-4 pb-4">
<OrdersPanel />
</div>
</ion-content>
</ion-page>
</template>
<style lang="css" scoped>
@reference "tailwindcss";
ion-input.count {
--background: var(--ion-color-faint);
--padding-start: 16px;
--padding-end: 16px;
--padding-top: 4px;
--padding-bottom: 4px;
--border-radius: 6px;
font-size: 12px;
min-height: 40px;
}
ion-range.range {
--bar-height: 3px;
--knob-size: 14px;
--pin-color: #fff;
--bar-background-active: #3e3e3e;
--bar-background: rgb(226, 226, 226);
padding: 0 8px;
}
ion-range.range::part(tick) {
z-index: 1;
border-radius: 100%;
background: #dcdcdc;
}
ion-range.range::part(tick),
ion-range.range::part(tick-active) {
height: 6px;
width: 6px;
top: 18px;
border-radius: 100%;
}
</style>