diff --git a/app.py b/app.py
index 45d2d7c1..29d70bdf 100755
--- a/app.py
+++ b/app.py
@@ -5913,11 +5913,12 @@ def get_stock_quotes():
# 使用 IN 子句一次查询所有股票,避免逐只循环查询
try:
# 批量查询价格和涨跌幅数据(使用窗口函数)
+ # 涨跌幅基于当日开盘价计算:(最新价 - 开盘价) / 开盘价 * 100
batch_price_query = """
- WITH first_prices AS (
+ WITH open_prices AS (
SELECT
code,
- close as first_price,
+ open as open_price,
ROW_NUMBER() OVER (PARTITION BY code ORDER BY timestamp ASC) as rn
FROM stock_minute
WHERE code IN %(codes)s
@@ -5935,12 +5936,12 @@ def get_stock_quotes():
AND timestamp <= %(end)s
)
SELECT
- fp.code,
+ op.code,
lp.last_price,
- (lp.last_price - fp.first_price) / fp.first_price * 100 as change_pct
- FROM first_prices fp
- INNER JOIN last_prices lp ON fp.code = lp.code
- WHERE fp.rn = 1 AND lp.rn = 1
+ (lp.last_price - op.open_price) / op.open_price * 100 as change_pct
+ FROM open_prices op
+ INNER JOIN last_prices lp ON op.code = lp.code
+ WHERE op.rn = 1 AND lp.rn = 1
"""
batch_data = client.execute(batch_price_query, {
diff --git a/src/views/Community/components/DynamicNewsDetail/StockListItem.js b/src/views/Community/components/DynamicNewsDetail/StockListItem.js
index b729342c..0188a3f5 100644
--- a/src/views/Community/components/DynamicNewsDetail/StockListItem.js
+++ b/src/views/Community/components/DynamicNewsDetail/StockListItem.js
@@ -187,12 +187,13 @@ const StockListItem = ({
{onWatchlistToggle && (
}
+ icon={}
onClick={handleWatchlistClick}
aria-label={isInWatchlist ? '已关注' : '加自选'}
borderRadius="full"
+ borderColor={isInWatchlist ? undefined : 'gray.300'}
/>
)}
diff --git a/src/views/Dashboard/Center.js b/src/views/Dashboard/Center.js
index 4a04ef5f..0ba315ec 100644
--- a/src/views/Dashboard/Center.js
+++ b/src/views/Dashboard/Center.js
@@ -64,11 +64,6 @@ import MyFutureEvents from './components/MyFutureEvents';
import InvestmentPlanningCenter from './components/InvestmentPlanningCenter';
export default function CenterDashboard() {
- // 🔍 性能调试:记录组件渲染
- const renderCountRef = React.useRef(0);
- renderCountRef.current += 1;
- console.log(`[Center] 🔄 渲染次数: ${renderCountRef.current}`, new Date().toISOString());
-
const { user } = useAuth();
const location = useLocation();
const navigate = useNavigate();
@@ -100,36 +95,19 @@ export default function CenterDashboard() {
const [quotesLoading, setQuotesLoading] = useState(false);
const loadData = useCallback(async () => {
- console.log('[Center] 📡 loadData 开始', new Date().toISOString());
try {
const base = getApiBase();
const ts = Date.now();
- console.log('[Center] 🌐 开始请求 API...', base);
+ const [w, e, c] = await Promise.all([
+ fetch(base + `/api/account/watchlist?_=${ts}`, { credentials: 'include', cache: 'no-store', headers: { 'Cache-Control': 'no-cache' } }),
+ fetch(base + `/api/account/events/following?_=${ts}`, { credentials: 'include', cache: 'no-store', headers: { 'Cache-Control': 'no-cache' } }),
+ fetch(base + `/api/account/events/posts?_=${ts}`, { credentials: 'include', cache: 'no-store', headers: { 'Cache-Control': 'no-cache' } }),
+ ]);
- // 分开请求,方便定位哪个 API 卡住
- console.time('[Center] API: watchlist');
- const w = await fetch(base + `/api/account/watchlist?_=${ts}`, { credentials: 'include', cache: 'no-store', headers: { 'Cache-Control': 'no-cache' } });
- console.timeEnd('[Center] API: watchlist');
- console.log('[Center] ✅ watchlist 响应状态:', w.status);
-
- console.time('[Center] API: events/following');
- const e = await fetch(base + `/api/account/events/following?_=${ts}`, { credentials: 'include', cache: 'no-store', headers: { 'Cache-Control': 'no-cache' } });
- console.timeEnd('[Center] API: events/following');
- console.log('[Center] ✅ events/following 响应状态:', e.status);
-
- console.time('[Center] API: events/posts');
- const c = await fetch(base + `/api/account/events/posts?_=${ts}`, { credentials: 'include', cache: 'no-store', headers: { 'Cache-Control': 'no-cache' } });
- console.timeEnd('[Center] API: events/posts');
- console.log('[Center] ✅ events/posts 响应状态:', c.status);
-
- console.log('[Center] 📥 开始解析 JSON...');
const jw = await w.json();
- console.log('[Center] ✅ watchlist JSON 解析完成');
const je = await e.json();
- console.log('[Center] ✅ events/following JSON 解析完成');
const jc = await c.json();
- console.log('[Center] ✅ events/posts JSON 解析完成');
if (jw.success) {
const watchlistData = Array.isArray(jw.data) ? jw.data : [];
setWatchlist(watchlistData);
diff --git a/src/views/Dashboard/components/InvestmentPlanningCenter.tsx b/src/views/Dashboard/components/InvestmentPlanningCenter.tsx
index cb580907..f6fcb756 100644
--- a/src/views/Dashboard/components/InvestmentPlanningCenter.tsx
+++ b/src/views/Dashboard/components/InvestmentPlanningCenter.tsx
@@ -70,11 +70,6 @@ const PanelLoadingFallback: React.FC = () => (
* InvestmentPlanningCenter 主组件
*/
const InvestmentPlanningCenter: React.FC = () => {
- // 🔍 性能调试
- const renderCountRef = React.useRef(0);
- renderCountRef.current += 1;
- console.log(`[InvestmentPlanningCenter] 🔄 渲染次数: ${renderCountRef.current}`, new Date().toISOString());
-
const toast = useToast();
// 颜色主题
@@ -93,7 +88,6 @@ const InvestmentPlanningCenter: React.FC = () => {
* 加载所有事件数据(日历事件 + 计划 + 复盘)
*/
const loadAllData = useCallback(async (): Promise => {
- console.log('[InvestmentPlanningCenter] 📡 loadAllData 被调用', new Date().toISOString());
try {
setLoading(true);
const base = getApiBase();