Selaa lähdekoodia

空状态文案精简为'暂无数据' + look 仅 apps/api 变更才重启

tianyu.chu 1 kuukausi sitten
vanhempi
commit
f48b99163c

+ 4 - 2
CHANGELOG.md

@@ -5,9 +5,11 @@
 ## 2026-06-29
 
 ### 变更
-- **单日默认改回「昨日」**(`apps/web`):去掉 06-26 引入的"最新可用日"默认(原为省略 `snapshot_dt` → 后端取 `MAX(dt)`)。改回默认查昨日并发 `snapshot_dt`;昨日无数据就如实显示「数据缺失」——**空就空,是上游问题,不在应用侧兜底**。
+- **单日默认改回「昨日」**(`apps/web`):去掉 06-26 引入的"最新可用日"默认(原为省略 `snapshot_dt` → 后端取 `MAX(dt)`)。改回默认查昨日并发 `snapshot_dt`;昨日无数据就如实显示空状态——**空就空,是上游问题,不在应用侧兜底**。
   - 起因:上游 daily 跑批从 6/27 起写入全 0 行,`MAX(dt)` 落到空行 → 默认显示 0000。
-  - `TimePeriodSelect` 去掉「最新」文案与「最新可用日」快捷项,单日按钮直接显示所选日期(默认昨日);日历仍可选历史。
+  - `TimePeriodSelect` 去掉「单日」字样与「最新/最新可用日」,按钮直接显示所选日期(默认昨日);日历仍可选历史。
+- **空状态文案精简**(`apps/web`):漏斗 / 趋势空状态由「数据缺失:所选周期暂无产出数据,未做补零处理。」→ **「暂无数据」**(去掉与状态重复的解释 + "补零"内部口径)。
+- **`look.sh` 部署不再误重启后端**(`infra`):仅当 `apps/api` 真有变更才重启 uvicorn(纯前端改动 uvicorn 实时读盘);重启改为 `pkill -9` + 等端口释放 + `setsid nohup` 直接拉起(不走 serve 脚本的 pgrep 守卫,消除将死进程竞态导致的部署掉站)。
 
 ## 2026-06-26
 

+ 1 - 3
apps/web/src/modules/funnel/TrendView.tsx

@@ -121,9 +121,7 @@ export function TrendView() {
         <Card>
           <CardContent className="flex flex-col items-center justify-center gap-3 py-12 text-center">
             <Inbox className="size-10 text-muted-foreground/60" />
-            <p className="text-sm text-muted-foreground m-0">
-              数据缺失:所选范围暂无产出数据,未做补零处理。
-            </p>
+            <p className="text-sm text-muted-foreground m-0">暂无数据</p>
           </CardContent>
         </Card>
       ) : (

+ 2 - 2
apps/web/src/modules/funnel/__tests__/FunnelPage.test.tsx

@@ -255,7 +255,7 @@ describe('FunnelPage — fixed funnel + period selection', () => {
     });
   });
 
