|
|
@@ -1,65 +1,58 @@
|
|
|
<!-- 掉期市场-持仓汇总-平仓 -->
|
|
|
<template>
|
|
|
- <app-drawer title="明细" v-model:show="show" :width="1200" :loading="loading" :refresh="refresh">
|
|
|
- <app-table :data="dataList" v-model:columns="tableColumns" :loading="loading" :row-key="rowKey"
|
|
|
- :expand-row-keys="expandKeys" @row-click="rowClick">
|
|
|
- <!-- 商品代码/名称 -->
|
|
|
- <template #goodsname="{ row }">
|
|
|
- {{ row.goodscode }}/{{ row.goodsname }}
|
|
|
- </template>
|
|
|
+ <app-drawer :title="`${position.goodscode}/${position.goodsname}`" v-model:show="show" :width="1200" :loading="loading"
|
|
|
+ :refresh="refresh">
|
|
|
+ <app-table :data="computedList" v-model:columns="tableColumns" :loading="loading" :row-key="rowKey"
|
|
|
+ :expand-row-keys="expandKeys" @row-click="rowClick">
|
|
|
<!-- 方向 -->
|
|
|
<template #buyorsell="{ value }">
|
|
|
{{ getBuyOrSellName(value) }}
|
|
|
</template>
|
|
|
- <!-- 最新价 -->
|
|
|
+ <!-- 持仓金额 -->
|
|
|
<template #holderamount="{ value }">
|
|
|
- <span>
|
|
|
- {{ formatDecimal(value) }}
|
|
|
- </span>
|
|
|
+ {{ formatDecimal(value) }}
|
|
|
</template>
|
|
|
<!-- 可用数量 -->
|
|
|
<template #enableqty="{ row }">
|
|
|
- {{ row.holderqty - row.freezeqty }}
|
|
|
+ {{ row.holderqty - row.freezeqty }}
|
|
|
</template>
|
|
|
<!-- 到期日 -->
|
|
|
<template #expiredate="{ value }">
|
|
|
- <span>{{ formatDate(value, 'YYYY/MM/DD') }}</span>
|
|
|
+ {{ formatDate(value, 'YYYY/MM/DD') }}
|
|
|
</template>
|
|
|
<!-- 平仓盈亏 -->
|
|
|
<template #closepl="{ row }">
|
|
|
- <span :class="handlePriceColor(closepl(row))">{{ formatDecimal(closepl(row)) }}</span>
|
|
|
+ <span :class="handlePriceColor(row.closepl)">{{ formatDecimal(row.closepl, quote?.decimalplace) }}</span>
|
|
|
</template>
|
|
|
- <!-- 展开行 -->
|
|
|
- <template v-if="useStore.userType === 5" #expand="{ row }">
|
|
|
- <div class="buttonbar">
|
|
|
+ <!-- 操作 -->
|
|
|
+ <template #operate="{ row }">
|
|
|
+ <div class="buttonbar" v-if="useStore.userType === 5">
|
|
|
<el-button type="danger" size="small" @click="onCloseSubmit(row)">平仓</el-button>
|
|
|
</div>
|
|
|
+ <span v-else>--</span>
|
|
|
</template>
|
|
|
</app-table>
|
|
|
<template #footer>
|
|
|
- <el-button type="info" @click="onCancel(false)">取消</el-button>
|
|
|
+ <el-button type="info" @click="show = false">取消</el-button>
|
|
|
</template>
|
|
|
</app-drawer>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
-import { shallowRef, ref, PropType } from 'vue'
|
|
|
+import { shallowRef, ref, PropType, computed } from 'vue'
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
import { useComposeTable } from '@pc/components/base/table'
|
|
|
import { useRequest } from '@/hooks/request'
|
|
|
import { useHolderClose } from '@/business/trade'
|
|
|
import { queryTradeHolderDetail } from '@/services/api/order'
|
|
|
-import { formatDate, formatDecimal, handlePriceColor, handleRequestBigNumber } from '@/filters'
|
|
|
+import { formatDate, formatDecimal, handlePriceColor, handleRequestBigNumber, round } from '@/filters'
|
|
|
import { getBuyOrSellName } from '@/constants/order'
|
|
|
import { ETradeMode } from '@/constants/client'
|
|
|
import AppDrawer from '@pc/components/base/drawer/index.vue'
|
|
|
import AppTable from '@pc/components/base/table/index.vue'
|
|
|
-import quoteSocket from '@/services/websocket/quote'
|
|
|
import { useFuturesStore, useUserStore } from '@/stores'
|
|
|
import { BuyOrSell } from '@/constants/order'
|
|
|
|
|
|
-const { rowKey, expandKeys, rowClick } = useComposeTable<Model.TradeHolderDetailRsp>({ rowKey: 'tradeid' })
|
|
|
-
|
|
|
const props = defineProps({
|
|
|
position: {
|
|
|
type: Object as PropType<Model.TradePositionRsp>,
|
|
|
@@ -67,18 +60,19 @@ const props = defineProps({
|
|
|
}
|
|
|
})
|
|
|
|
|
|
+const { rowKey, expandKeys, rowClick } = useComposeTable<Model.TradeHolderDetailRsp>({ rowKey: 'tradeid' })
|
|
|
+
|
|
|
+const { holderCloseSubmit, formData } = useHolderClose()
|
|
|
const show = ref(true)
|
|
|
const refresh = ref(false)
|
|
|
-const dataList = shallowRef<Model.TradeHolderDetailRsp[]>([])
|
|
|
-const error = shallowRef(false)
|
|
|
-const subscribe = quoteSocket.createSubscribe()
|
|
|
-const { holderCloseSubmit, formData } = useHolderClose()
|
|
|
-const futuresStore = useFuturesStore()
|
|
|
-const quote = futuresStore.getGoodsQuote(props.position.refgoodscode)
|
|
|
const useStore = useUserStore()
|
|
|
-const { loading, pageIndex } = useRequest(queryTradeHolderDetail, {
|
|
|
+const futuresStore = useFuturesStore()
|
|
|
+
|
|
|
+const refQuote = futuresStore.getGoodsQuote(props.position.refgoodscode)
|
|
|
+const quote = futuresStore.getGoodsQuote(props.position.goodscode)
|
|
|
+
|
|
|
+const { dataList, loading, run } = useRequest(queryTradeHolderDetail, {
|
|
|
params: {
|
|
|
- pagesize: 20,
|
|
|
/// 交易模式, 格式 1,2,3
|
|
|
trademodes: ETradeMode.TRADEMODE_TJMD.toString(),
|
|
|
/// marketid
|
|
|
@@ -87,33 +81,28 @@ const { loading, pageIndex } = useRequest(queryTradeHolderDetail, {
|
|
|
goodsid: props.position.goodsid,
|
|
|
/// 买卖方向 0-买 1-卖
|
|
|
buyorsell: props.position.buyorsell
|
|
|
- },
|
|
|
- onSuccess: (res) => {
|
|
|
- if (pageIndex.value === 1) {
|
|
|
- dataList.value = []
|
|
|
- }
|
|
|
- dataList.value.push(...res.data)
|
|
|
- /// 订阅行情
|
|
|
- subscribe.start(props.position.refgoodscode)
|
|
|
- },
|
|
|
- onError: () => {
|
|
|
- error.value = true
|
|
|
}
|
|
|
})
|
|
|
|
|
|
-// 损益
|
|
|
-const closepl = (row: Model.TradeHolderDetailRsp) => {
|
|
|
- const { presettle = 0, last = 0 } = quote.value ?? {}
|
|
|
- const { holderqty, holderamount, agreeunit, buyorsell } = row
|
|
|
+const computedList = computed(() => dataList.value.map((item) => {
|
|
|
+ const last = refQuote.value?.last || quote.value?.last || 0 // 有 refgoodscode 的优先取 refgoodscode 行情
|
|
|
+ const presettle = quote.value?.presettle || 0
|
|
|
const price = last || presettle // 没有最新价取昨结价
|
|
|
+
|
|
|
// 计算市值 = 现价 * 数量 * 合约单位
|
|
|
- const marketValue = price ? price * holderqty * agreeunit : 0
|
|
|
- return price ? (marketValue - holderamount) * (buyorsell === BuyOrSell.Buy ? 1 : -1) : 0
|
|
|
-}
|
|
|
+ const marketValue = price ? price * item.holderqty * item.agreeunit : 0
|
|
|
+ const roundedMarketValue = round(marketValue, quote.value?.decimalplace)
|
|
|
+ // 计算浮动盈亏
|
|
|
+ const closepl = price ? (roundedMarketValue - item.holderamount) * (item.buyorsell === BuyOrSell.Buy ? 1 : -1) : 0
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ closepl
|
|
|
+ }
|
|
|
+}))
|
|
|
|
|
|
const tableColumns = shallowRef<Model.TableColumn[]>([
|
|
|
{ prop: 'tradeid', label: '单号' },
|
|
|
- { prop: 'goodsname', label: '商品代码/名称' },
|
|
|
{ prop: 'buyorsell', label: '方向' },
|
|
|
{ prop: 'holderqty', label: '持有数量' },
|
|
|
{ prop: 'freezeqty', label: '冻结数量' },
|
|
|
@@ -121,17 +110,14 @@ const tableColumns = shallowRef<Model.TableColumn[]>([
|
|
|
{ prop: 'holderprice', label: '持仓价格' },
|
|
|
{ prop: 'holderamount', label: '持仓金额' },
|
|
|
{ prop: 'closepl', label: '参考损益' },
|
|
|
- { prop: 'expiredate', label: '到期日' }
|
|
|
+ { prop: 'expiredate', label: '到期日' },
|
|
|
+ { prop: 'operate', label: '操作', fixed: 'right', width: 100 }
|
|
|
])
|
|
|
|
|
|
-const onCancel = (isRefresh = false) => {
|
|
|
- show.value = false
|
|
|
- refresh.value = isRefresh
|
|
|
-}
|
|
|
-
|
|
|
const onCloseSubmit = (row: Model.TradeHolderDetailRsp) => {
|
|
|
ElMessageBox.confirm(
|
|
|
- '是否立即平仓?'
|
|
|
+ '是否立即平仓?',
|
|
|
+ '提示'
|
|
|
).then(() => {
|
|
|
const { marketid, goodsid, buyorsell, tradeid } = row
|
|
|
formData.Header = { MarketID: marketid, GoodsID: goodsid }
|
|
|
@@ -142,11 +128,10 @@ const onCloseSubmit = (row: Model.TradeHolderDetailRsp) => {
|
|
|
|
|
|
holderCloseSubmit().then(() => {
|
|
|
ElMessage.success('提交成功')
|
|
|
- onCancel(true)
|
|
|
+ run()
|
|
|
}).catch((err) => {
|
|
|
ElMessage.error('提交失败:' + err)
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
-
|
|
|
</script>
|