update pay ui
This commit is contained in:
15
app.py
15
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, {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user