持仓数据的 前20名总持仓汇总
This commit is contained in:
parent
249be8d882
commit
7728061d00
@ -9,17 +9,23 @@
|
||||
<span v-if="data.updatedAt" class="updated">数据日期 {{ data.updatedAt }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 总持仓:多 / 空 -->
|
||||
<div v-if="tab === 'total'" class="cols">
|
||||
<div class="col">
|
||||
<h3 class="long-title">多单持仓前20名</h3>
|
||||
<PositionDonut :list="data.long" />
|
||||
<PositionTable :list="data.long" qty-label="多单" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<h3 class="short-title">空单持仓前20名</h3>
|
||||
<PositionDonut :list="data.short" />
|
||||
<PositionTable :list="data.short" qty-label="空单" />
|
||||
<!-- 总持仓:多空汇总柱状图 + 多 / 空前20 -->
|
||||
<div v-if="tab === 'total'">
|
||||
<PositionSumBar
|
||||
v-if="data.topTwentySum?.length"
|
||||
:list="data.topTwentySum"
|
||||
/>
|
||||
<div class="cols">
|
||||
<div class="col">
|
||||
<h3 class="long-title">多单持仓前20名</h3>
|
||||
<PositionDonut :list="data.long" />
|
||||
<PositionTable :list="data.long" qty-label="多单" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<h3 class="short-title">空单持仓前20名</h3>
|
||||
<PositionDonut :list="data.short" />
|
||||
<PositionTable :list="data.short" qty-label="空单" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -53,6 +59,7 @@ import { ref } from 'vue'
|
||||
import type { PositionsData } from '../../types'
|
||||
import PositionDonut from './PositionDonut.vue'
|
||||
import PositionTable from './PositionTable.vue'
|
||||
import PositionSumBar from './PositionSumBar.vue'
|
||||
|
||||
defineProps<{
|
||||
data: PositionsData
|
||||
|
||||
103
src/components/position/PositionSumBar.vue
Normal file
103
src/components/position/PositionSumBar.vue
Normal file
@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<div class="sum-bar">
|
||||
<h3 class="title">前20多空总持仓</h3>
|
||||
<v-chart class="chart" :option="option" autoresize />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { use } from 'echarts/core'
|
||||
import { CanvasRenderer } from 'echarts/renderers'
|
||||
import { BarChart } from 'echarts/charts'
|
||||
import {
|
||||
GridComponent,
|
||||
TooltipComponent,
|
||||
LegendComponent,
|
||||
} from 'echarts/components'
|
||||
import type { EChartsOption } from 'echarts'
|
||||
import VChart from 'vue-echarts'
|
||||
import type { TopTwentySum } from '../../types'
|
||||
|
||||
use([CanvasRenderer, BarChart, GridComponent, TooltipComponent, LegendComponent])
|
||||
|
||||
const props = defineProps<{
|
||||
list: TopTwentySum[]
|
||||
}>()
|
||||
|
||||
const option = computed((): EChartsOption => {
|
||||
// 接口通常新→旧,图表按时间从左到右
|
||||
const sorted = [...props.list].sort((a, b) =>
|
||||
a.tradeDate.localeCompare(b.tradeDate),
|
||||
)
|
||||
const dates = sorted.map((x) => x.tradeDate)
|
||||
const longData = sorted.map((x) => x.longSum)
|
||||
const shortData = sorted.map((x) => x.shortSum)
|
||||
|
||||
return {
|
||||
color: ['#e54545', '#0ea5a0'],
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { type: 'shadow' },
|
||||
valueFormatter: (v) =>
|
||||
typeof v === 'number' ? v.toLocaleString('zh-CN') : String(v ?? ''),
|
||||
},
|
||||
legend: {
|
||||
data: ['多总持仓', '空总持仓'],
|
||||
top: 0,
|
||||
right: 8,
|
||||
textStyle: { fontSize: 12 },
|
||||
},
|
||||
grid: { left: 56, right: 16, top: 36, bottom: 28 },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: dates,
|
||||
axisLabel: { fontSize: 11 },
|
||||
axisTick: { alignWithLabel: true },
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
scale: true,
|
||||
axisLabel: {
|
||||
fontSize: 10,
|
||||
formatter: (v: number) =>
|
||||
v >= 10000 ? `${(v / 10000).toFixed(0)}万` : String(v),
|
||||
},
|
||||
splitLine: { lineStyle: { type: 'dashed', color: '#eee' } },
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '多总持仓',
|
||||
type: 'bar',
|
||||
data: longData,
|
||||
barMaxWidth: 36,
|
||||
itemStyle: { color: '#e54545', borderRadius: [2, 2, 0, 0] },
|
||||
},
|
||||
{
|
||||
name: '空总持仓',
|
||||
type: 'bar',
|
||||
data: shortData,
|
||||
barMaxWidth: 36,
|
||||
itemStyle: { color: '#0ea5a0', borderRadius: [2, 2, 0, 0] },
|
||||
},
|
||||
],
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.sum-bar {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0 0 4px;
|
||||
font-size: 14px;
|
||||
color: var(--text-primary, #303133);
|
||||
}
|
||||
|
||||
.chart {
|
||||
height: 240px;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -83,6 +83,7 @@ export const positionsMock: PositionsData = {
|
||||
topTwentySum: [
|
||||
{ tradeDate: '2026-07-15', longSum: 1073446, shortSum: 1502020 },
|
||||
{ tradeDate: '2026-07-14', longSum: 1094199, shortSum: 1519906 },
|
||||
{ tradeDate: '2026-07-13', longSum: 1095204, shortSum: 1537419 },
|
||||
],
|
||||
updatedAt: '2026-07-15',
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user