|
|
@@ -1,5 +1,5 @@
|
|
|
<template>
|
|
|
- <app-view>
|
|
|
+ <app-view class="pricing-detail">
|
|
|
<template #header>
|
|
|
<app-navbar title="点价详情" />
|
|
|
</template>
|
|
|
@@ -16,12 +16,12 @@
|
|
|
<tr>
|
|
|
<td style="width: calc(`100% / 3`);">
|
|
|
<span>幅度</span>
|
|
|
- <span :class="quote.lastColor" style="margin-left: .2rem;">{{ handleNumberValue(quote.amplitude)
|
|
|
+ <span :class="quote.lastColor" style="margin-left: .2rem;">{{ parsePercent(quote.amplitude)
|
|
|
}}</span>
|
|
|
</td>
|
|
|
<td style="width: calc(`100% / 3`);">
|
|
|
<span>涨跌</span>
|
|
|
- <span :class="quote.lastColor" style="margin-left: .2rem;">{{ handleNumberValue(quote.change)
|
|
|
+ <span :class="quote.lastColor" style="margin-left: .2rem;">{{ parsePercent(quote.change)
|
|
|
}}</span>
|
|
|
</td>
|
|
|
<td style="width: calc(`100% / 3`);" rowspan="3">
|
|
|
@@ -63,10 +63,10 @@
|
|
|
</table>
|
|
|
</div>
|
|
|
<!-- 下单 -->
|
|
|
- <Form ref="formRef" style="padding: 0.2rem; background-color: white;" @submit="onSubmit">
|
|
|
+ <Form class="pricing-detail__form" ref="formRef" style="padding: 0.2rem; background-color: white;" @submit="onSubmit">
|
|
|
<Field label="方向">
|
|
|
<template #input>
|
|
|
- <RadioGroup v-model="formData.BuyOrSell" direction="horizontal">
|
|
|
+ <RadioGroup v-model="formData.BuyOrSell" direction="horizontal" @click="onBuyOrSellChanged">
|
|
|
<Radio v-for="(item, index) in getBuyOrSellList()" :key="index" :name="item.value">{{ item.label
|
|
|
}}</Radio>
|
|
|
</RadioGroup>
|
|
|
@@ -74,7 +74,7 @@
|
|
|
</Field>
|
|
|
<Field label="类型">
|
|
|
<template #input>
|
|
|
- <RadioGroup v-model="formData.BuildType" direction="horizontal">
|
|
|
+ <RadioGroup v-model="formData.BuildType" direction="horizontal" @click="onBuildTypeChanged">
|
|
|
<Radio :name="BuildType.Open">{{ getBuildTypeName(BuildType.Open) }}</Radio>
|
|
|
<Radio :name="BuildType.Close">{{ getBuildTypeName(BuildType.Close) }}</Radio>
|
|
|
</RadioGroup>
|
|
|
@@ -82,16 +82,16 @@
|
|
|
</Field>
|
|
|
<Field label="价格方式">
|
|
|
<template #input>
|
|
|
- <RadioGroup v-model="formData.PriceMode" direction="horizontal">
|
|
|
+ <RadioGroup v-model="formData.PriceMode" direction="horizontal" @click="onPriceModeChanged">
|
|
|
<Radio v-for="(item, index) in getPricemode2List()" :key="index" :name="item.value">{{
|
|
|
item.label
|
|
|
}}</Radio>
|
|
|
</RadioGroup>
|
|
|
</template>
|
|
|
</Field>
|
|
|
- <Field name="OrderQty" label="挂牌数量">
|
|
|
+ <Field name="OrderQty" label="数量">
|
|
|
<template #input>
|
|
|
- <Stepper v-model="formData.OrderQty" theme="round" button-size="22" :auto-fixed="false" integer />
|
|
|
+ <Stepper v-model="formData.OrderQty" :rules="formRules.OrderQty" theme="round" button-size="22" :auto-fixed="false" integer />
|
|
|
</template>
|
|
|
</Field>
|
|
|
<!-- 市价 -->
|
|
|
@@ -106,7 +106,27 @@
|
|
|
</template>
|
|
|
</Field>
|
|
|
<!-- 限价 -->
|
|
|
-
|
|
|
+ <Field name="OrderPrice" :rules="formRules.OrderPrice" label="价格" v-if="formData.PriceMode === PriceMode.Limit">
|
|
|
+ <template #input>
|
|
|
+ <Stepper v-model="formData.OrderPrice" theme="round" button-size="22" :auto-fixed="false" />
|
|
|
+ </template>
|
|
|
+ </Field>
|
|
|
+ <Field name="SlPrice" :rules="formRules.SlPrice" v-if="formData.PriceMode === PriceMode.Limit && formData.BuildType === BuildType.Open">
|
|
|
+ <template #label>
|
|
|
+ <Checkbox v-model="sl" shape="square">止损</Checkbox>
|
|
|
+ </template>
|
|
|
+ <template #input>
|
|
|
+ <Stepper v-model="formData.SlPrice" :disabled="!sl" theme="round" button-size="22" allow-empty :default-value="0" :min="0" integer />
|
|
|
+ </template>
|
|
|
+ </Field>
|
|
|
+ <Field name="SpPrice" :rules="formRules.SpPrice" v-if="formData.PriceMode === PriceMode.Limit && formData.BuildType === BuildType.Open">
|
|
|
+ <template #label>
|
|
|
+ <Checkbox v-model="sp" shape="square">止盈</Checkbox>
|
|
|
+ </template>
|
|
|
+ <template #input>
|
|
|
+ <Stepper v-model="formData.SpPrice" :disabled="!sp" theme="round" button-size="22" allow-empty :default-value="0" :min="0" integer />
|
|
|
+ </template>
|
|
|
+ </Field>
|
|
|
</Form>
|
|
|
</div>
|
|
|
<template #footer>
|
|
|
@@ -118,28 +138,72 @@
|
|
|
<script lang="ts" setup>
|
|
|
import { useFuturesStore } from '@/stores'
|
|
|
import { useNavigation } from '@/hooks/navigation'
|
|
|
-import { handleNumberValue } from '@/filters'
|
|
|
+import { parsePercent, handleNumberValue } from '@/filters'
|
|
|
import quoteSocket from '@/services/websocket/quote'
|
|
|
import { shallowRef, onMounted, onUnmounted, computed } from 'vue'
|
|
|
-import { Form, Field, Stepper, Button, FieldRule, FormInstance, Radio, RadioGroup } from 'vant'
|
|
|
+import { Form, Field, Stepper, Button, FieldRule, FormInstance, Radio, RadioGroup, Checkbox } from 'vant'
|
|
|
import { useOrder } from '@/business/trade'
|
|
|
import { BuyOrSell, getBuyOrSellList, BuildType, getBuildTypeName, getPricemode2List, PriceMode } from '@/constants/order'
|
|
|
import { fullloading, dialog } from '@/utils/vant'
|
|
|
+import { useRequest } from '@/hooks/request'
|
|
|
+import { queryTradePosition } from '@/services/api/order'
|
|
|
|
|
|
+const { router } = useNavigation()
|
|
|
const futuresStore = useFuturesStore()
|
|
|
const { getQueryString, getQueryStringToNumber } = useNavigation()
|
|
|
-
|
|
|
-const goodscode = getQueryString('goodscode')
|
|
|
-const buyOrSell = getQueryStringToNumber('buyOrSell')
|
|
|
-const buildType = getQueryStringToNumber('buildType')
|
|
|
-const quote = futuresStore.getQuoteInfo(goodscode)
|
|
|
-const subscribe = quoteSocket.addSubscribe([goodscode])
|
|
|
const formRef = shallowRef<FormInstance>()
|
|
|
const { formData, formSubmit } = useOrder()
|
|
|
+
|
|
|
const marketPrice = computed(() => {
|
|
|
const { ask = 0, bid = 0 } = quote.value ?? {}
|
|
|
return formData.BuyOrSell === BuyOrSell.Buy ? ask : bid
|
|
|
})
|
|
|
+const goodscode = getQueryString('goodscode')
|
|
|
+const buyOrSell = getQueryStringToNumber('buyOrSell')
|
|
|
+const buildType = getQueryStringToNumber('buildType')
|
|
|
+const quote = futuresStore.getQuoteInfo(goodscode)
|
|
|
+const subscribe = quoteSocket.addSubscribe([goodscode])
|
|
|
+const sl = shallowRef(false) // 止损
|
|
|
+const sp = shallowRef(false) // 止盈
|
|
|
+const position = shallowRef<Model.TradePositionRsp[]>([]) // 持仓汇总
|
|
|
+
|
|
|
+// 表单验证规则
|
|
|
+const formRules: { [key in keyof Proto.OrderReq]?: FieldRule[] } = {
|
|
|
+ OrderQty: [{
|
|
|
+ message: '请输入数量',
|
|
|
+ validator: () => {
|
|
|
+ return !!formData.OrderQty
|
|
|
+ }
|
|
|
+ }],
|
|
|
+ // 限价
|
|
|
+ OrderPrice: [{
|
|
|
+ message: '请输入价格',
|
|
|
+ validator: () => {
|
|
|
+ if (formData.PriceMode === PriceMode.Limit) {
|
|
|
+ return !!formData.OrderPrice
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }],
|
|
|
+ SlPrice :[{
|
|
|
+ message: '请输入止损价',
|
|
|
+ validator: () => {
|
|
|
+ if (sl.value) {
|
|
|
+ return !!formData.SlPrice
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }],
|
|
|
+ SpPrice :[{
|
|
|
+ message: '请输入止盈价',
|
|
|
+ validator: () => {
|
|
|
+ if (sp.value) {
|
|
|
+ return !!formData.SpPrice
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }],
|
|
|
+}
|
|
|
|
|
|
onMounted(() => {
|
|
|
subscribe.start()
|
|
|
@@ -154,20 +218,70 @@ onUnmounted(() => {
|
|
|
subscribe.stop()
|
|
|
})
|
|
|
|
|
|
+// 获取当前商品持仓汇总
|
|
|
+useRequest(queryTradePosition, {
|
|
|
+ params: {
|
|
|
+ tradeMode: '10'
|
|
|
+ },
|
|
|
+ onSuccess: (res) => {
|
|
|
+ position.value = res.data.filter(item => item.goodscode === goodscode)
|
|
|
+ const datas = position.value.filter( item => formData.BuyOrSell === BuyOrSell.Buy ? item.buyorsell === BuyOrSell.Sell : item.buyorsell === BuyOrSell.Buy ) // 反方向持仓
|
|
|
+ if (datas.length > 0) {
|
|
|
+ formData.OrderQty = datas[0].enableqty
|
|
|
+ }
|
|
|
+ },
|
|
|
+})
|
|
|
+
|
|
|
+const onBuyOrSellChanged = () => {
|
|
|
+ if (formData.PriceMode === PriceMode.Limit) {
|
|
|
+ const { ask = 0, bid = 0 } = quote.value ?? {}
|
|
|
+ formData.OrderPrice = formData.BuyOrSell === BuyOrSell.Buy ? ask : bid
|
|
|
+ }
|
|
|
+}
|
|
|
+const onPriceModeChanged = () => {
|
|
|
+ if (formData.PriceMode === PriceMode.Limit) {
|
|
|
+ const { ask = 0, bid = 0 } = quote.value ?? {}
|
|
|
+ formData.OrderPrice = formData.BuyOrSell === BuyOrSell.Buy ? ask : bid
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const onBuildTypeChanged = () => {
|
|
|
+ if (formData.BuildType === BuildType.Close) {
|
|
|
+ const { ask = 0, bid = 0 } = quote.value ?? {}
|
|
|
+ formData.OrderPrice = formData.BuyOrSell === BuyOrSell.Buy ? ask : bid
|
|
|
+
|
|
|
+ const datas = position.value.filter( item => formData.BuyOrSell === BuyOrSell.Buy ? item.buyorsell === BuyOrSell.Sell : item.buyorsell === BuyOrSell.Buy ) // 反方向持仓
|
|
|
+ if (datas.length > 0) {
|
|
|
+ formData.OrderQty = datas[0].enableqty
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// 委托下单
|
|
|
const onSubmit = () => {
|
|
|
const { goodsid, marketid } = quote.value ?? {}
|
|
|
formData.GoodsID = goodsid
|
|
|
formData.MarketID = marketid
|
|
|
+ // 市价
|
|
|
+ if (formData.PriceMode === PriceMode.Market) { formData.OrderPrice = marketPrice.value }
|
|
|
+ // 限价
|
|
|
+ if (!sl.value) { formData.SlPrice = undefined }
|
|
|
+ if (!sp.value) { formData.SpPrice = undefined }
|
|
|
|
|
|
fullloading((hideLoading) => {
|
|
|
formSubmit().then(() => {
|
|
|
hideLoading()
|
|
|
- dialog('委托成功。')
|
|
|
+ dialog('委托成功。').then(() => {
|
|
|
+ router.back()
|
|
|
+ })
|
|
|
}).catch((err) => {
|
|
|
hideLoading(err, 'fail')
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-</script>
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="less">
|
|
|
+@import './index.less';
|
|
|
+</style>
|