update pay ui

This commit is contained in:
2025-12-02 19:44:46 +08:00
parent 642de62566
commit 4ba6fd34ff
4 changed files with 16 additions and 42 deletions

15
app.py
View File

@@ -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, {

View File

@@ -187,12 +187,13 @@ const StockListItem = ({
{onWatchlistToggle && (
<IconButton
size="xs"
variant={isInWatchlist ? 'solid' : 'ghost'}
variant={isInWatchlist ? 'solid' : 'outline'}
colorScheme={isInWatchlist ? 'yellow' : 'gray'}
icon={<StarIcon />}
icon={<StarIcon color={isInWatchlist ? undefined : 'gray.400'} />}
onClick={handleWatchlistClick}
aria-label={isInWatchlist ? '已关注' : '加自选'}
borderRadius="full"
borderColor={isInWatchlist ? undefined : 'gray.300'}
/>
)}
</HStack>

View File

@@ -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);

View File

@@ -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<void> => {
console.log('[InvestmentPlanningCenter] 📡 loadAllData 被调用', new Date().toISOString());
try {
setLoading(true);
const base = getApiBase();