持仓数据的 前20名总持仓汇总

This commit is contained in:
dongzp 2026-07-21 16:21:40 +08:00
parent 249be8d882
commit 7728061d00
3 changed files with 122 additions and 11 deletions

View File

@ -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

View 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>

View File

@ -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',
}