| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- <template>
- <app-view class="pricing-trade">
- <template #header>
- <app-navbar :title="quote ? `${quote.goodscode}` : $t('quote.pricing.title')" >
- <template #right>
- <Icon v-if="system_1012 != '0'" name="bars" size="20px" @click="openComponent('detail')" />
- </template>
- </app-navbar>
- </template>
- <div class="pricing-trade__form" v-if="quote">
- <div class="form-price">
- <dl>
- <dt>{{ t('quote.bid') }}</dt>
- <dd :class="quote.bidColor">{{ handleNumberValue(formatDecimal(quote.ask, quote.decimalplace)) }}
- </dd>
- </dl>
- <dl>
- <dt>{{ t('quote.ask') }}</dt>
- <dd :class="quote.askColor">{{ handleNumberValue(formatDecimal(quote.bid, quote.decimalplace)) }}
- </dd>
- </dl>
- </div>
- </div>
- <!-- 下单 -->
- <Form ref="formRef" class="g-form__container" @submit="onSubmit">
- <CellGroup inset>
- <Field :label="$t('quote.pricing.buyorsell')">
- <template #input>
- <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>
- </template>
- </Field>
- <Field :label="$t('quote.pricing.pricemode')">
- <template #input>
- <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="$t('quote.pricing.orderqty')">
- <template #input>
- <div class="g-qty-group">
- <div class="g-qty-group__stepper">
- <Stepper v-model="formData.OrderQty" theme="round" button-size="22" :min="0"
- :step="qtyStep" integer />
- </div>
- <RadioGroup v-model="qtyStep" direction="horizontal" @change="onRadioChange">
- <Radio v-for="(value, index) in qtyStepList" :key="index" :name="value">{{ value }}
- </Radio>
- </RadioGroup>
- </div>
- </template>
- </Field>
- <!-- 市价 -->
- <!-- <Field label="价格" v-if="formData.PriceMode === PriceMode.Market">
- <template #input>
- <span>{{ handleNumberValue(marketPrice) }}</span>
- </template>
- </Field> -->
- <!-- 允许成交范围 -->
- <!-- <Field name="MarketMaxSub" :rules="formRules.MarketMaxSub" :label="$t('quote.pricing.marketmaxsub')" v-if="formData.PriceMode === PriceMode.Market">
- <template #input>
- <Stepper v-model="formData.MarketMaxSub" :min="0" :max="999" theme="round" button-size="22" :auto-fixed="false" integer />
- </template>
- </Field> -->
- <!-- 限价 -->
- <Field name="OrderPrice" :rules="formRules.OrderPrice" :label="$t('quote.pricing.price')" v-if="formData.PriceMode === PriceMode.Limit">
- <template #input>
- <Stepper v-model="formData.OrderPrice" theme="round" button-size="22" :min="0"
- :auto-fixed="false" :decimal-length="decimalplace" :step="decimalvalue" />
- </template>
- </Field>
- <!-- <Field name="SlPrice" :rules="formRules.SlPrice"
- v-if="formData.PriceMode === PriceMode.Limit && formData.BuildType === BuildType.Open">
- <template #label>
- <Checkbox v-model="sl">止损</Checkbox>
- </template>
- <template #input>
- <Stepper v-model="formData.SlPrice" :disabled="!sl" theme="round" button-size="22" allow-empty
- :default-value="0" :min="0" :decimal-length="decimalplace" :step="decimalvalue" />
- </template>
- </Field>
- <Field name="SpPrice" :rules="formRules.SpPrice"
- v-if="formData.PriceMode === PriceMode.Limit && formData.BuildType === BuildType.Open">
- <template #label>
- <Checkbox v-model="sp">止盈</Checkbox>
- </template>
- <template #input>
- <Stepper v-model="formData.SpPrice" :disabled="!sp" theme="round" button-size="22" allow-empty
- :default-value="0" :min="0" :decimal-length="decimalplace" :step="decimalvalue" />
- </template>
- </Field> -->
- <!-- <template v-if="formData.BuyOrSell === BuyOrSell.Buy || quote?.tradeproperty !== 2">
- <Field :label="$t('quote.pricing.enableQty')">
- <template #input>
- <span>{{ total.enableQty }}</span>
- </template>
- </Field>
- <Field :label="$t('quote.pricing.deposit')">
- <template #input>
- <span>{{ total.deposit.toFixed(2) }}</span>
- </template>
- </Field>
- </template>
- <Field :label="$t('quote.pricing.avaiableMoney')">
- <template #input>
- <span>{{ accountStore.currentAccount.avaiableMoney?.toFixed(2) }}</span>
- </template>
- </Field> -->
- </CellGroup>
- </Form>
- <div class="g-form__footer">
- <template v-if="formData.BuyOrSell === BuyOrSell.Buy">
- <Button type="danger" block square :disabled="!formData.OrderQty"
- @click="onBeforeSubmit(BuildType.Open)" v-if="!quote?.iscannotbuy">{{ $t('operation.order') }}</Button>
- <!-- <Button color="#199e00" block square
- :disabled="!formData.OrderQty || !sellQty || (formData.OrderQty > sellQty)"
- @click="onBeforeSubmit(BuildType.Close)" v-if="!isTrademode16">
- <span>{{ $t('quote.transferbuy') }}</span>
- <span v-if="sellQty">(≤{{ sellQty }})</span>
- </Button> -->
- </template>
- <template v-if="formData.BuyOrSell === BuyOrSell.Sell">
- <Button type="danger" block square :disabled="!formData.OrderQty"
- @click="onBeforeSubmit(BuildType.Open)"
- v-if="!isTrademode16 && !quote?.iscannotsell">{{ $t('operation.order') }}</Button>
- <!-- <Button color="#199e00" block square
- :disabled="!formData.OrderQty || !buyQty || (formData.OrderQty > buyQty)"
- @click="onBeforeSubmit(BuildType.Close)">
- <span>{{ $t('quote.transfersell') }}</span>
- <span v-if="buyQty">(≤{{ buyQty }})</span>
- </Button> -->
- </template>
- </div>
- <Tabs class="van-tabs--list" v-model:active="active" >
- <template v-for="(item, index) in components.filter(e => e.show === true)" :key="index">
- <Tab :title="item.title" :name="item.name">
- <component :is="item.component" v-bind="{ goodsCode, goodsid, fromTrade, pictureurl }" @callBack="itemBack"/>
- </Tab>
- </template>
- </Tabs>
- <template #footer>
- <component ref="componentRef" :is="componentMap.get(componentId)" v-bind="{ goodsCode, goodsid, selectedRow }"
- @closed="closeComponent" v-if="componentId" />
- </template>
- </app-view>
- </template>
- <script lang="ts" setup>
- import { useFuturesStore, useUserStore, i18n } from '@/stores'
- import { useNavigation } from '@mobile/router/navigation'
- import { shallowRef, onMounted, computed, defineAsyncComponent } from 'vue'
- import { Form, Field, Button, FieldRule, FormInstance, Radio, RadioGroup, CellGroup, Icon, Tab, Tabs } from 'vant'
- import { useOrder } from '@/business/trade'
- import { BuyOrSell, getBuyOrSellList, BuildType, getPricemode2List, PriceMode } from '@/constants/order'
- import { useComponent } from '@/hooks/component'
- import { fullloading, dialog } from '@/utils/vant'
- import { formatDecimal, handleNumberValue } from '@/filters'
- // import service from '@/services'
- import Stepper from '@mobile/components/base/stepper/index.vue'
- import eventBus from '@/services/bus'
- const { getQueryString, getQueryStringToNumber } = useNavigation()
- const { global: { t } } = i18n
- const goodsCode = getQueryString('goodscode') ?? ''
- const goodsid = getQueryStringToNumber('goodsid')
- const buyOrSell = getQueryStringToNumber('buyOrSell')
- const buildType = getQueryStringToNumber('buildType')
- const orderQty = getQueryStringToNumber('orderQty')
- const futuresStore = useFuturesStore()
- const quote = futuresStore.getGoodsQuote(goodsCode)
- const { pictureurl } = futuresStore.getGoods(goodsCode) ?? {}
- // 小数位以及步进值
- const { decimalplace = 0.0 } = quote.value ?? {}
- const quoteminunit = quote.value?.quoteminunit ?? 1.0
- const decimalvalue = Math.pow(10.0, -decimalplace)*(quoteminunit == 0 ? 1 : quoteminunit)
- const isTrademode16 = computed(() => quote.value?.trademode === 16)
- const selectedRow = shallowRef<Model.SBYJMyOrderRsp>()
- const { getSystemParamValue } = useUserStore()
- const system_1012 = getSystemParamValue('1012') ?? '1'
- // const accountStore = useAccountStore()
- // const positionStore = usePositionStore()
- const { formData, formSubmit } = useOrder()
- const formRef = shallowRef<FormInstance>()
- // 数量步长列表
- const qtyStepList = computed(() => {
- const system_1009 = Number(getSystemParamValue('1009')) ?? 1
- return [1*system_1009, 5*system_1009, 10*system_1009, 20*system_1009, 30*system_1009, 50*system_1009]
- })
- const qtyStep = shallowRef(qtyStepList.value[0]) // 数量步长
- const fromTrade = true
- // 持仓汇总
- const position = shallowRef<Model.TradePositionRsp[]>([])
- // const oem = service.getConfig('oem')
- // 点击返回
- const itemBack = (isPosition: number, buyorsell: BuyOrSell, tradeId: string, item: Model.SBYJMyOrderRsp) => {
- formData.BuyOrSell = buyorsell === BuyOrSell.Buy ? BuyOrSell.Sell : BuyOrSell.Buy
- if (isPosition === 2) {
- // formData.RelatedID = handleRequestBigNumber(tradeId)
- selectedRow.value = item
- // 打开退订
- openComponent('transfer')
- }
- }
- const { componentRef, componentId, openComponent, closeComponent } = useComponent()
- const active = shallowRef(pictureurl != '' ? 'images' : 'cancel')
- const components = [
- {
- name: 'images',
- title: t('operation.details'),
- component: defineAsyncComponent(() => import('./images/Index.vue')),
- show: pictureurl != ''
- },
- {
- name: 'cancel',
- title: t('quote.pricing.ordercancel'),
- component: defineAsyncComponent(() => import('../trade/components/cancel/Index.vue')),
- show: true
- },
- {
- name: 'position',
- title: t('quote.pricing.position'),
- component: defineAsyncComponent(() => import('@mobile/views/order/position/components/pricing/list/Index.vue')),
- show: true
- },
- // {
- // name: 'holdlb',
- // title: t('quote.pricing.holdlb'),
- // component: defineAsyncComponent(() => import('../trade/holdlb/Index.vue')),
- // },
- {
- name: 'holdlb2',
- title: t('quote.pricing.orderdetails'),
- component: defineAsyncComponent(() => import('../trade/holdlb2/Index.vue')),
- detail: defineAsyncComponent(() => import('@mobile/views/order/position/components/pricing/detail2/Index.vue')),
- show: true
- }]
-
- const componentMap = new Map<string, unknown>([
- ['detail', defineAsyncComponent(() => import('./components/detail/Index.vue'))],
- ['transfer', defineAsyncComponent(() => import('@mobile/views/order/position/components/pricing/detail2/components/transfer/Index.vue'))],
- ])
- // // const sl = shallowRef(false) // 止损
- // // const sp = shallowRef(false) // 止盈
- // const total = computed(() => {
- // const { avaiableMoney = 0 } = accountStore.currentAccount
- // const { marketmarginalgorithm = 0, marketmarginvalue = 0, agreeunit = 0 } = quote.value ?? {}
- // const result = {
- // enableQty: 0,
- // deposit: 0
- // }
- // const fixed = agreeunit * marketmarginvalue
- // const ratio = fixed * (formData.OrderPrice ?? 0)
- // if (fixed && ratio) {
- // if (marketmarginalgorithm === 1) {
- // const qty = Math.trunc(avaiableMoney / ratio)
- // result.deposit = (formData.OrderQty ?? 0) * ratio
- // result.enableQty = qty > 0 ? qty : 0
- // }
- // if (marketmarginalgorithm === 2) {
- // const qty = Math.trunc(avaiableMoney / fixed)
- // result.deposit = (formData.OrderQty ?? 0) * fixed
- // result.enableQty = qty > 0 ? qty : 0
- // }
- // }
- // return result
- // })
- // 计算市价
- const marketPrice = computed(() => {
- const { ask = 0, bid = 0 } = quote.value ?? {}
- return formData.BuyOrSell === BuyOrSell.Buy ? ask : bid
- })
- // 买方向持仓数量
- // const buyQty = computed(() => positionStore.getOrderQty(BuyOrSell.Buy, goodsCode))
- // 卖方向持仓数量
- // const sellQty = computed(() => positionStore.getOrderQty(BuyOrSell.Sell, goodsCode))
- // 表单验证规则
- const formRules: { [key: string]: FieldRule[] } = {
- OrderQty: [{
- message: t('quote.pricing.tips1'),
- validator: () => {
- return !!formData.OrderQty
- }
- }],
- // 限价
- MarketMaxSub: [{
- message: t('quote.pricing.tips3'),
- validator: (val) => {
- if (formData.PriceMode === PriceMode.Market) {
- if (val < 0) {
- return t('quote.pricing.tips3')
- }
- return true
- }
- return !!formData.MarketMaxSub
- }
- }],
- // 限价
- OrderPrice: [{
- message: t('quote.pricing.tips2'),
- 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
- // // }
- // // }],
- }
- 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 onBeforeSubmit = (buildType: BuildType) => {
- formData.BuildType = buildType
- if (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
- }
- } else {
- formData.RelatedID = undefined
- }
- formRef.value?.submit()
- }
- // 委托下单
- 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({ message: t('common.submitsuccess'), confirmButtonText: t('operation.confirm') }).then(() => {
- // 成交通知
- eventBus.$emit('OrderDealedNtf')
- })
- }).catch((err) => {
- hideLoading(err, 'fail')
- })
- })
- }
- const onRadioChange = (value: number) => {
- formData.OrderQty = value
- }
- onMounted(() => {
- formData.BuyOrSell = BuyOrSell.Buy
- formData.BuildType = BuildType.Open
- formData.PriceMode = PriceMode.Market
- formData.MarketMaxSub = 100.0
- /// 默认价格和数量
- const { last = 0, presettle = 0 } = quote.value ?? {}
- formData.OrderPrice = last || presettle
- formData.OrderQty = qtyStep.value
- /// 如果是从头寸点进来的
- if ( buildType === BuildType.Close) {
- formData.OrderQty = orderQty
- formData.BuyOrSell = buyOrSell
- formData.BuildType = buildType
- }
- })
- </script>
- <style lang="less">
- @import './index.less';
- </style>
|