Skip to content

Commit fd4136d

Browse files
Ruicursoragent
andcommitted
refactor(client-ui): remove notice and financial tabs from detail panel
Drop announcement and financial tabs from CN and cross-market right panels; relocate dividend, shareholder, and money-flow blocks to the company tab and update cross-market footnotes for MCP-first deep data. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent a0d4b53 commit fd4136d

3 files changed

Lines changed: 5 additions & 192 deletions

File tree

client-ui/src/market/CrossMarketSnapshotDetail.tsx

Lines changed: 3 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { openExternalUrl } from '../platform/openUrl'
1414
import type {
1515
CryptoSnapshotData,
1616
CrossMarketRelatedStock,
17-
FinancialSummaryData,
1817
RevenueBreakdownBlock,
1918
SeniorTradeItem,
2019
StockDividendItem,
@@ -50,7 +49,7 @@ import { listRowKey } from '../utils/listRowKey'
5049
const CONTENT_PAD = '15px'
5150

5251
type EquityDetail = UsSnapshotData
53-
type DetailTab = 'chart' | 'basic' | 'company' | 'notices' | 'articles' | 'f10' | 'dividends' | 'holders'
52+
type DetailTab = 'chart' | 'basic' | 'company' | 'articles' | 'dividends' | 'holders'
5453

5554
const useStyles = makeStyles({
5655
root: {
@@ -705,33 +704,6 @@ function ShareholderPanel({ data }: { data: StockShareholderData | null | undefi
705704
)
706705
}
707706

708-
function FinancialHistoryPanel({ rows }: { rows: FinancialSummaryData[] }) {
709-
const s = useStyles()
710-
if (!rows.length) {
711-
return <Text className={s.emptyHint}>暂无历史财务数据</Text>
712-
}
713-
return (
714-
<div className={s.flatList}>
715-
<div className={s.tableHeadWide}>
716-
<span className={s.tableHeadCell}>报告期</span>
717-
<span className={s.tableHeadCell}>类型</span>
718-
<span className={s.tableHeadCell}>营收</span>
719-
<span className={s.tableHeadCell}>净利</span>
720-
<span className={s.tableHeadCell}>负债率</span>
721-
</div>
722-
{rows.slice(0, 12).map((row, index) => (
723-
<div key={listRowKey(index, row.reportDate, row.reportType)} className={s.tableRowWide}>
724-
<span className={s.tableCell}>{row.reportDate || '—'}</span>
725-
<span className={s.tableCell}>{row.reportType || '—'}</span>
726-
<span className={s.tableCell}>{formatCompactNumber(row.revenue)}</span>
727-
<span className={s.tableCell}>{formatCompactNumber(row.netProfit)}</span>
728-
<span className={s.tableCell}>{row.debtRatio != null ? `${row.debtRatio.toFixed(2)}%` : '—'}</span>
729-
</div>
730-
))}
731-
</div>
732-
)
733-
}
734-
735707
function MiniKline({
736708
bars,
737709
formatPriceLabel,
@@ -823,9 +795,6 @@ export default function CrossMarketSnapshotDetail({
823795
const crypto = isCrypto ? (snapshot as CryptoSnapshotData | null) : null
824796
const quote = equity?.quote ?? crypto?.quote ?? null
825797
const profile = asProfile(equity?.profile ?? null)
826-
const financial = equity?.financial ?? null
827-
const financialHistory = equity?.financialHistory ?? (financial ? [financial] : [])
828-
const notices = equity?.notices ?? equity?.news ?? []
829798
const articles = equity?.articles ?? []
830799
const dividends = equity?.dividends ?? []
831800
const shareholders = equity?.shareholders ?? null
@@ -860,8 +829,8 @@ export default function CrossMarketSnapshotDetail({
860829
: ref.market === 'US'
861830
? (quote && 'quoteSession' in quote && (quote.quoteSession === 'pre' || quote.quoteSession === 'post')
862831
? '当前为延长交易时段报价;盘中以常规时段为准。'
863-
: '行情、公告、资讯与财务摘要来自腾讯公开接口,约每 1–2 分钟刷新。')
864-
: '行情、公告、资讯、分红与业绩展望来自腾讯公开接口,约每 1–2 分钟刷新。'
832+
: '行情约每 1–2 分钟刷新;深度资料请通过助手查询。')
833+
: '行情与业绩展望约每 1–2 分钟刷新;深度资料请通过助手查询。'
865834

866835
if (isCrypto) {
867836
return (
@@ -967,9 +936,7 @@ export default function CrossMarketSnapshotDetail({
967936
<Tab value="chart">走势</Tab>
968937
<Tab value="basic">概况</Tab>
969938
<Tab value="company">公司</Tab>
970-
<Tab value="notices">公告</Tab>
971939
<Tab value="articles">资讯</Tab>
972-
<Tab value="f10">财务</Tab>
973940
{showDividendsTab ? <Tab value="dividends">分红</Tab> : null}
974941
{showHoldersTab ? <Tab value="holders">股东</Tab> : null}
975942
</TabList>
@@ -1016,18 +983,6 @@ export default function CrossMarketSnapshotDetail({
1016983
) : null}
1017984
</div>
1018985
</MetricSection>
1019-
{financial ? (
1020-
<MetricSection title="最新财务摘要">
1021-
<div className={s.metricGrid3}>
1022-
<Metric label="报告期" value={financial.reportDate || '—'} />
1023-
<Metric label="营收" value={formatCompactNumber(financial.revenue)} />
1024-
<Metric label="净利润" value={formatCompactNumber(financial.netProfit)} />
1025-
<Metric label="净利率" value={financial.netMargin != null ? `${financial.netMargin.toFixed(2)}%` : '—'} />
1026-
<Metric label="负债率" value={financial.debtRatio != null ? `${financial.debtRatio.toFixed(2)}%` : '—'} />
1027-
<Metric label="经营现金流" value={formatCompactNumber(financial.operatingCashFlow)} />
1028-
</div>
1029-
</MetricSection>
1030-
) : null}
1031986
{ref.market === 'HK' && tradingDistribution ? (
1032987
<MetricSection title="今日成交分布">
1033988
<TradingDistributionPanel data={tradingDistribution} formatPrice={v => fmtPrice(v)} />
@@ -1105,40 +1060,12 @@ export default function CrossMarketSnapshotDetail({
11051060
</div>
11061061
</div>
11071062

1108-
<div className={mergeClasses(s.tabPanel, detailTab !== 'notices' && s.tabPanelHidden)}>
1109-
<div className={mergeClasses(s.scrollPanel, 'opptrix-scroll')}>
1110-
<NewsPanel items={notices} emptyHint="暂无官方公告" />
1111-
</div>
1112-
</div>
1113-
11141063
<div className={mergeClasses(s.tabPanel, detailTab !== 'articles' && s.tabPanelHidden)}>
11151064
<div className={mergeClasses(s.scrollPanel, 'opptrix-scroll')}>
11161065
<NewsPanel items={articles} emptyHint="暂无相关资讯" />
11171066
</div>
11181067
</div>
11191068

1120-
<div className={mergeClasses(s.tabPanel, detailTab !== 'f10' && s.tabPanelHidden)}>
1121-
<div className={mergeClasses(s.scrollPanel, 'opptrix-scroll')}>
1122-
{financial ? (
1123-
<MetricSection title="最新财报摘要">
1124-
<div className={s.metricGrid3}>
1125-
<Metric label="营收" value={formatCompactNumber(financial.revenue)} />
1126-
<Metric label="净利润" value={formatCompactNumber(financial.netProfit)} />
1127-
<Metric label="净利率" value={financial.netMargin != null ? `${financial.netMargin.toFixed(2)}%` : '—'} />
1128-
<Metric label="总资产" value={formatCompactNumber(financial.totalAssets ?? null)} />
1129-
<Metric label="总负债" value={formatCompactNumber(financial.totalLiabilities ?? null)} />
1130-
<Metric label="负债率" value={financial.debtRatio != null ? `${financial.debtRatio.toFixed(2)}%` : '—'} />
1131-
<Metric label="经营现金流" value={formatCompactNumber(financial.operatingCashFlow)} />
1132-
<Metric label="报告期" value={financial.reportDate || '—'} />
1133-
</div>
1134-
</MetricSection>
1135-
) : null}
1136-
<MetricSection title="历史财务">
1137-
<FinancialHistoryPanel rows={financialHistory} />
1138-
</MetricSection>
1139-
</div>
1140-
</div>
1141-
11421069
{showDividendsTab ? (
11431070
<div className={mergeClasses(s.tabPanel, detailTab !== 'dividends' && s.tabPanelHidden)}>
11441071
<div className={mergeClasses(s.scrollPanel, 'opptrix-scroll')}>

client-ui/src/market/StockDetailTab.tsx

Lines changed: 1 addition & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@ import { Link, Spinner, Tab, TabList, Text, Badge, makeStyles, mergeClasses } fr
33
import { EditRegular } from '@fluentui/react-icons'
44
import { research } from '../api/client'
55
import type {
6-
FinancialSummaryData,
76
ProfileInstitutionRating,
87
ProfilePlateItem,
98
StockDetailData,
109
StockDividendItem,
1110
StockMoneyFlowItem,
12-
StockNewsItem,
1311
StockProfileData,
1412
StockShareholderData,
1513
WatchlistItem,
@@ -37,7 +35,7 @@ import type { HoldingSnapshot } from './useFollowPortfolio'
3735
import { opptrixTokens, opptrixCssVars } from '../theme/tokens'
3836
import { ghostInteractive } from '../theme/mixins'
3937

40-
type DetailTab = 'analysis' | 'chart' | 'trend' | 'basic' | 'company' | 'news' | 'f10'
38+
type DetailTab = 'analysis' | 'chart' | 'trend' | 'basic' | 'company'
4139

4240
const CONTENT_PAD = '15px'
4341

@@ -482,35 +480,6 @@ function MetricSection({ title, children }: { title: string; children: ReactNode
482480
)
483481
}
484482

485-
function NewsPanel({ items }: { items: StockNewsItem[] }) {
486-
const s = useStyles()
487-
if (!items.length) {
488-
return <Text className={s.emptyHint}>暂无公告信息</Text>
489-
}
490-
return (
491-
<div className={s.flatList}>
492-
{items.map((item, index) => (
493-
<div key={listRowKey(index, item.date, item.title, item.url)} className={s.annRow}>
494-
<span className={s.listDate}>{item.date || '—'}</span>
495-
{item.url ? (
496-
<Link
497-
className={s.listTitle}
498-
href={item.url}
499-
target="_blank"
500-
rel="noreferrer"
501-
onClick={event => openExternalUrl(item.url!, event)}
502-
>
503-
{item.title}
504-
</Link>
505-
) : (
506-
<span className={s.listTitle}>{item.title}</span>
507-
)}
508-
</div>
509-
))}
510-
</div>
511-
)
512-
}
513-
514483
function DividendPanel({ items }: { items: StockDividendItem[] }) {
515484
const s = useStyles()
516485
if (!items.length) {
@@ -686,33 +655,6 @@ function InstitutionRatingPanel({ rating }: { rating: ProfileInstitutionRating }
686655
)
687656
}
688657

689-
function FinancialHistoryPanel({ rows }: { rows: FinancialSummaryData[] }) {
690-
const s = useStyles()
691-
if (!rows.length) {
692-
return <Text className={s.emptyHint}>暂无历史财务数据</Text>
693-
}
694-
return (
695-
<div className={s.flatList}>
696-
<div className={s.tableHeadWide}>
697-
<span className={s.tableHeadCell}>报告期</span>
698-
<span className={s.tableHeadCell}>类型</span>
699-
<span className={s.tableHeadCell}>营收</span>
700-
<span className={s.tableHeadCell}>净利</span>
701-
<span className={s.tableHeadCell}>ROE</span>
702-
</div>
703-
{rows.slice(0, 12).map((row, index) => (
704-
<div key={listRowKey(index, row.reportDate, row.reportType)} className={s.tableRowWide}>
705-
<span className={s.tableCell}>{row.reportDate || '—'}</span>
706-
<span className={s.tableCell}>{row.reportType || '—'}</span>
707-
<span className={s.tableCell}>{formatCompactNumber(row.revenue)}</span>
708-
<span className={s.tableCell}>{formatCompactNumber(row.netProfit)}</span>
709-
<span className={s.tableCell}>{row.roe != null ? `${row.roe.toFixed(2)}%` : '—'}</span>
710-
</div>
711-
))}
712-
</div>
713-
)
714-
}
715-
716658
function StockDetailTab({
717659
stock,
718660
isHolding = false,
@@ -814,7 +756,6 @@ function StockDetailTab({
814756

815757
const quote = detail.quote
816758
const profile = detail.profile
817-
const financial = detail.financial
818759
const displayName = detail.name && detail.name !== detail.code
819760
? detail.name
820761
: (stock.name && stock.name !== stock.code ? stock.name : (profile?.name || profile?.orgName || detail.code))
@@ -876,8 +817,6 @@ function StockDetailTab({
876817
<Tab value="analysis">分析</Tab>
877818
<Tab value="basic">概况</Tab>
878819
<Tab value="company">公司</Tab>
879-
<Tab value="news">公告</Tab>
880-
<Tab value="f10">财务</Tab>
881820
</TabList>
882821
</div>
883822

@@ -947,9 +886,6 @@ function StockDetailTab({
947886
<Metric label="总市值" value={formatCompactNumber(profile?.totalMarketCap ?? quote?.marketCap ?? null)} />
948887
<Metric label="流通市值" value={formatCompactNumber(profile?.circulatingMarketCap ?? null)} />
949888
<Metric label="所属行业" value={formatIndustryLine(profile, stock.industry)} />
950-
<Metric label="EPS" value={financial?.eps != null ? financial.eps.toFixed(2) : '—'} />
951-
<Metric label="每股净资产" value={financial?.bps != null ? financial.bps.toFixed(2) : '—'} />
952-
<Metric label="报告类型" value={financial?.reportType ?? '—'} />
953889
</div>
954890
</MetricSection>
955891

@@ -975,23 +911,6 @@ function StockDetailTab({
975911
</div>
976912
</MetricSection>
977913
) : null}
978-
979-
{financial && (
980-
<MetricSection title="盈利能力">
981-
<div className={s.metricGrid3}>
982-
<Metric label="营收" value={formatCompactNumber(financial.revenue)} />
983-
<Metric label="营收同比" value={formatPct(financial.revenueYoy)} />
984-
<Metric label="净利润" value={formatCompactNumber(financial.netProfit)} />
985-
<Metric label="净利同比" value={formatPct(financial.netProfitYoy)} />
986-
<Metric label="ROE" value={financial.roe != null ? `${financial.roe.toFixed(2)}%` : '—'} />
987-
<Metric label="毛利率" value={financial.grossMargin != null ? `${financial.grossMargin.toFixed(2)}%` : '—'} />
988-
<Metric label="净利率" value={financial.netMargin != null ? `${financial.netMargin.toFixed(2)}%` : '—'} />
989-
<Metric label="资产负债率" value={financial.debtRatio != null ? `${financial.debtRatio.toFixed(2)}%` : '—'} />
990-
<Metric label="每股现金流" value={financial.operatingCashFlow != null ? financial.operatingCashFlow.toFixed(2) : '—'} />
991-
<Metric label="报告期" value={financial.reportDate || '—'} />
992-
</div>
993-
</MetricSection>
994-
)}
995914
</div>
996915
</div>
997916

@@ -1114,39 +1033,6 @@ function StockDetailTab({
11141033
<Text className={s.prose} block>{profile.businessScope}</Text>
11151034
</MetricSection>
11161035
)}
1117-
</div>
1118-
</div>
1119-
1120-
<div className={mergeClasses(s.tabPanel, detailTab !== 'news' && s.tabPanelHidden)}>
1121-
<div className={mergeClasses(s.scrollPanel, 'opptrix-scroll')}>
1122-
<NewsPanel items={detail.news ?? []} />
1123-
</div>
1124-
</div>
1125-
1126-
<div className={mergeClasses(s.tabPanel, detailTab !== 'f10' && s.tabPanelHidden)}>
1127-
<div className={mergeClasses(s.scrollPanel, 'opptrix-scroll')}>
1128-
{financial && (
1129-
<MetricSection title="最新财报摘要">
1130-
<div className={s.metricGrid3}>
1131-
<Metric label="营收" value={formatCompactNumber(financial.revenue)} />
1132-
<Metric label="营收同比" value={formatPct(financial.revenueYoy)} />
1133-
<Metric label="净利润" value={formatCompactNumber(financial.netProfit)} />
1134-
<Metric label="净利同比" value={formatPct(financial.netProfitYoy)} />
1135-
<Metric label="ROE" value={financial.roe != null ? `${financial.roe.toFixed(2)}%` : '—'} />
1136-
<Metric label="毛利率" value={financial.grossMargin != null ? `${financial.grossMargin.toFixed(2)}%` : '—'} />
1137-
<Metric label="净利率" value={financial.netMargin != null ? `${financial.netMargin.toFixed(2)}%` : '—'} />
1138-
<Metric label="资产负债率" value={financial.debtRatio != null ? `${financial.debtRatio.toFixed(2)}%` : '—'} />
1139-
<Metric label="每股现金流" value={financial.operatingCashFlow != null ? financial.operatingCashFlow.toFixed(2) : '—'} />
1140-
<Metric label="每股净资产" value={financial.bps != null ? financial.bps.toFixed(2) : '—'} />
1141-
<Metric label="EPS" value={financial.eps != null ? financial.eps.toFixed(2) : '—'} />
1142-
<Metric label="报告期" value={`${financial.reportDate || '—'} ${financial.reportType ?? ''}`.trim()} />
1143-
</div>
1144-
</MetricSection>
1145-
)}
1146-
1147-
<MetricSection title="财务历史">
1148-
<FinancialHistoryPanel rows={detail.financialHistory ?? []} />
1149-
</MetricSection>
11501036

11511037
<MetricSection title="分红送转">
11521038
<DividendPanel items={detail.dividends ?? []} />

packages/research-hub/src/cross-market-detail.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/** 美股 / 港股详情 — 将腾讯自定义方法响应规范为与 A 股 stockDetail 对齐的结构 */
1+
/** 美股 / 港股详情 — 将标准层响应规范为与 A 股 stockDetail 对齐的结构 */
22

33
function num(v: unknown): number | null {
44
if (v == null || v === '') return null

0 commit comments

Comments
 (0)