feat: improve stock detail view and update docs

This commit is contained in:
wanghep
2026-05-02 18:27:36 +08:00
parent a492c73cc6
commit 597aef1271
21 changed files with 1739 additions and 1481 deletions

View File

@ -5,6 +5,7 @@ import type {
ActionsResponse,
PipelineStatus,
StockDetail,
StockSearchItem,
Summary,
TraderDetail,
TraderListItem,
@ -82,22 +83,30 @@ export function useDashboardData() {
const groups = new Map<string, ActionItem>()
for (const item of rows) {
const existing = groups.get(item.stock_code)
const groupKey = `${item.stock_code}::${item.trade_date}`
const existing = groups.get(groupKey)
if (!existing) {
groups.set(item.stock_code, { ...item })
groups.set(groupKey, {
...item,
participant_traders: item.trader_name ? [item.trader_name] : [],
participant_trader_count: item.trader_name ? 1 : 0,
})
continue
}
const nextBuy = (numberFromText(existing.buy_amount_wan) ?? 0) + (numberFromText(item.buy_amount_wan) ?? 0)
const nextSell = (numberFromText(existing.sell_amount_wan) ?? 0) + (numberFromText(item.sell_amount_wan) ?? 0)
const nextNet = nextBuy - nextSell
const traderNames = new Set([existing.trader_name, item.trader_name].filter(Boolean))
const traderNames = new Set([...(existing.participant_traders ?? [existing.trader_name]), item.trader_name].filter(Boolean))
const tableTitles = new Set([existing.table_title, item.table_title].filter(Boolean))
const seatNames = new Set([existing.seat_name, item.seat_name].filter(Boolean))
const participantTraders = [...traderNames]
groups.set(item.stock_code, {
groups.set(groupKey, {
...existing,
trader_name: [...traderNames].join(' / '),
trader_name: participantTraders.join(' / '),
participant_traders: participantTraders,
participant_trader_count: participantTraders.length,
table_title: [...tableTitles].join(' / '),
seat_name: seatNames.size > 1 ? `${seatNames.size}个席位` : existing.seat_name,
buy_amount_wan: nextBuy.toFixed(2),
@ -107,7 +116,15 @@ export function useDashboardData() {
})
}
return [...groups.values()]
return [...groups.values()].sort((left, right) => {
const traderDiff = (right.participant_trader_count ?? 0) - (left.participant_trader_count ?? 0)
if (traderDiff !== 0) return traderDiff
const netDiff = (numberFromText(right.net_amount_wan) ?? 0) - (numberFromText(left.net_amount_wan) ?? 0)
if (netDiff !== 0) return netDiff
return right.trade_date.localeCompare(left.trade_date)
})
}
const filteredActions = computed(() => {
@ -226,6 +243,17 @@ export function useDashboardData() {
stockDetail.value = await api<StockDetail>(`/api/stocks/${encodeURIComponent(stockCode)}`)
}
async function searchStocks(query: string, limit = 8) {
const keyword = query.trim()
if (!keyword) return [] as StockSearchItem[]
const params = new URLSearchParams({
q: keyword,
limit: String(limit),
})
return api<StockSearchItem[]>(`/api/stocks/search?${params.toString()}`)
}
async function selectWarning(item: WarningItem) {
selectedWarningCode.value = item.stock_code
await selectStock(item.stock_code)
@ -316,6 +344,7 @@ export function useDashboardData() {
loadWatchlist,
selectTrader,
selectStock,
searchStocks,
selectWarning,
selectTradeDateRange,
isWatched,