li.shaoyi преди 1 месец
родител
ревизия
bdbb65fe30

+ 11 - 20
src/packages/digital/views/contract/components/position/detail/close/index.vue

@@ -10,24 +10,20 @@
                     <Cell title="持仓单号" :value="selectedItem.tradeid" />
                     <Cell title="代码/名称" :value="`${selectedItem.goodscode}/${selectedItem.goodsname}`" />
                     <Cell title="持仓方向" :value="getBuyOrSellName(selectedItem.buyorsell)" />
-                    <Cell title="持仓价格(USDT)"
-                        :value="formatDecimal(selectedItem.holderprice, selectedItem.decimalplace)" />
+                    <Cell title="持仓价格(USDT)" :value="round(selectedItem.holderprice, selectedItem.decimalplace)" />
                     <Cell title="持仓量" :value="selectedItem.holderqty" />
                     <Cell title="冻结量" :value="selectedItem.freezeqty" />
-                    <Cell title="行情价格">
+                    <Cell title="行情价格" :value="floatingPL.lastPrice">
                         <template #value>
-                            <span :class="quote?.bidColor" v-if="selectedItem.buyorsell === BuyOrSell.Buy">
-                                {{ quote?.bid }}
-                            </span>
-                            <span :class="quote?.askColor" v-if="selectedItem.buyorsell === BuyOrSell.Sell">
-                                {{ quote?.ask }}
+                            <span :class="floatingPL.lastPriceClass">
+                                {{ round(floatingPL.lastPrice, selectedItem.decimalplace) }}
                             </span>
                         </template>
                     </Cell>
                     <Cell title="浮动盈亏">
                         <template #value>
-                            <span :class="handlePriceColor(closepl)">
-                                {{ formatDecimal(closepl, selectedItem.decimalplace) }}
+                            <span :class="floatingPL.profitLossClass">
+                                {{ round(floatingPL.profitLoss, selectedItem.decimalplace) }}
                             </span>
                         </template>
                     </Cell>
@@ -64,8 +60,9 @@
 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 { round } from 'lodash'
 import { getBuyOrSellName, BuyOrSell, getPricemode2List } from '@/constants/order'
-import { formatDecimal, handleRequestBigNumber, handlePriceColor } from '@/filters'
+import { handleRequestBigNumber } from '@/filters'
 import { useOrder } from '@/business/trade'
 import { dialog, fullloading } from '@/utils/vant'
 import { useFuturesStore, usePositionStore, i18n, useUserStore } from '@/stores'