-  it('missing data_status renders 数据缺失 without zero-fill', async () => {
+  it('missing data_status renders 暂无数据 without zero-fill', async () => {
     queryFunnelMock.mockResolvedValue({
       period: 'last_7d',
       snapshot_dt: null,
@@ -264,7 +264,7 @@ describe('FunnelPage — fixed funnel + period selection', () => {
     });
     renderPage();
     await waitFor(() =>
-      expect(screen.getByText(/数据缺失/)).toBeInTheDocument(),
+      expect(screen.getByText(/暂无数据/)).toBeInTheDocument(),
     );
     expect(screen.queryByTestId('funnel-chart')).not.toBeInTheDocument();
   });

+ 2 - 2
apps/web/src/modules/funnel/__tests__/FunnelResult.test.tsx

@@ -59,12 +59,12 @@ describe('FunnelResult states', () => {
     expect(screen.getByText('82.00%')).toBeInTheDocument();
   });
 
-  it('missing: explicit 数据缺失 empty state, no zeros / no chart', () => {
+  it('missing: explicit 暂无数据 empty state, no zeros / no chart', () => {
     renderResult({
       ...baseProps,
       data: { ...readyData, results: [], data_status: 'missing' },
     });
-    expect(screen.getByText(/数据缺失/)).toBeInTheDocument();
+    expect(screen.getByText(/暂无数据/)).toBeInTheDocument();
     expect(screen.queryByTestId('funnel-chart')).not.toBeInTheDocument();
     expect(screen.queryByText('0')).not.toBeInTheDocument();
   });

+ 2 - 2
apps/web/src/modules/funnel/__tests__/TrendView.test.tsx

@@ -91,7 +91,7 @@ describe('TrendView — 按日折线', () => {
     ).toBeInTheDocument();
   });
 
-  it('missing renders 数据缺失 without charts', async () => {
+  it('missing renders 暂无数据 without charts', async () => {
     trendMock.mockResolvedValue({
       start_dt: null,
       end_dt: null,
@@ -99,7 +99,7 @@ describe('TrendView — 按日折线', () => {
       points: [],
     });
     renderEl(<TrendView />);
-    await waitFor(() => expect(screen.getByText(/数据缺失/)).toBeInTheDocument());
+    await waitFor(() => expect(screen.getByText(/暂无数据/)).toBeInTheDocument());
     expect(screen.queryByTestId('trend-chart-uv')).not.toBeInTheDocument();
   });
 

+ 1 - 3
apps/web/src/modules/funnel/components/FunnelResult.tsx

@@ -71,9 +71,7 @@ export function FunnelResult({
       <Card>
         <CardContent className="flex flex-col items-center justify-center gap-3 py-12 text-center">
           <Inbox className="size-10 text-muted-foreground/60" />
-          <p className="text-sm text-muted-foreground m-0">
-            数据缺失:所选周期暂无产出数据,未做补零处理。
-          </p>
+          <p className="text-sm text-muted-foreground m-0">暂无数据</p>
         </CardContent>
       </Card>
     );

+ 10 - 6
infra/look.sh

@@ -42,14 +42,18 @@ echo "==> 4/5 服务器拉取(git pull,非 scp)+ 后端按需重启"
 ssh -o BatchMode=yes "$SERVER" '
   cd $HOME/hs-data && GIT_TERMINAL_PROMPT=0 git pull -q
   cd $HOME/hs-api && before=$(git rev-parse HEAD) && GIT_TERMINAL_PROMPT=0 git pull -q && after=$(git rev-parse HEAD)
-  if [ "$before" != "$after" ]; then
-    echo "后端有更新 → 重启 uvicorn"
-    pkill -f "uvicorn app.main:app" || true
-    # 等优雅退出彻底结束(避免 serve 脚本看到将死进程而误判在跑),再补 SIGKILL。
-    for i in $(seq 1 20); do pgrep -f "uvicorn app.main:app" >/dev/null || break; sleep 0.5; done
+  # 仅当 apps/api 真的变了才重启(纯前端改动 uvicorn 实时读盘,不动它=不抖、不掉)。
+  if git diff --name-only "$before" "$after" | grep -q "^apps/api/"; then
+    echo "后端代码有更新 → 重启 uvicorn"
     pkill -9 -f "uvicorn app.main:app" 2>/dev/null || true
+    for i in $(seq 1 20); do ss -ltn 2>/dev/null | grep -q :8080 || break; sleep 0.5; done
+    cd $HOME/hs-api/apps/api
+    STATIC_DIR=$HOME/hs-data setsid nohup $HOME/miniconda3/bin/python -m uvicorn app.main:app \
+      --host 0.0.0.0 --port 8080 >$HOME/hs-api.log 2>&1 </dev/null &
+    sleep 3   # 让 setsid 在 ssh 关闭前完成 fork/exec,进程随后脱离会话存活
+  else
+    bash $HOME/serve-hs-api.sh   # 未在跑则冷启动拉起;在跑则幂等退出
   fi
-  bash $HOME/serve-hs-api.sh
   echo pulled-ok
 '