From 22905aeb395e732e283abfc2949c9b976a6f455b Mon Sep 17 00:00:00 2001
From: dongzp <975303544@qq.com>
Date: Tue, 21 Jul 2026 14:59:43 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E9=97=BB=E6=95=B0=E6=8D=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.vue | 10 ++++--
src/api/baidu/mapNews.ts | 22 +++++++++++++
src/api/baidu/news.ts | 38 +++++++++++++++++++++++
src/api/baidu/types.ts | 21 +++++++++++++
src/components/news/NewsItem.vue | 2 +-
src/components/news/NewsList.vue | 53 ++++++++++++++++++++++++++++++--
src/composables/useNews.ts | 18 ++++++-----
src/mocks/news.ts | 49 ++---------------------------
src/types/index.ts | 5 +--
9 files changed, 156 insertions(+), 62 deletions(-)
create mode 100644 src/api/baidu/mapNews.ts
create mode 100644 src/api/baidu/news.ts
diff --git a/src/App.vue b/src/App.vue
index 0efa384..8535a93 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -15,7 +15,13 @@
-
+
@@ -45,7 +51,7 @@ import { usePositions } from './composables/usePositions'
import { useAiAdvice } from './composables/useAiAdvice'
const { data: quote } = useQuote()
-const { data: news } = useNews()
+const { data: news, loading: newsLoading, error: newsError, refresh: refreshNews } = useNews()
const { data: positions } = usePositions()
const { data: advice, loading: adviceLoading, refresh: refreshAdvice } = useAiAdvice()
diff --git a/src/api/baidu/mapNews.ts b/src/api/baidu/mapNews.ts
new file mode 100644
index 0000000..6359393
--- /dev/null
+++ b/src/api/baidu/mapNews.ts
@@ -0,0 +1,22 @@
+import type { NewsItem } from '../../types'
+import type { BaiduFuturesNewsItem } from './types'
+
+/** 将 Unix 秒时间戳格式化为「MM-DD HH:mm」 */
+function formatPublishTime(raw: string): string {
+ const sec = Number(raw)
+ if (!Number.isFinite(sec) || sec <= 0) return ''
+ const d = new Date(sec * 1000)
+ if (Number.isNaN(d.getTime())) return ''
+ const pad = (n: number) => String(n).padStart(2, '0')
+ return `${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`
+}
+
+export function mapBaiduNewsToItems(list: BaiduFuturesNewsItem[]): NewsItem[] {
+ return list.map((item) => ({
+ id: item.news_id,
+ source: item.source || item.provider || '未知来源',
+ time: formatPublishTime(item.publish_time),
+ title: item.title,
+ url: item.loc || item.third_url,
+ }))
+}
diff --git a/src/api/baidu/news.ts b/src/api/baidu/news.ts
new file mode 100644
index 0000000..5cf7e79
--- /dev/null
+++ b/src/api/baidu/news.ts
@@ -0,0 +1,38 @@
+import { baiduHttp } from '../http'
+import type { BaiduFuturesNewsItem, BaiduFuturesNewsResponse } from './types'
+
+export interface GetFuturesNewsParams {
+ /** 合约编码,如 FG609 */
+ code: string
+ /** 页码,从 0 起 */
+ pn?: number
+ /** 每页条数 */
+ rn?: number
+}
+
+/**
+ * 百度财经 — 期货相关新闻
+ * GET /vapi/getfuturesnews?code=&pn=&rn=&finClientType=pc
+ */
+export async function getFuturesNews(
+ params: GetFuturesNewsParams,
+): Promise {
+ const { data } = await baiduHttp.get(
+ '/vapi/getfuturesnews',
+ {
+ params: {
+ code: params.code,
+ pn: params.pn ?? 0,
+ rn: params.rn ?? 20,
+ finClientType: 'pc',
+ },
+ },
+ )
+
+ const codeOk = data.ResultCode === 0 || data.ResultCode === '0'
+ if (!codeOk) {
+ throw new Error(`新闻接口失败: ResultCode=${data.ResultCode}`)
+ }
+
+ return Array.isArray(data.Result) ? data.Result : []
+}
diff --git a/src/api/baidu/types.ts b/src/api/baidu/types.ts
index 8f1b186..252a55b 100644
--- a/src/api/baidu/types.ts
+++ b/src/api/baidu/types.ts
@@ -101,3 +101,24 @@ export interface BaiduQuotationResponse {
ResultCode: string
Result: BaiduQuotationResult | BaiduQuotationResult[]
}
+
+/** 百度财经 — 期货相关新闻单条 */
+export interface BaiduFuturesNewsItem {
+ loc: string
+ provider: string
+ source: string
+ /** Unix 秒级时间戳(字符串) */
+ publish_time: string
+ third_url?: string
+ title: string
+ is_self_build?: string
+ news_id: string
+ locate_url?: string
+}
+
+export interface BaiduFuturesNewsResponse {
+ ResultCode: number | string
+ ResultNum: number
+ QueryID: string
+ Result: BaiduFuturesNewsItem[]
+}
diff --git a/src/components/news/NewsItem.vue b/src/components/news/NewsItem.vue
index 5a75e00..afdd6eb 100644
--- a/src/components/news/NewsItem.vue
+++ b/src/components/news/NewsItem.vue
@@ -5,7 +5,7 @@
查看原文 >
{{ item.title }}
- {{ item.summary }}
+ {{ item.summary }}
diff --git a/src/components/news/NewsList.vue b/src/components/news/NewsList.vue
index 9693619..4bfae88 100644
--- a/src/components/news/NewsList.vue
+++ b/src/components/news/NewsList.vue
@@ -1,17 +1,49 @@
- 相关新闻
-
+
+
相关新闻
+
+ 刷新
+
+
+
+
+
+
+
+
+
diff --git a/src/composables/useNews.ts b/src/composables/useNews.ts
index 9ce885a..603a3b7 100644
--- a/src/composables/useNews.ts
+++ b/src/composables/useNews.ts
@@ -1,10 +1,9 @@
-import { ref } from 'vue'
+import { onMounted, ref } from 'vue'
import type { NewsItem } from '../types'
import { newsMock } from '../mocks/news'
-
-function delay(ms = 300): Promise {
- return new Promise((r) => setTimeout(r, ms))
-}
+import { contractConfig } from '../config/contract'
+import { getFuturesNews } from '../api/baidu/news'
+import { mapBaiduNewsToItems } from '../api/baidu/mapNews'
export function useNews() {
const data = ref(structuredClone(newsMock))
@@ -15,14 +14,19 @@ export function useNews() {
loading.value = true
error.value = null
try {
- await delay()
- data.value = structuredClone(newsMock)
+ const list = await getFuturesNews({ code: contractConfig.code })
+ data.value = mapBaiduNewsToItems(list)
} catch (e) {
error.value = e
+ console.error('[useNews] 拉取新闻失败', e)
} finally {
loading.value = false
}
}
+ onMounted(() => {
+ void refresh()
+ })
+
return { data, loading, error, refresh }
}
diff --git a/src/mocks/news.ts b/src/mocks/news.ts
index 68b062b..d2dad8b 100644
--- a/src/mocks/news.ts
+++ b/src/mocks/news.ts
@@ -1,49 +1,4 @@
import type { NewsItem } from '../types'
-export const newsMock: NewsItem[] = [
- {
- id: 1,
- source: 'LSEG',
- time: '07-16 04:07',
- title: 'Precipitate Gold appoints Pelayo Troncoso and John Wenger to the Board',
- summary:
- 'Precipitate Gold Corp announced the appointment of Pelayo Troncoso and John Wenger as independent directors, strengthening governance ahead of exploration milestones.',
- url: 'https://example.com/news/1',
- },
- {
- id: 2,
- source: '路透',
- time: '07-16 03:42',
- title: '原油短线承压,美油回落关注库存数据',
- summary:
- '隔夜油价震荡回落,市场等待本周库存与炼厂开工率数据,短线交易者对风险偏好趋于谨慎。',
- url: 'https://example.com/news/2',
- },
- {
- id: 3,
- source: '财联社',
- time: '07-15 21:18',
- title: '玻璃期货日内走弱,期现基差小幅收敛',
- summary:
- '盘面跟随黑色系情绪回落,现货报价相对坚挺,基差有所收窄;机构提示关注沙河地区库存变化。',
- url: 'https://example.com/news/3',
- },
- {
- id: 4,
- source: 'Bloomberg',
- time: '07-15 18:05',
- title: 'Gold holds near highs as markets await PPI print',
- summary:
- 'Bullion stayed firm as traders positioned for U.S. producer price data, with real yields and dollar moves still the key drivers.',
- url: 'https://example.com/news/4',
- },
- {
- id: 5,
- source: '新华财经',
- time: '07-15 15:30',
- title: '碳酸锂价格波动加剧,产业链观望情绪升温',
- summary:
- '下游备货节奏放缓,部分贸易商报价分歧加大,锂盐市场短期或以区间震荡为主。',
- url: 'https://example.com/news/5',
- },
-]
+/** 首屏占位;打开页面后由百度 getfuturesnews 覆盖 */
+export const newsMock: NewsItem[] = []
diff --git a/src/types/index.ts b/src/types/index.ts
index 5fc964d..8504123 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -65,11 +65,12 @@ export interface QuoteData {
}
export interface NewsItem {
- id: number
+ id: string | number
source: string
time: string
title: string
- summary: string
+ /** 接口无摘要时可不填 */
+ summary?: string
url?: string
}