@@ -83,7 +80,7 @@ const props = defineProps({
 const userStore = useUserStore()
 const futuresStore = useFuturesStore()
 const positionStore = usePositionStore()
-const quote = futuresStore.getGoodsQuote(props.selectedItem.goodscode)
+const quote = computed(() => futuresStore.getQuoteItem({ goodsid: props.selectedItem.goodsid }))
 const { global: { t } } = i18n
 
 // 可用数量
@@ -95,15 +92,9 @@ const maxQty = computed(() => {
 })
 
 // 损益
-const closepl = computed(() => {
+const floatingPL = computed(() => {
     const { holderqty, buyorsell, holderamount } = props.selectedItem
-    const { agreeunit } = props.selectedItem
-    const { presettle = 0, ask = 0, bid = 0 } = quote.value ?? {}
-    const price = (buyorsell === BuyOrSell.Buy ? ask : bid) || presettle // 没有最新价取昨结价
-    // 计算市值 = 现价 * 数量 * 合约单位
-    const marketValue = price ? price * holderqty * agreeunit : 0
-
-    return price ? (marketValue - holderamount) * (buyorsell === BuyOrSell.Buy ? 1 : -1) : 0
+    return futuresStore.calcFloatingPL(quote.value, buyorsell, holderqty, holderamount)
 })
 
 const formRef = shallowRef<FormInstance>()

+ 18 - 5
src/packages/digital/views/contract/components/position/detail/index.vue

@@ -6,7 +6,7 @@
             </template>
             <app-pull-refresh ref="pullRefreshRef" class="g-detail-table" v-model:loading="loading"
                 @refresh="onRefresh">
-                <table cellspacing="0" cellpadding="0" v-for="(item, index) in dataList" :key="index">
+                <table cellspacing="0" cellpadding="0" v-for="(item, index) in tableList" :key="index">
                     <tbody>
                         <tr>
                             <th colspan="2">
@@ -22,14 +22,16 @@
                         <tr>
                             <td colspan="3">
                                 <span class="text-small">浮动盈亏({{ getGoodsCurrencyItemName(item.currencyid) }})</span>
-                                <span>{{ 0 }}</span>
+                                <span :class="item.profitLossClass">
+                                    {{ round(item.profitLoss, item.decimalplace) }}
+                                </span>
                             </td>
                         </tr>
                         <tr>
                             <td>
                                 <span class="text-small">可用量({{ item.goodscode }})</span>
                                 <span>
-                                    {{ 0 }}
+                                    {{ item.holderqty - item.freezeqty }}
                                 </span>
                             </td>
                             <td>
@@ -70,13 +72,15 @@
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, PropType, defineAsyncComponent } from 'vue'
+import { shallowRef, PropType, defineAsyncComponent, computed } from 'vue'
 import { Button } from 'vant'
+import { round } from 'lodash'
 import { formatDate } from '@/filters'
 import { getBuyOrSellName, getGoodsCurrencyItemName } from '@/constants/order'
 import { useRequest } from '@/hooks/request'
 import { useComponent } from '@/hooks/component'
 import { queryTradeHolderDetail } from '@/services/api/order'
+import { useFuturesStore } from '@/stores'
 import AppModal from '@/components/base/modal/index.vue'
 import AppPullRefresh from '@mobile/components/base/pull-refresh/index.vue'
 
@@ -96,14 +100,23 @@ const showModal = shallowRef(true) // 是否刷新父组件数据
 const refresh = shallowRef(false)
 const selectedItem = shallowRef<Model.TradeHolderDetailRsp>()
 
+const futuresStore = useFuturesStore()
+const quote = computed(() => futuresStore.getQuoteItem({ goodsid: props.selectedRow.goodsid }))
+
 const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => onRefresh())
 
 const { dataList, loading, run } = useRequest(queryTradeHolderDetail, {
     defaultParams: {
-        goodsid: props.selectedRow.goodsid
+        goodsid: props.selectedRow.goodsid,
+        buyorsell: props.selectedRow.buyorsell
     }
 })
 
+const tableList = computed(() => dataList.value.map((item) => ({
+    ...item,
+    ...futuresStore.calcFloatingPL(quote.value, item.buyorsell, item.holderqty, item.holderamount)
+})))
+
 const showComponent = (componentName: string, row: Model.TradeHolderDetailRsp) => {
     selectedItem.value = row
     openComponent(componentName)

+ 9 - 11
src/packages/digital/views/contract/components/position/list/close/index.vue

@@ -14,18 +14,15 @@
                     <Cell title="冻结量" :value="selectedRow.frozenqty" />
                     <Cell title="行情价格">
                         <template #value>
-                            <span :class="quote?.bidColor" v-if="selectedRow.buyorsell === BuyOrSell.Buy">
-                                {{ quote?.bid }}
-                            </span>
-                            <span :class="quote?.askColor" v-if="selectedRow.buyorsell === BuyOrSell.Sell">
-                                {{ quote?.ask }}
+                            <span :class="selectedRow.lastPriceClass">
+                                {{ round(selectedRow.lastPrice, selectedRow.decimalplace) }}
                             </span>
                         </template>
                     </Cell>
                     <Cell title="浮动盈亏">
                         <template #value>
-                            <span :class="selectedRow.closeplColor">
-                                {{ selectedRow.closepl }}
+                            <span :class="selectedRow.profitLossClass">
+                                {{ round(selectedRow.profitLoss, selectedRow.decimalplace) }}
                             </span>
                         </template>
                     </Cell>
@@ -60,6 +57,7 @@
 <script lang="ts" setup>
 import { shallowRef, PropType, onMounted, computed } from 'vue'
 import { CellGroup, Cell, Button, FieldRule, Form, Field, FormInstance } from 'vant'
+import { round } from 'lodash'
 import { dialog, fullloading } from '@/utils/vant'
 import { getBuyOrSellName, BuyOrSell, getPricemode2List } from '@/constants/order'
 import { useOrder } from '@/business/trade'
@@ -72,10 +70,10 @@ import AppSelect from '@mobile/components/base/select/index.vue'
 const props = defineProps({
     selectedRow: {
         type: Object as PropType<Model.TradePositionRsp & {
-            lastColor: string;
-            closepl: number;
-            closeplColor: string;
-            marketValue: number;
+            lastPrice: number;
+            lastPriceClass: string;
+            profitLoss: number;
+            profitLossClass: string;
         }>,
         required: true,
     }

+ 5 - 2
src/packages/digital/views/contract/components/position/list/index.vue

@@ -14,7 +14,9 @@
                 <tr>
                     <td colspan="2">
                         <span class="text-small">浮动盈亏({{ getGoodsCurrencyItemName(item.currencyid) }})</span>
-                        <span :class="item.closeplColor">{{ item.closepl }}</span>
+                        <span :class="item.profitLossClass">
+                            {{ round(item.profitLoss, item.decimalplace) }}
+                        </span>
                     </td>
                     <td>
                         <span :class="item.buyorsell === 0 ? 'g-price-up' : 'g-price-down'">
@@ -31,7 +33,7 @@
                     </td>
                     <td>
                         <span class="text-small">持仓量({{ item.goodscode }})</span>
-                        <span>{{ item.positionqty }}</span>
+                        <span>{{ item.curpositionqty }}</span>
                     </td>
                     <td>
                         <span class="text-small">冻结量({{ item.goodscode }})</span>
@@ -67,6 +69,7 @@
 <script lang="ts" setup>
 import { PropType, shallowRef, defineAsyncComponent, computed } from 'vue'
 import { Button, Icon } from 'vant'
+import { round } from 'lodash'
 import { useComponent } from '@/hooks/component'
 import { getBuyOrSellName, getGoodsCurrencyItemName } from '@/constants/order'
 import { usePositionStore } from '@/stores'

+ 2 - 2
src/packages/mobile/views/order/position/components/goods/list/Index.vue

@@ -37,8 +37,8 @@
                         </li>
                         <li>
                             <span>{{ $t('position.goods.closepl') }}</span>
-                            <span :class="item.closeplColor">
-                                {{ formatDecimal(item.closepl, item.decimalplace) }}
+                            <span :class="item.profitLossClass">
+                                {{ formatDecimal(item.profitLoss, item.decimalplace) }}
                             </span>
                         </li>
                     </ul>

+ 2 - 2
src/packages/mobile/views/order/position/components/pricing/list/Index.vue

@@ -37,8 +37,8 @@
                         </li>
                         <li>
                             <span>{{ $t('position.pricing.closepl') }}</span>
-                            <span :class="item.closeplColor">
-                                {{ formatDecimal(item.closepl, item.decimalplace) }}
+                            <span :class="item.profitLossClass">
+                                {{ formatDecimal(item.profitLoss, item.decimalplace) }}
                             </span>
                         </li>
                     </ul>

+ 3 - 3
src/packages/mobile/views/order/position/components/swap/list/Index.vue

@@ -31,7 +31,7 @@
                         </li>
                         <li>
                             <span>{{ $t('position.swap.lastprice') }}</span>
-                            <span :class="item.lastColor">{{ handleNumberValue(item.lastprice) }}</span>
+                            <span :class="item.lastPriceClass">{{ handleNumberValue(item.lastPrice) }}</span>
                         </li>
                         <li>
                             <span>{{ $t('position.swap.enableqty') }}</span>
@@ -39,8 +39,8 @@
                         </li>
                         <li>
                             <span>{{ $t('position.swap.closepl') }}</span>
-                            <span :class="item.closeplColor">
-                                {{ formatDecimal(item.closepl, item.decimalplace) }}
+                            <span :class="item.profitLossClass">
+                                {{ formatDecimal(item.profitLoss, item.decimalplace) }}
                             </span>
                         </li>
                     </ul>

+ 1 - 1
src/stores/modules/account.ts

@@ -55,7 +55,7 @@ export const useAccountStore = defineStore(() => {
             // 账号持仓列表
             const positionList = positionStore.positionComputedList.filter((e) => e.accountid === item.accountid)
             // 计算浮动盈亏
-            const profitLoss = positionList.reduce((pre, cur) => cur.tradeproperty === 1 ? pre += cur.closepl : pre, 0)
+            const profitLoss = positionList.reduce((pre, cur) => cur.tradeproperty === 1 ? pre += cur.profitLoss : pre, 0)
 
             // 计算市值(所有权)
             const marketValue = positionList.reduce((pre, cur) => cur.tradeproperty === 2 ? pre += cur.marketValue : pre, 0)

+ 30 - 1
src/stores/modules/futures.ts

@@ -3,6 +3,7 @@ import { v4 } from 'uuid'
 import { isMatch } from 'lodash'
 import { timerTask } from '@/utils/timer'
 import { handlePriceColor } from '@/filters'
+import { BuyOrSell } from '@/constants/order'
 import { queryMemberGoodsLimitConfig } from '@/services/api/common'
 import { queryErmcpGoods, queryQuoteDay } from '@/services/api/goods'
 import { wordArrayToUint8Array } from '@/services/websocket/package/crypto'
@@ -563,6 +564,33 @@ export const useFuturesStore = defineStore(() => {
         return '--'
     }
 
+    // 计算浮动盈亏
+    const calcFloatingPL = (quote: Model.GoodsQuote | undefined, buyorsell: number, quantity: number, amount: number, exchangerate = 1) => {
+        const { trademode = 0, last = 0, presettle = 0, ask = 0, bid = 0, agreeunit = 1 } = quote ?? {}
+        const isSupportedMode = [10, 52, 80].includes(trademode)
+        const lastPrice = (isSupportedMode && (buyorsell === BuyOrSell.Buy ? bid : ask)) || last || presettle
+
+        const result = {
+            lastPrice, // 最新价
+            marketValue: 0, // 市值
+            profitLoss: 0, // 浮动盈亏
+            lastPriceClass: '', // 最新价样式
+            profitLossClass: '' // 浮动盈亏样式
+        }
+
+        if (lastPrice) {
+            // 计算市值 = 现价 * 数量 * 合约单位 * 汇率
+            result.marketValue = lastPrice * quantity * agreeunit * exchangerate
+            // 计算浮动盈亏 任务 #5600 #6013
+            result.profitLoss = (result.marketValue - amount) * (buyorsell === BuyOrSell.Buy ? 1 : -1)
+
+            result.lastPriceClass = handlePriceColor(lastPrice, presettle)
+            result.profitLossClass = handlePriceColor(result.profitLoss)
+        }
+
+        return result
+    }
+
     return {
         ...toRefs(state),
         marketGoodsList,
@@ -584,6 +612,7 @@ export const useFuturesStore = defineStore(() => {
         getGoods,
         goodsdisplay,
         getQuoteItem,
-        getFeeValue
+        getFeeValue,
+        calcFloatingPL
     }
 })

+ 26 - 56
src/stores/modules/position.ts

@@ -1,9 +1,7 @@
 import { reactive, computed, toRefs } from 'vue'
 import { isMatch } from 'lodash'
-import { handlePriceColor, round } from '@/filters'
 import { BuyOrSell } from '@/constants/order'
 import { queryTradePosition, querySBYJMyOrders } from '@/services/api/order'
-import { useGlobalStore } from './global'
 import { useUserStore } from './user'
 import { useFuturesStore } from './futures'
 import { defineStore } from '../store'
@@ -14,7 +12,6 @@ import quoteSocket from '@/services/websocket/quote'
  * 持仓存储对象
  */
 export const usePositionStore = defineStore(() => {
-    const globalStore = useGlobalStore()
     const userStore = useUserStore()
     const futuresStore = useFuturesStore()
     const subscribe = quoteSocket.createSubscribe()
@@ -40,48 +37,25 @@ export const usePositionStore = defineStore(() => {
     }
 
     // 持仓汇总计算列表
-    const positionComputedList = computed(() => {
-        const result: (Model.TradePositionRsp & {
-            lastColor: string; // 最新价颜色
-            closepl: number; // 浮动盈亏
-            closeplColor: string; // 浮动盈亏颜色
-            marketValue: number; // 市值
-        })[] = []
-
-        state.positionList.forEach((item) => {
-            const quote = futuresStore.getGoodsQuote(item.goodscode)
-            const refQuote = futuresStore.getGoodsQuote(item.refgoodscode)
-
-            const last = refQuote.value?.last || quote.value?.last || 0 // 有 refgoodscode 的优先取 refgoodscode 行情
-            const presettle = quote.value?.presettle || 0
-            const price = last || presettle // 没有最新价取昨结价
-
-            let exchangerate = 1
-            // 查找汇率
-            if (item.currencyid !== item.tacurrencyid) {
-                const currency = userStore.userData.exchangeRateConfigs.find((e) => e.descurrencyid === item.tacurrencyid && e.oricurrencyid === item.currencyid)
-                exchangerate = currency?.exchangerate ?? 0
-            }
+    const positionComputedList = computed(() => state.positionList.map((item) => {
+        const quote = futuresStore.getQuoteItem({ goodscode: item.goodscode })
+        const refQuote = futuresStore.getQuoteItem({ goodscode: item.refgoodscode })
+        const quoteItem = refQuote || quote
+
+        let exchangerate = 1
+        // 查找汇率
+        if (item.currencyid !== item.tacurrencyid) {
+            const currency = userStore.userData.exchangeRateConfigs.find((e) => e.descurrencyid === item.tacurrencyid && e.oricurrencyid === item.currencyid)
+            exchangerate = currency?.exchangerate ?? 0
+        }
 
-            // 计算市值 = 现价 * 数量 * 合约单位 * 汇率
-            const marketValue = price * item.curpositionqty * item.agreeunit * exchangerate
-            const roundedMarketValue = round(marketValue, quote.value?.decimalplace)
-            // 计算浮动盈亏 任务 #5600 #6013
-            const closepl = (price && globalStore.getSystemInfo('riskType') !== 1) ? (roundedMarketValue - item.curholderamount) * (item.buyorsell === BuyOrSell.Buy ? 1 : -1) : 0
-            const roundedClosepl = round(closepl, quote.value?.decimalplace)
-
-            result.push({
-                ...item,
-                lastprice: price,
-                lastColor: handlePriceColor(price, presettle),
-                closepl: roundedClosepl,
-                closeplColor: handlePriceColor(roundedClosepl, 0),
-                marketValue: roundedMarketValue,
-            })
-        })
+        const floatingPL = futuresStore.calcFloatingPL(quoteItem, item.buyorsell, item.curpositionqty, item.curholderamount, exchangerate)
 
-        return result
-    })
+        return {
+            ...item,
+            ...floatingPL
+        }
+    }))
 
     // 过滤持仓列表
     const filterPositionList = (props: Partial<Model.TradePositionRsp>) => {
@@ -150,19 +124,15 @@ export const useSBYJOrderStore = defineStore(() => {
 
     // 计算浮动盈亏
     const calcFloatpl = ({ tHDetailEx }: Model.SBYJMyOrderRsp) => {
-        const quote = futuresStore.getGoodsQuote(tHDetailEx.goodsID)
-        const { ask = 0, bid = 0, agreeunit = 0 } = quote.value ?? {}
-        const price = tHDetailEx.buyOrSell === BuyOrSell.Buy ? bid : ask // 根据方向取买卖价
-        // 计算浮动盈亏 (价格 * 手数 * 合约乘数 - 持仓金额) * 方向标识
-        const float = price ? price * tHDetailEx.holderQty * agreeunit - tHDetailEx.holderAmount : 0
-        const result = float * (tHDetailEx.buyOrSell === BuyOrSell.Buy ? 1 : -1)
-        return round(result, quote.value?.decimalplace)
+        const quote = futuresStore.getQuoteItem({ goodsid: tHDetailEx.goodsID })
+        const floatingPL = futuresStore.calcFloatingPL(quote, tHDetailEx.buyOrSell, tHDetailEx.holderQty, tHDetailEx.holderAmount)
+        return floatingPL.profitLoss
     }
 
     // 计算定金率
     const calcDepositRate = ({ tHDetailEx }: Model.SBYJMyOrderRsp) => {
-        const quote = futuresStore.getGoodsQuote(tHDetailEx.goodsID)
-        const { ask = 0, bid = 0, agreeunit = 0 } = quote.value ?? {}
+        const quote = futuresStore.getQuoteItem({ goodsid: tHDetailEx.goodsID })
+        const { ask = 0, bid = 0, agreeunit = 0 } = quote ?? {}
         const price = tHDetailEx.buyOrSell === BuyOrSell.Buy ? bid : ask // 根据方向取买卖价
 
         // 计算浮动盈亏 (价格 * 手数 * 合约乘数 - 持仓金额) * 方向标识
@@ -185,8 +155,8 @@ export const useSBYJOrderStore = defineStore(() => {
         // 已付定金+补充定金
         const useMargin = e.tHDetailEx.payedDeposit + e.tHDetailEx.restockDeposit
 
-        const quote = futuresStore.getGoodsQuote(e.tHDetailEx.goodsID)
-        const { ask = 0, bid = 0, agreeunit = 0 } = quote.value ?? {}
+        const quote = futuresStore.getQuoteItem({ goodsid: e.tHDetailEx.goodsID })
+        const { ask = 0, bid = 0, agreeunit = 0 } = quote ?? {}
         const price = e.tHDetailEx.buyOrSell === BuyOrSell.Buy ? bid : ask // 根据方向取买卖价
 
         // 计算浮动盈亏 (价格 * 手数 * 合约乘数 - 持仓金额) * 方向标识
@@ -202,8 +172,8 @@ export const useSBYJOrderStore = defineStore(() => {
         // 已付定金+补充定金
         const useMargin = e.tHDetailEx.payedDeposit + e.tHDetailEx.restockDeposit
 
-        const quote = futuresStore.getGoodsQuote(e.tHDetailEx.goodsID)
-        const { ask = 0, bid = 0, agreeunit = 0 } = quote.value ?? {}
+        const quote = futuresStore.getQuoteItem({ goodsid: e.tHDetailEx.goodsID })
+        const { ask = 0, bid = 0, agreeunit = 0 } = quote ?? {}
         const price = e.tHDetailEx.buyOrSell === BuyOrSell.Buy ? bid : ask // 根据方向取买卖价
 
         // 计算浮动盈亏 (价格 * 手数 * 合约乘数 - 持仓金额) * 方向标识