refactor(Company): fetch 请求迁移至 axios
- DeepAnalysis: 4 个 fetch → axios - DynamicTracking: 3 个 fetch → axios (NewsPanel, ForecastPanel) - MarketDataView/services: 4 个 fetch → axios - CompanyOverview/hooks: 9 个 fetch → axios (6 个文件) - StockQuoteCard/hooks: 1 个 fetch → axios - ValueChainNodeCard: 1 个 fetch → axios 清理: - 删除未使用的 useCompanyOverviewData.ts - 移除所有 getApiBase/API_BASE_URL 引用 总计: 22 个 fetch 调用迁移, 复用项目已有的 axios 拦截器配置 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -32,12 +32,10 @@ import {
|
|||||||
FaStar,
|
FaStar,
|
||||||
} from 'react-icons/fa';
|
} from 'react-icons/fa';
|
||||||
import { logger } from '@utils/logger';
|
import { logger } from '@utils/logger';
|
||||||
import { getApiBase } from '@utils/apiConfig';
|
import axios from '@utils/axiosConfig';
|
||||||
import RelatedCompaniesModal from './RelatedCompaniesModal';
|
import RelatedCompaniesModal from './RelatedCompaniesModal';
|
||||||
import type { ValueChainNodeCardProps, RelatedCompany } from '../../types';
|
import type { ValueChainNodeCardProps, RelatedCompany } from '../../types';
|
||||||
|
|
||||||
const API_BASE_URL = getApiBase();
|
|
||||||
|
|
||||||
// 黑金主题配置
|
// 黑金主题配置
|
||||||
const THEME = {
|
const THEME = {
|
||||||
cardBg: 'gray.700',
|
cardBg: 'gray.700',
|
||||||
@@ -120,12 +118,11 @@ const ValueChainNodeCard: React.FC<ValueChainNodeCardProps> = memo(({
|
|||||||
const fetchRelatedCompanies = async () => {
|
const fetchRelatedCompanies = async () => {
|
||||||
setLoadingRelated(true);
|
setLoadingRelated(true);
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const { data } = await axios.get(
|
||||||
`${API_BASE_URL}/api/company/value-chain/related-companies?node_name=${encodeURIComponent(
|
`/api/company/value-chain/related-companies?node_name=${encodeURIComponent(
|
||||||
node.node_name
|
node.node_name
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
const data = await response.json();
|
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
setRelatedCompanies(data.data || []);
|
setRelatedCompanies(data.data || []);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -3,11 +3,9 @@
|
|||||||
|
|
||||||
import { useState, useEffect, useCallback } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { logger } from "@utils/logger";
|
import { logger } from "@utils/logger";
|
||||||
import { getApiBase } from "@utils/apiConfig";
|
import axios from "@utils/axiosConfig";
|
||||||
import type { Announcement } from "../types";
|
import type { Announcement } from "../types";
|
||||||
|
|
||||||
const API_BASE_URL = getApiBase();
|
|
||||||
|
|
||||||
interface ApiResponse<T> {
|
interface ApiResponse<T> {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
data: T;
|
data: T;
|
||||||
@@ -35,10 +33,9 @@ export const useAnnouncementsData = (stockCode?: string): UseAnnouncementsDataRe
|
|||||||
setError(null);
|
setError(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const { data: result } = await axios.get<ApiResponse<Announcement[]>>(
|
||||||
`${API_BASE_URL}/api/stock/${stockCode}/announcements?limit=20`
|
`/api/stock/${stockCode}/announcements?limit=20`
|
||||||
);
|
);
|
||||||
const result = (await response.json()) as ApiResponse<Announcement[]>;
|
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
setAnnouncements(result.data);
|
setAnnouncements(result.data);
|
||||||
|
|||||||
@@ -3,11 +3,9 @@
|
|||||||
|
|
||||||
import { useState, useEffect, useCallback } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { logger } from "@utils/logger";
|
import { logger } from "@utils/logger";
|
||||||
import { getApiBase } from "@utils/apiConfig";
|
import axios from "@utils/axiosConfig";
|
||||||
import type { BasicInfo } from "../types";
|
import type { BasicInfo } from "../types";
|
||||||
|
|
||||||
const API_BASE_URL = getApiBase();
|
|
||||||
|
|
||||||
interface ApiResponse<T> {
|
interface ApiResponse<T> {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
data: T;
|
data: T;
|
||||||
@@ -35,8 +33,9 @@ export const useBasicInfo = (stockCode?: string): UseBasicInfoResult => {
|
|||||||
setError(null);
|
setError(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/stock/${stockCode}/basic-info`);
|
const { data: result } = await axios.get<ApiResponse<BasicInfo>>(
|
||||||
const result = (await response.json()) as ApiResponse<BasicInfo>;
|
`/api/stock/${stockCode}/basic-info`
|
||||||
|
);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
setBasicInfo(result.data);
|
setBasicInfo(result.data);
|
||||||
|
|||||||
@@ -3,11 +3,9 @@
|
|||||||
|
|
||||||
import { useState, useEffect, useCallback } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { logger } from "@utils/logger";
|
import { logger } from "@utils/logger";
|
||||||
import { getApiBase } from "@utils/apiConfig";
|
import axios from "@utils/axiosConfig";
|
||||||
import type { Branch } from "../types";
|
import type { Branch } from "../types";
|
||||||
|
|
||||||
const API_BASE_URL = getApiBase();
|
|
||||||
|
|
||||||
interface ApiResponse<T> {
|
interface ApiResponse<T> {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
data: T;
|
data: T;
|
||||||
@@ -35,8 +33,9 @@ export const useBranchesData = (stockCode?: string): UseBranchesDataResult => {
|
|||||||
setError(null);
|
setError(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/stock/${stockCode}/branches`);
|
const { data: result } = await axios.get<ApiResponse<Branch[]>>(
|
||||||
const result = (await response.json()) as ApiResponse<Branch[]>;
|
`/api/stock/${stockCode}/branches`
|
||||||
|
);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
setBranches(result.data);
|
setBranches(result.data);
|
||||||
|
|||||||
@@ -1,140 +0,0 @@
|
|||||||
// src/views/Company/components/CompanyOverview/hooks/useCompanyOverviewData.ts
|
|
||||||
// 公司概览数据加载 Hook
|
|
||||||
|
|
||||||
import { useState, useEffect, useCallback } from "react";
|
|
||||||
import { logger } from "@utils/logger";
|
|
||||||
import { getApiBase } from "@utils/apiConfig";
|
|
||||||
import type {
|
|
||||||
BasicInfo,
|
|
||||||
ActualControl,
|
|
||||||
Concentration,
|
|
||||||
Management,
|
|
||||||
Shareholder,
|
|
||||||
Branch,
|
|
||||||
Announcement,
|
|
||||||
DisclosureSchedule,
|
|
||||||
CompanyOverviewData,
|
|
||||||
} from "../types";
|
|
||||||
|
|
||||||
const API_BASE_URL = getApiBase();
|
|
||||||
|
|
||||||
interface ApiResponse<T> {
|
|
||||||
success: boolean;
|
|
||||||
data: T;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 公司概览数据加载 Hook
|
|
||||||
* @param propStockCode - 股票代码
|
|
||||||
* @returns 公司概览数据
|
|
||||||
*/
|
|
||||||
export const useCompanyOverviewData = (propStockCode?: string): CompanyOverviewData => {
|
|
||||||
const [stockCode, setStockCode] = useState(propStockCode || "000001");
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [dataLoaded, setDataLoaded] = useState(false);
|
|
||||||
|
|
||||||
// 基本信息数据
|
|
||||||
const [basicInfo, setBasicInfo] = useState<BasicInfo | null>(null);
|
|
||||||
const [actualControl, setActualControl] = useState<ActualControl[]>([]);
|
|
||||||
const [concentration, setConcentration] = useState<Concentration[]>([]);
|
|
||||||
const [management, setManagement] = useState<Management[]>([]);
|
|
||||||
const [topCirculationShareholders, setTopCirculationShareholders] = useState<Shareholder[]>([]);
|
|
||||||
const [topShareholders, setTopShareholders] = useState<Shareholder[]>([]);
|
|
||||||
const [branches, setBranches] = useState<Branch[]>([]);
|
|
||||||
const [announcements, setAnnouncements] = useState<Announcement[]>([]);
|
|
||||||
const [disclosureSchedule, setDisclosureSchedule] = useState<DisclosureSchedule[]>([]);
|
|
||||||
|
|
||||||
// 监听 props 中的 stockCode 变化
|
|
||||||
useEffect(() => {
|
|
||||||
if (propStockCode && propStockCode !== stockCode) {
|
|
||||||
setStockCode(propStockCode);
|
|
||||||
setDataLoaded(false);
|
|
||||||
}
|
|
||||||
}, [propStockCode, stockCode]);
|
|
||||||
|
|
||||||
// 加载基本信息数据(9个接口)
|
|
||||||
const loadBasicInfoData = useCallback(async () => {
|
|
||||||
if (dataLoaded) return;
|
|
||||||
|
|
||||||
setLoading(true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const [
|
|
||||||
basicRes,
|
|
||||||
actualRes,
|
|
||||||
concentrationRes,
|
|
||||||
managementRes,
|
|
||||||
circulationRes,
|
|
||||||
shareholdersRes,
|
|
||||||
branchesRes,
|
|
||||||
announcementsRes,
|
|
||||||
disclosureRes,
|
|
||||||
] = await Promise.all([
|
|
||||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/basic-info`).then((r) =>
|
|
||||||
r.json()
|
|
||||||
) as Promise<ApiResponse<BasicInfo>>,
|
|
||||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/actual-control`).then((r) =>
|
|
||||||
r.json()
|
|
||||||
) as Promise<ApiResponse<ActualControl[]>>,
|
|
||||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/concentration`).then((r) =>
|
|
||||||
r.json()
|
|
||||||
) as Promise<ApiResponse<Concentration[]>>,
|
|
||||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/management?active_only=true`).then((r) =>
|
|
||||||
r.json()
|
|
||||||
) as Promise<ApiResponse<Management[]>>,
|
|
||||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/top-circulation-shareholders?limit=10`).then((r) =>
|
|
||||||
r.json()
|
|
||||||
) as Promise<ApiResponse<Shareholder[]>>,
|
|
||||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/top-shareholders?limit=10`).then((r) =>
|
|
||||||
r.json()
|
|
||||||
) as Promise<ApiResponse<Shareholder[]>>,
|
|
||||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/branches`).then((r) =>
|
|
||||||
r.json()
|
|
||||||
) as Promise<ApiResponse<Branch[]>>,
|
|
||||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/announcements?limit=20`).then((r) =>
|
|
||||||
r.json()
|
|
||||||
) as Promise<ApiResponse<Announcement[]>>,
|
|
||||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/disclosure-schedule`).then((r) =>
|
|
||||||
r.json()
|
|
||||||
) as Promise<ApiResponse<DisclosureSchedule[]>>,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (basicRes.success) setBasicInfo(basicRes.data);
|
|
||||||
if (actualRes.success) setActualControl(actualRes.data);
|
|
||||||
if (concentrationRes.success) setConcentration(concentrationRes.data);
|
|
||||||
if (managementRes.success) setManagement(managementRes.data);
|
|
||||||
if (circulationRes.success) setTopCirculationShareholders(circulationRes.data);
|
|
||||||
if (shareholdersRes.success) setTopShareholders(shareholdersRes.data);
|
|
||||||
if (branchesRes.success) setBranches(branchesRes.data);
|
|
||||||
if (announcementsRes.success) setAnnouncements(announcementsRes.data);
|
|
||||||
if (disclosureRes.success) setDisclosureSchedule(disclosureRes.data);
|
|
||||||
|
|
||||||
setDataLoaded(true);
|
|
||||||
} catch (err) {
|
|
||||||
logger.error("useCompanyOverviewData", "loadBasicInfoData", err, { stockCode });
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
}, [stockCode, dataLoaded]);
|
|
||||||
|
|
||||||
// 首次加载
|
|
||||||
useEffect(() => {
|
|
||||||
if (stockCode) {
|
|
||||||
loadBasicInfoData();
|
|
||||||
}
|
|
||||||
}, [stockCode, loadBasicInfoData]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
basicInfo,
|
|
||||||
actualControl,
|
|
||||||
concentration,
|
|
||||||
management,
|
|
||||||
topCirculationShareholders,
|
|
||||||
topShareholders,
|
|
||||||
branches,
|
|
||||||
announcements,
|
|
||||||
disclosureSchedule,
|
|
||||||
loading,
|
|
||||||
dataLoaded,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -3,11 +3,9 @@
|
|||||||
|
|
||||||
import { useState, useEffect, useCallback } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { logger } from "@utils/logger";
|
import { logger } from "@utils/logger";
|
||||||
import { getApiBase } from "@utils/apiConfig";
|
import axios from "@utils/axiosConfig";
|
||||||
import type { DisclosureSchedule } from "../types";
|
import type { DisclosureSchedule } from "../types";
|
||||||
|
|
||||||
const API_BASE_URL = getApiBase();
|
|
||||||
|
|
||||||
interface ApiResponse<T> {
|
interface ApiResponse<T> {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
data: T;
|
data: T;
|
||||||
@@ -35,10 +33,9 @@ export const useDisclosureData = (stockCode?: string): UseDisclosureDataResult =
|
|||||||
setError(null);
|
setError(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const { data: result } = await axios.get<ApiResponse<DisclosureSchedule[]>>(
|
||||||
`${API_BASE_URL}/api/stock/${stockCode}/disclosure-schedule`
|
`/api/stock/${stockCode}/disclosure-schedule`
|
||||||
);
|
);
|
||||||
const result = (await response.json()) as ApiResponse<DisclosureSchedule[]>;
|
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
setDisclosureSchedule(result.data);
|
setDisclosureSchedule(result.data);
|
||||||
|
|||||||
@@ -3,11 +3,9 @@
|
|||||||
|
|
||||||
import { useState, useEffect, useCallback } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { logger } from "@utils/logger";
|
import { logger } from "@utils/logger";
|
||||||
import { getApiBase } from "@utils/apiConfig";
|
import axios from "@utils/axiosConfig";
|
||||||
import type { Management } from "../types";
|
import type { Management } from "../types";
|
||||||
|
|
||||||
const API_BASE_URL = getApiBase();
|
|
||||||
|
|
||||||
interface ApiResponse<T> {
|
interface ApiResponse<T> {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
data: T;
|
data: T;
|
||||||
@@ -35,10 +33,9 @@ export const useManagementData = (stockCode?: string): UseManagementDataResult =
|
|||||||
setError(null);
|
setError(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const { data: result } = await axios.get<ApiResponse<Management[]>>(
|
||||||
`${API_BASE_URL}/api/stock/${stockCode}/management?active_only=true`
|
`/api/stock/${stockCode}/management?active_only=true`
|
||||||
);
|
);
|
||||||
const result = (await response.json()) as ApiResponse<Management[]>;
|
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
setManagement(result.data);
|
setManagement(result.data);
|
||||||
|
|||||||
@@ -3,11 +3,9 @@
|
|||||||
|
|
||||||
import { useState, useEffect, useCallback } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { logger } from "@utils/logger";
|
import { logger } from "@utils/logger";
|
||||||
import { getApiBase } from "@utils/apiConfig";
|
import axios from "@utils/axiosConfig";
|
||||||
import type { ActualControl, Concentration, Shareholder } from "../types";
|
import type { ActualControl, Concentration, Shareholder } from "../types";
|
||||||
|
|
||||||
const API_BASE_URL = getApiBase();
|
|
||||||
|
|
||||||
interface ApiResponse<T> {
|
interface ApiResponse<T> {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
data: T;
|
data: T;
|
||||||
@@ -41,19 +39,16 @@ export const useShareholderData = (stockCode?: string): UseShareholderDataResult
|
|||||||
setError(null);
|
setError(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const [actualRes, concentrationRes, shareholdersRes, circulationRes] = await Promise.all([
|
const [
|
||||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/actual-control`).then((r) =>
|
{ data: actualRes },
|
||||||
r.json()
|
{ data: concentrationRes },
|
||||||
) as Promise<ApiResponse<ActualControl[]>>,
|
{ data: shareholdersRes },
|
||||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/concentration`).then((r) =>
|
{ data: circulationRes },
|
||||||
r.json()
|
] = await Promise.all([
|
||||||
) as Promise<ApiResponse<Concentration[]>>,
|
axios.get<ApiResponse<ActualControl[]>>(`/api/stock/${stockCode}/actual-control`),
|
||||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/top-shareholders?limit=10`).then((r) =>
|
axios.get<ApiResponse<Concentration[]>>(`/api/stock/${stockCode}/concentration`),
|
||||||
r.json()
|
axios.get<ApiResponse<Shareholder[]>>(`/api/stock/${stockCode}/top-shareholders?limit=10`),
|
||||||
) as Promise<ApiResponse<Shareholder[]>>,
|
axios.get<ApiResponse<Shareholder[]>>(`/api/stock/${stockCode}/top-circulation-shareholders?limit=10`),
|
||||||
fetch(`${API_BASE_URL}/api/stock/${stockCode}/top-circulation-shareholders?limit=10`).then((r) =>
|
|
||||||
r.json()
|
|
||||||
) as Promise<ApiResponse<Shareholder[]>>,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (actualRes.success) setActualControl(actualRes.data);
|
if (actualRes.success) setActualControl(actualRes.data);
|
||||||
|
|||||||
@@ -3,13 +3,11 @@
|
|||||||
|
|
||||||
import React, { useState, useEffect, useCallback, useRef } from "react";
|
import React, { useState, useEffect, useCallback, useRef } from "react";
|
||||||
import { logger } from "@utils/logger";
|
import { logger } from "@utils/logger";
|
||||||
import { getApiBase } from "@utils/apiConfig";
|
import axios from "@utils/axiosConfig";
|
||||||
|
|
||||||
// 复用原有的展示组件
|
// 复用原有的展示组件
|
||||||
import DeepAnalysisTab from "../CompanyOverview/DeepAnalysisTab";
|
import DeepAnalysisTab from "../CompanyOverview/DeepAnalysisTab";
|
||||||
|
|
||||||
const API_BASE_URL = getApiBase();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tab 与 API 接口映射
|
* Tab 与 API 接口映射
|
||||||
* - strategy 和 business 共用 comprehensive 接口
|
* - strategy 和 business 共用 comprehensive 接口
|
||||||
@@ -84,9 +82,9 @@ const DeepAnalysis = ({ stockCode }) => {
|
|||||||
switch (apiKey) {
|
switch (apiKey) {
|
||||||
case "comprehensive":
|
case "comprehensive":
|
||||||
setComprehensiveLoading(true);
|
setComprehensiveLoading(true);
|
||||||
const comprehensiveRes = await fetch(
|
const { data: comprehensiveRes } = await axios.get(
|
||||||
`${API_BASE_URL}/api/company/comprehensive-analysis/${stockCode}`
|
`/api/company/comprehensive-analysis/${stockCode}`
|
||||||
).then((r) => r.json());
|
);
|
||||||
// 检查 stockCode 是否已变更(防止竞态)
|
// 检查 stockCode 是否已变更(防止竞态)
|
||||||
if (currentStockCodeRef.current === stockCode) {
|
if (currentStockCodeRef.current === stockCode) {
|
||||||
if (comprehensiveRes.success)
|
if (comprehensiveRes.success)
|
||||||
@@ -97,9 +95,9 @@ const DeepAnalysis = ({ stockCode }) => {
|
|||||||
|
|
||||||
case "valueChain":
|
case "valueChain":
|
||||||
setValueChainLoading(true);
|
setValueChainLoading(true);
|
||||||
const valueChainRes = await fetch(
|
const { data: valueChainRes } = await axios.get(
|
||||||
`${API_BASE_URL}/api/company/value-chain-analysis/${stockCode}`
|
`/api/company/value-chain-analysis/${stockCode}`
|
||||||
).then((r) => r.json());
|
);
|
||||||
if (currentStockCodeRef.current === stockCode) {
|
if (currentStockCodeRef.current === stockCode) {
|
||||||
if (valueChainRes.success) setValueChainData(valueChainRes.data);
|
if (valueChainRes.success) setValueChainData(valueChainRes.data);
|
||||||
loadedApisRef.current.valueChain = true;
|
loadedApisRef.current.valueChain = true;
|
||||||
@@ -108,9 +106,9 @@ const DeepAnalysis = ({ stockCode }) => {
|
|||||||
|
|
||||||
case "keyFactors":
|
case "keyFactors":
|
||||||
setKeyFactorsLoading(true);
|
setKeyFactorsLoading(true);
|
||||||
const keyFactorsRes = await fetch(
|
const { data: keyFactorsRes } = await axios.get(
|
||||||
`${API_BASE_URL}/api/company/key-factors-timeline/${stockCode}`
|
`/api/company/key-factors-timeline/${stockCode}`
|
||||||
).then((r) => r.json());
|
);
|
||||||
if (currentStockCodeRef.current === stockCode) {
|
if (currentStockCodeRef.current === stockCode) {
|
||||||
if (keyFactorsRes.success) setKeyFactorsData(keyFactorsRes.data);
|
if (keyFactorsRes.success) setKeyFactorsData(keyFactorsRes.data);
|
||||||
loadedApisRef.current.keyFactors = true;
|
loadedApisRef.current.keyFactors = true;
|
||||||
@@ -119,9 +117,9 @@ const DeepAnalysis = ({ stockCode }) => {
|
|||||||
|
|
||||||
case "industryRank":
|
case "industryRank":
|
||||||
setIndustryRankLoading(true);
|
setIndustryRankLoading(true);
|
||||||
const industryRankRes = await fetch(
|
const { data: industryRankRes } = await axios.get(
|
||||||
`${API_BASE_URL}/api/financial/industry-rank/${stockCode}`
|
`/api/financial/industry-rank/${stockCode}`
|
||||||
).then((r) => r.json());
|
);
|
||||||
if (currentStockCodeRef.current === stockCode) {
|
if (currentStockCodeRef.current === stockCode) {
|
||||||
if (industryRankRes.success) setIndustryRankData(industryRankRes.data);
|
if (industryRankRes.success) setIndustryRankData(industryRankRes.data);
|
||||||
loadedApisRef.current.industryRank = true;
|
loadedApisRef.current.industryRank = true;
|
||||||
|
|||||||
@@ -12,9 +12,7 @@ import {
|
|||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { Tag } from 'antd';
|
import { Tag } from 'antd';
|
||||||
import { logger } from '@utils/logger';
|
import { logger } from '@utils/logger';
|
||||||
import { getApiBase } from '@utils/apiConfig';
|
import axios from '@utils/axiosConfig';
|
||||||
|
|
||||||
const API_BASE_URL = getApiBase();
|
|
||||||
|
|
||||||
// 黑金主题
|
// 黑金主题
|
||||||
const THEME = {
|
const THEME = {
|
||||||
@@ -53,10 +51,9 @@ const ForecastPanel = ({ stockCode }) => {
|
|||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const { data: result } = await axios.get(
|
||||||
`${API_BASE_URL}/api/stock/${stockCode}/forecast`
|
`/api/stock/${stockCode}/forecast`
|
||||||
);
|
);
|
||||||
const result = await response.json();
|
|
||||||
if (result.success && result.data) {
|
if (result.success && result.data) {
|
||||||
setForecast(result.data);
|
setForecast(result.data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,9 @@
|
|||||||
|
|
||||||
import React, { useState, useEffect, useCallback } from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
import { logger } from '@utils/logger';
|
import { logger } from '@utils/logger';
|
||||||
import { getApiBase } from '@utils/apiConfig';
|
import axios from '@utils/axiosConfig';
|
||||||
import NewsEventsTab from '../../CompanyOverview/NewsEventsTab';
|
import NewsEventsTab from '../../CompanyOverview/NewsEventsTab';
|
||||||
|
|
||||||
const API_BASE_URL = getApiBase();
|
|
||||||
|
|
||||||
const NewsPanel = ({ stockCode }) => {
|
const NewsPanel = ({ stockCode }) => {
|
||||||
const [newsEvents, setNewsEvents] = useState([]);
|
const [newsEvents, setNewsEvents] = useState([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -25,10 +23,9 @@ const NewsPanel = ({ stockCode }) => {
|
|||||||
// 获取股票名称
|
// 获取股票名称
|
||||||
const fetchStockName = useCallback(async () => {
|
const fetchStockName = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const { data: result } = await axios.get(
|
||||||
`${API_BASE_URL}/api/stock/${stockCode}/basic-info`
|
`/api/stock/${stockCode}/basic-info`
|
||||||
);
|
);
|
||||||
const result = await response.json();
|
|
||||||
if (result.success && result.data) {
|
if (result.success && result.data) {
|
||||||
const name = result.data.SECNAME || result.data.ORGNAME || stockCode;
|
const name = result.data.SECNAME || result.data.ORGNAME || stockCode;
|
||||||
setStockName(name);
|
setStockName(name);
|
||||||
@@ -47,10 +44,9 @@ const NewsPanel = ({ stockCode }) => {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const searchTerm = query || stockName || stockCode;
|
const searchTerm = query || stockName || stockCode;
|
||||||
const response = await fetch(
|
const { data: result } = await axios.get(
|
||||||
`${API_BASE_URL}/api/events?q=${encodeURIComponent(searchTerm)}&page=${page}&per_page=10`
|
`/api/events?q=${encodeURIComponent(searchTerm)}&page=${page}&per_page=10`
|
||||||
);
|
);
|
||||||
const result = await response.json();
|
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
setNewsEvents(result.data || []);
|
setNewsEvents(result.data || []);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// src/views/Company/components/MarketDataView/services/marketService.ts
|
// src/views/Company/components/MarketDataView/services/marketService.ts
|
||||||
// MarketDataView API 服务层
|
// MarketDataView API 服务层
|
||||||
|
|
||||||
import { getApiBase } from '@utils/apiConfig';
|
import axios from '@utils/axiosConfig';
|
||||||
import { logger } from '@utils/logger';
|
import { logger } from '@utils/logger';
|
||||||
import type {
|
import type {
|
||||||
MarketSummary,
|
MarketSummary,
|
||||||
@@ -23,21 +23,13 @@ interface ApiResponse<T> {
|
|||||||
message?: string;
|
message?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* API 基础 URL
|
|
||||||
*/
|
|
||||||
const getBaseUrl = (): string => getApiBase();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用 API 请求函数
|
* 通用 API 请求函数
|
||||||
*/
|
*/
|
||||||
const apiRequest = async <T>(url: string): Promise<ApiResponse<T>> => {
|
const apiRequest = async <T>(url: string): Promise<ApiResponse<T>> => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${getBaseUrl()}${url}`);
|
const { data } = await axios.get<ApiResponse<T>>(url);
|
||||||
if (!response.ok) {
|
return data;
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('marketService', 'apiRequest', error, { url });
|
logger.error('marketService', 'apiRequest', error, { url });
|
||||||
throw error;
|
throw error;
|
||||||
@@ -80,11 +72,8 @@ export const marketService = {
|
|||||||
* @param days 天数,默认 30 天
|
* @param days 天数,默认 30 天
|
||||||
*/
|
*/
|
||||||
async getBigDealData(stockCode: string, days: number = 30): Promise<BigDealData> {
|
async getBigDealData(stockCode: string, days: number = 30): Promise<BigDealData> {
|
||||||
const response = await fetch(`${getBaseUrl()}/api/market/bigdeal/${stockCode}?days=${days}`);
|
const { data } = await axios.get<BigDealData>(`/api/market/bigdeal/${stockCode}?days=${days}`);
|
||||||
if (!response.ok) {
|
return data;
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -93,11 +82,8 @@ export const marketService = {
|
|||||||
* @param days 天数,默认 30 天
|
* @param days 天数,默认 30 天
|
||||||
*/
|
*/
|
||||||
async getUnusualData(stockCode: string, days: number = 30): Promise<UnusualData> {
|
async getUnusualData(stockCode: string, days: number = 30): Promise<UnusualData> {
|
||||||
const response = await fetch(`${getBaseUrl()}/api/market/unusual/${stockCode}?days=${days}`);
|
const { data } = await axios.get<UnusualData>(`/api/market/unusual/${stockCode}?days=${days}`);
|
||||||
if (!response.ok) {
|
return data;
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,18 +118,8 @@ export const marketService = {
|
|||||||
*/
|
*/
|
||||||
async getMinuteData(stockCode: string): Promise<MinuteData> {
|
async getMinuteData(stockCode: string): Promise<MinuteData> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${getBaseUrl()}/api/stock/${stockCode}/latest-minute`, {
|
const { data } = await axios.get<MinuteData>(`/api/stock/${stockCode}/latest-minute`);
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('Failed to fetch minute data');
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
if (data.data && Array.isArray(data.data)) {
|
if (data.data && Array.isArray(data.data)) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,10 @@
|
|||||||
import { useState, useEffect, useCallback } from 'react';
|
import { useState, useEffect, useCallback } from 'react';
|
||||||
import { stockService } from '@services/eventService';
|
import { stockService } from '@services/eventService';
|
||||||
import { logger } from '@utils/logger';
|
import { logger } from '@utils/logger';
|
||||||
import { getApiBase } from '@utils/apiConfig';
|
import axios from '@utils/axiosConfig';
|
||||||
import type { StockQuoteCardData } from '../types';
|
import type { StockQuoteCardData } from '../types';
|
||||||
import type { BasicInfo } from '../../CompanyOverview/types';
|
import type { BasicInfo } from '../../CompanyOverview/types';
|
||||||
|
|
||||||
const API_BASE_URL = getApiBase();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 API 响应数据转换为 StockQuoteCard 所需格式
|
* 将 API 响应数据转换为 StockQuoteCard 所需格式
|
||||||
*/
|
*/
|
||||||
@@ -114,8 +112,7 @@ export const useStockQuoteData = (stockCode?: string): UseStockQuoteDataResult =
|
|||||||
setBasicLoading(true);
|
setBasicLoading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/stock/${stockCode}/basic-info`);
|
const { data: result } = await axios.get(`/api/stock/${stockCode}/basic-info`);
|
||||||
const result = await response.json();
|
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
setBasicInfo(result.data);
|
setBasicInfo(result.data);
|
||||||
|
|||||||
Reference in New Issue
Block a user