Handy_Cao 2 月之前
父節點
當前提交
c6798c37c6

+ 1 - 1
oem/digital/config/appconfig.json

@@ -3,7 +3,7 @@
   "appName": "Digital",
   "version": "1.0.0",
   "versionCode": "100000",
-  "apiUrl": "http://192.168.31.210:8080/cfg?key=test_210",
+  "apiUrl": "http://192.168.31.204:8080/cfg?key=test_204",
   "tradeChannel": "ws",
   "modules": [
     "register"

+ 1 - 1
public/config/appconfig.json

@@ -4,7 +4,7 @@
   "appTitle": "多元世纪交易中心",
   "version": "1.0.8",
   "versionCode": "10008",
-  "apiUrl": "http://192.168.31.210:8080/cfg?key=test_210",
+  "apiUrl": "http://192.168.31.204:8080/cfg?key=test_204",
   "tradeChannel": "ws",
   "modules": [
     "register",

+ 153 - 7
src/packages/digital/views/contract/components/position/close/index.vue

@@ -1,33 +1,179 @@
+<!-- 合约 - 持仓 - 平仓 -->
 <template>
     <app-modal direction="right-top" height="100%" width="100%" v-model:show="showModal" :refresh="refresh">
         <app-view class="g-form">
             <template #header>
-                <app-navbar title="平仓" />
+                <app-navbar title="平仓" @back="closed" />
+            </template>
+            <Form ref="formRef" class="g-form__container" @submit="onCloseSumit">
+                <CellGroup title="持仓信息" inset>
+                    <Cell title="代码/名称"
+                        :value="`${selectedRow.goodsCode}/${selectedRow.goodsName}`" />
+                    <Cell title="持仓方向" :value="getBuyOrSellName(selectedRow.tHDetailEx.buyOrSell)" />
+                    <Cell title="持仓价格(USDT)" :value="formatDecimal(selectedRow.tHDetailEx.holderPrice, selectedRow.decimalPlace)" />
+                    <Cell title="持仓量" :value="selectedRow.tHDetailEx.holderQty" />
+                    <Cell title="冻结量" :value="selectedRow.tHDetailEx.freezeQty" />
+                    <Cell title="浮动盈亏">
+                        <template #value>
+                            <span :class="handlePriceColor(closepl)">
+                                {{ formatDecimal(closepl, selectedRow.decimalplace) }}
+                            </span>
+                        </template>
+                    </Cell>
+                    <Field name="OrderPrice" :rules="formRules.OrderPrice" label="价格">
+                        <template #input>
+                            <app-stepper v-model="formData.OrderPrice" min="0.0" :decimal-length="quote?.decimalplace"
+                            :step="quote?.decimalvalue" :auto-fixed="false" />
+                        </template>
+                    </Field>
+                    <Field label="限单价" is-link>
+                        <template #input>
+                            <app-select v-model="formData.PriceMode" :options="options" />
+                        </template>
+                    </Field>
+                    <Field name="OrderQty" :rules="formRules.OrderQty" label="数量">
+                        <template #input>
+                            <app-stepper v-model="formData.OrderQty" min="0.0" :max="maxQty" :auto-fixed="false" integer />
+                        </template>
+                    </Field>
+                </CellGroup>
+            </Form>
+            <template #footer>
+                <Button block square type="danger" @click="formRef?.submit">平仓</Button>
             </template>
         </app-view>
     </app-modal>
 </template>
 
 <script lang="ts" setup>
-import { shallowRef } from 'vue'
+import { shallowRef, PropType, onMounted, computed } from 'vue'
 import AppModal from '@/components/base/modal/index.vue'
+import { CellGroup, Cell, Button, FieldRule, Form, Field, FormInstance } from 'vant'
+import { getBuyOrSellName, BuyOrSell } from '@/constants/order'
+import { formatDecimal, handleRequestBigNumber, handlePriceColor } from '@/filters'
+import { useOrder } from '@/business/trade'
+import { dialog, fullloading } from '@/utils/vant'
+import { useFuturesStore, usePositionStore, i18n } from '@/stores'
+import { EBuildType, EDelistingType, EListingSelectType, EPriceMode, EValidType } from '@/constants/client'
+import AppStepper from '@mobile/components/base/stepper/index.vue'
+import AppSelect from '@mobile/components/base/select/index.vue'
 
-defineProps({
+const props = defineProps({
     selectedRow: {
-        type: Object,
-        required: true
+        type: Object as PropType<Model.SBYJMyOrderRsp>,
+        required: true,
     }
 })
 
+const options = computed(() => {
+    return [{
+        label: '限价单', value: EPriceMode.PRICEMODE_LIMIT
+    }, {
+        label: '市价单', value: EPriceMode.PRICEMODE_MARKET
+    }]
+})
+
+const futuresStore = useFuturesStore()
+const positionStore = usePositionStore()
+const quote = futuresStore.getGoodsQuote(props.selectedRow.goodsCode)
+const { global: { t } } = i18n
+
+// 可用数量
+const maxQty = computed(() => {
+    const { holderQty, freezeQty, goodsID, buyOrSell } = props.selectedRow.tHDetailEx
+    const record = positionStore.positionList.find((e) => e.goodsid === goodsID && e.buyorsell === buyOrSell)
+    const qty = holderQty - freezeQty
+    return Math.min(record?.enableqty ?? 0, qty)
+})
+
+// 损益
+const closepl = computed(() => {
+    const { holderQty, buyOrSell, holderAmount } = props.selectedRow.tHDetailEx
+    const { agreeUnit } = props.selectedRow
+    const { presettle = 0, last = 0 } = quote.value ?? {}
+    const price = last || presettle // 没有最新价取昨结价
+    // 计算市值 = 现价 * 数量 * 合约单位
+    const marketValue = price ? price * holderQty * agreeUnit : 0
+
+    return price ? (marketValue - holderAmount) * (buyOrSell === BuyOrSell.Buy ? 1 : -1) : 0
+})
+
+const formRef = shallowRef<FormInstance>()
 const showModal = shallowRef(true)
-const refresh = shallowRef(false) // 是否刷新父组件数据
+// 是否刷新父组件数据
+const refresh = shallowRef(false)
+const { formSubmit, formData } = useOrder()
 
-// 关闭弹窗=
+// 表单验证规则
+const formRules: { [key: string]: FieldRule[] } = {
+    OrderPrice: [{
+        message: t('position.goods.tips1'),
+        validator: () => {
+            return !!formData.OrderPrice
+        }
+    }],
+    OrderQty: [{
+        message: t('position.goods.tips2'),
+        validator: () => {
+            return !!formData.OrderQty
+        }
+    }],
+}
+
+const onCloseSumit = () => {
+    dialog({
+        message: '确认要平仓吗?',
+        showCancelButton: true,
+    }).then(() => {
+
+        const { marketID, goodsID, buyOrSell, tradeID } = props.selectedRow.tHDetailEx
+        /// 市场ID
+        formData.Header = { GoodsID: goodsID }
+        formData.MarketID = marketID
+        formData.BuyOrSell = buyOrSell === BuyOrSell.Buy ? BuyOrSell.Sell : BuyOrSell.Buy
+        formData.GoodsID = goodsID
+        formData.ListingSelectType = EListingSelectType.LISTINGSELECTTYPE_DELISTINGTHENLISTING
+        formData.DelistingType = EDelistingType.DELISTINGTYPE_PRICE
+        formData.BuildType = EBuildType.BUILDTYPE_CLOSE
+        formData.TimevalidType = EValidType.VALIDTYPE_DR
+        formData.OperateType = 24
+        formData.RelatedID = handleRequestBigNumber(tradeID)
+
+        /// loding....
+        fullloading((hideLoading) => {
+            formSubmit().then(() => {
+                hideLoading(t('position.goods.tips4'), 'success')
+                closed(true)
+            }).catch((err) => {
+                hideLoading(err, 'fail')
+            })
+        })
+    })
+}
+
+// 关闭弹窗
 const closed = (isRefresh = false) => {
     refresh.value = isRefresh
     showModal.value = false
 }
 
+onMounted(() => {
+    const { bid, ask, presettle = 0 } = quote.value ?? {}
+    const { buyOrSell } = props.selectedRow.tHDetailEx
+    switch (buyOrSell) {
+        case BuyOrSell.Buy:
+            formData.OrderPrice = ask || presettle
+            break
+        case BuyOrSell.Sell:
+            formData.OrderPrice = bid || presettle
+            break
+        default:
+            formData.OrderPrice = presettle
+    }
+    formData.OrderQty = maxQty.value
+    formData.PriceMode = EPriceMode.PRICEMODE_LIMIT
+})
+
 // 暴露组件属性给父组件调用
 defineExpose({
     closed,

+ 3 - 3
src/packages/digital/views/contract/components/position/index.vue

@@ -58,8 +58,8 @@
             <tfoot>
                 <tr>
                     <td colspan="3">
-                        <Button size="small" @click="closePosition()">平仓</Button>
-                        <Button size="small" @click="closePositionAtMarket()">市价平仓</Button>
+                        <Button size="small" @click="closePosition(item)">平仓</Button>
+                        <Button size="small" @click="closePositionAtMarket(item)">市价平仓</Button>
                     </td>
                 </tr>
             </tfoot>
@@ -89,7 +89,7 @@ const componentMap = new Map<string, unknown>([
 
 const selectedRow = shallowRef<Model.SBYJMyOrderRsp>()
 const { getSBYJMyOrders, $toRefs, calRiskRate, calReturnRate, calUseMargin } = useSBYJOrderStore()
-const { orderComputedList, loading, error } = $toRefs()
+const { orderComputedList } = $toRefs()
 
 const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => getSBYJMyOrders())
 

+ 30 - 5
src/packages/digital/views/contract/components/position/market-close/index.vue

@@ -1,23 +1,29 @@
 <template>
-    <Dialog v-model:show="showDialog" title="您确定要按市价平仓吗?" show-cancel-button :before-close="onBeforeClose"
+    <Dialog v-model:show="showDialog" title="您确定要按市价平仓吗?" show-cancel-button :before-close="onBeforeClose" @confirm="marketClose"
         @closed="onClosed">
         <span>市价平仓会以市价委托方式平掉此仓位。</span>
     </Dialog>
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, onMounted } from 'vue'
+import { shallowRef, onMounted, PropType } from 'vue'
 import { Dialog } from 'vant'
+import { useHolderClose } from '@/business/trade'
+import { handleRequestBigNumber } from '@/filters'
+import { fullloading } from '@/utils/vant'
+import { i18n } from '@/stores'
 
-defineProps({
+
+const props = defineProps({
     selectedRow: {
-        type: Object,
+        type: Object as PropType<Model.SBYJMyOrderRsp>,
         required: true
     }
 })
 
+const { holderCloseSubmit, formData } = useHolderClose()
 const emit = defineEmits(['closed'])
-
+const { global: { t } } = i18n
 const showDialog = shallowRef(false)
 const refresh = shallowRef(false) // 是否刷新父组件数据
 
@@ -33,6 +39,25 @@ const onClosed = () => {
     emit('closed', refresh.value)
 }
 
+const marketClose = () => {
+    
+    const { marketID, goodsID, buyOrSell, tradeID } = props.selectedRow.tHDetailEx
+        formData.Header = { MarketID: marketID }
+        formData.GoodsID = goodsID
+        formData.BuyOrSell = buyOrSell
+        formData.MarketID = marketID
+        formData.TradeID = handleRequestBigNumber(tradeID)
+        /// loding....
+        fullloading((hideLoading) => {
+            holderCloseSubmit().then(() => {
+                hideLoading(t('position.swap.tips2'))
+                onClosed()
+            }).catch((err) => {
+                hideLoading(err, 'fail')
+            })
+        })
+}
+
 onMounted(() => {
     showDialog.value = true
 })

+ 3 - 2
src/packages/digital/views/contract/goods/detail/index.vue

@@ -80,6 +80,7 @@ import { useNavigation } from '@mobile/router/navigation'
 import { useFuturesStore } from '@/stores'
 import { fullloading, dialog } from '@/utils/vant'
 import { useOrder } from '@/business/trade'
+import { useSBYJOrderStore } from '@/stores'
 import AppStepper from '@mobile/components/base/stepper/index.vue'
 import AppSelect from '@mobile/components/base/select/index.vue'
 import ContractPosition from '../../components/position/index.vue'
@@ -93,7 +94,7 @@ const futuresStore = useFuturesStore()
 const tabIndex = shallowRef(0)
 
 const { formData, formSubmit } = useOrder()
-
+const { getSBYJMyOrders } = useSBYJOrderStore()
 const quote = computed(() => futuresStore.getQuoteInfo({ goodsid: goodsId }))
 
 const options = computed(() => {
@@ -158,7 +159,7 @@ const onSubmit = () => {
             formSubmit().then(() => {
                 hideLoading('提交成功。', 'success')
                 // 刷新订单列表
-                // getSBYJMyOrders()
+                getSBYJMyOrders()
             }).catch((err) => {
                 hideLoading(err, 'fail')
             })