Files
ewoooc/docker/superset/IMPLEMENTATION_GUIDE.md
OoO d6d8777e41
All checks were successful
CD Pipeline / deploy (push) Successful in 1m12s
V10.601 收斂 Gemini 與密鑰治理
2026-06-06 14:52:46 +08:00

467 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Superset 功能實作指南
> 本指南詳細說明如何在 Superset 中複製現有頁面的分析功能
> 建立日期: 2026-02-08
---
## 存取資訊
| 項目 | 值 |
|------|-----|
| URL | https://monitor.wooo.work/superset/ |
| 帳號 | admin |
| 密碼 | <SUPERSET_ADMIN_PASSWORD> |
| 資料庫 | MOMO_UAT |
---
## 已建立的資料集
| 資料集 | 資料表 | 用途 |
|--------|--------|------|
| daily_sales_snapshot | public.daily_sales_snapshot | 當日業績 |
| realtime_sales_monthly | public.realtime_sales_monthly | 銷售分析、成長分析 |
| monthly_summary_analysis | public.monthly_summary_analysis | 月度總結 |
| products | public.products | 商品資料、ABC 分析 |
| price_records | public.price_records | 價格趨勢 |
---
## 第一部分:當日業績 (Daily Sales)
**對應頁面**: `/daily_sales`
### 1.1 SQL Lab 建立虛擬資料集
在 SQL Lab 執行以下查詢,然後儲存為資料集:
```sql
-- 資料集名稱: daily_sales_kpi
-- 用途: 每日 KPI 彙總
SELECT
snapshot_date,
DATE_TRUNC('month', snapshot_date) as month,
EXTRACT(DOW FROM snapshot_date) as day_of_week,
COUNT(DISTINCT "商品代碼") as sku_count,
SUM("銷售金額") as total_revenue,
SUM("總成本") as total_cost,
SUM("銷售金額") - SUM("總成本") as gross_margin,
SUM("銷售數量") as total_qty,
CASE
WHEN SUM("銷售金額") > 0
THEN (SUM("銷售金額") - SUM("總成本")) / SUM("銷售金額") * 100
ELSE 0
END as margin_rate,
CASE
WHEN SUM("銷售數量") > 0
THEN SUM("銷售金額") / SUM("銷售數量")
ELSE 0
END as avg_price
FROM daily_sales_snapshot
GROUP BY snapshot_date
ORDER BY snapshot_date DESC
```
### 1.2 建議圖表
| 圖表名稱 | 類型 | 說明 |
|----------|------|------|
| 當日業績 Big Number | Big Number with Trendline | 顯示最新日期的 total_revenue |
| 當日毛利 Big Number | Big Number with Trendline | 顯示最新日期的 gross_margin |
| 30 天業績趨勢 | Line Chart | X軸: snapshot_date, Y軸: total_revenue |
| DoD 比較 | Bar Chart | 比較今日與昨日 |
| WoW 比較 | Bar Chart | 比較今日與上週同日 |
| 分類業績圓餅圖 | Pie Chart | 依商品分類分組 |
| 日曆熱力圖 | Calendar Heatmap | 每日業績視覺化 |
### 1.3 建立步驟
1. **SQL Lab** → 執行上述 SQL
2. 點擊 **Save****Save Dataset**
3. 命名為 `daily_sales_kpi`
4. 前往 **Charts****+ Chart**
5. 選擇 `daily_sales_kpi` 資料集
6. 依序建立各圖表
---
## 第二部分:銷售分析 (Sales Analysis)
**對應頁面**: `/sales_analysis`
### 2.1 SQL Lab 建立虛擬資料集
```sql
-- 資料集名稱: sales_analysis_detail
-- 用途: 銷售明細分析
SELECT
"日期" as order_date,
"商品名稱" as product_name,
"商品代碼" as product_code,
"館別" as category,
"品牌" as brand,
"廠商名稱" as vendor,
"總業績" as amount,
"總成本" as cost,
"總業績" - "總成本" as profit,
"銷量" as qty,
CASE
WHEN "總業績" > 0
THEN ("總業績" - "總成本") / "總業績" * 100
ELSE 0
END as margin_rate,
EXTRACT(DOW FROM "日期"::date) as day_of_week,
EXTRACT(HOUR FROM "訂單時間"::time) as order_hour,
DATE_TRUNC('month', "日期"::date) as month,
DATE_TRUNC('week', "日期"::date) as week
FROM realtime_sales_monthly
WHERE "日期" IS NOT NULL
```
### 2.2 建議圖表
| 圖表名稱 | 類型 | 設定 |
|----------|------|------|
| 總業績 KPI | Big Number | SUM(amount) |
| 總毛利 KPI | Big Number | SUM(profit) |
| 毛利率 KPI | Big Number | AVG(margin_rate) |
| 業績 TOP 20 商品 | Bar Chart (Horizontal) | GROUP BY product_name, ORDER BY SUM(amount) DESC LIMIT 20 |
| 分類業績分佈 | Pie Chart | GROUP BY category |
| 品牌業績排行 | Bar Chart | GROUP BY brand |
| 廠商業績排行 | Bar Chart | GROUP BY vendor |
| 星期銷售熱力圖 | Heatmap | X: day_of_week, Y: order_hour, Value: SUM(amount) |
| 月度趨勢 | Line Chart | X: month, Y: SUM(amount) |
| 週趨勢 | Line Chart | X: week, Y: SUM(amount) |
| 價格區間分佈 | Histogram | amount 分佈 |
| BCG 矩陣 | Scatter Plot | X: SUM(qty), Y: margin_rate, Size: SUM(amount) |
| 樹狀圖 | Treemap | 分類 → 品牌 階層 |
### 2.3 篩選器設定
建立以下 Filter Box:
- 日期範圍 (order_date)
- 分類 (category)
- 品牌 (brand)
- 廠商 (vendor)
- 星期 (day_of_week)
- 時段 (order_hour)
---
## 第三部分:成長分析 (Growth Analysis)
**對應頁面**: `/growth_analysis`
### 3.1 SQL Lab 建立虛擬資料集
```sql
-- 資料集名稱: growth_analysis_monthly
-- 用途: 月度成長分析 (MoM, YoY, AOV)
WITH monthly_data AS (
SELECT
DATE_TRUNC('month', "日期"::date) as month,
SUM("總業績") as revenue,
SUM("總成本") as cost,
SUM("總業績") - SUM("總成本") as profit,
COUNT(DISTINCT "訂單編號") as orders
FROM realtime_sales_monthly
WHERE "日期" IS NOT NULL
GROUP BY DATE_TRUNC('month', "日期"::date)
),
with_growth AS (
SELECT
month,
revenue,
profit,
orders,
revenue / NULLIF(orders, 0) as aov,
profit / NULLIF(revenue, 0) * 100 as margin_rate,
-- MoM (月增率)
(revenue - LAG(revenue) OVER (ORDER BY month)) /
NULLIF(LAG(revenue) OVER (ORDER BY month), 0) * 100 as mom,
-- YoY (年增率)
(revenue - LAG(revenue, 12) OVER (ORDER BY month)) /
NULLIF(LAG(revenue, 12) OVER (ORDER BY month), 0) * 100 as yoy
FROM monthly_data
)
SELECT
month,
revenue,
profit,
orders,
ROUND(aov::numeric, 0) as aov,
ROUND(margin_rate::numeric, 1) as margin_rate,
COALESCE(ROUND(mom::numeric, 2), 0) as mom,
COALESCE(ROUND(yoy::numeric, 2), 0) as yoy
FROM with_growth
ORDER BY month DESC
```
### 3.2 建議圖表
| 圖表名稱 | 類型 | 說明 |
|----------|------|------|
| YTD 業績 | Big Number | 今年累計業績 |
| YTD 成長率 | Big Number | 與去年同期比較 |
| 近 30 天客單價 | Big Number | 最近客單價 |
| 月度業績趨勢 | Line Chart | X: month, Y: revenue |
| 月度毛利趨勢 | Line Chart | X: month, Y: profit |
| MoM 月增率 | Bar Chart | X: month, Y: mom (紅/綠顏色區分正負) |
| YoY 年增率 | Bar Chart | X: month, Y: yoy |
| 客單價趨勢 | Line Chart | X: month, Y: aov |
| 毛利率趨勢 | Line Chart | X: month, Y: margin_rate |
| 綜合指標雙軸圖 | Mixed Chart | 左軸: revenue, 右軸: margin_rate |
---
## 第四部分:月度總結 (Monthly Summary)
**對應頁面**: `/monthly_summary_analysis`
### 4.1 使用現有資料集
直接使用 `monthly_summary_analysis` 資料集。
### 4.2 建議圖表
| 圖表名稱 | 類型 | 說明 |
|----------|------|------|
| 本月業績 | Big Number | 最新月份的業績 |
| 月度業績比較 | Bar Chart | 12 個月業績對比 |
| 月環比 | Line Chart | MoM 變化 |
| 月度彙總表 | Pivot Table | 月份 x 各項指標 |
| 季度彙總 | Bar Chart | 依季度分組 |
---
## 第五部分ABC 分析
**對應頁面**: `/abc_analysis/detail`
### 5.1 SQL Lab 建立虛擬資料集
```sql
-- 資料集名稱: abc_analysis
-- 用途: 商品 ABC 分類
WITH product_sales AS (
SELECT
p.i_code,
p.name as product_name,
p.category,
COALESCE(SUM(d."銷售金額"), 0) as total_sales,
COALESCE(SUM(d."銷售數量"), 0) as total_qty
FROM products p
LEFT JOIN daily_sales_snapshot d ON p.i_code = d."商品代碼"
GROUP BY p.i_code, p.name, p.category
HAVING COALESCE(SUM(d."銷售金額"), 0) > 0
),
ranked AS (
SELECT
*,
SUM(total_sales) OVER (ORDER BY total_sales DESC) as cumulative_sales,
SUM(total_sales) OVER () as grand_total,
ROW_NUMBER() OVER (ORDER BY total_sales DESC) as rank
FROM product_sales
)
SELECT
i_code,
product_name,
category,
total_sales,
total_qty,
cumulative_sales,
grand_total,
rank,
cumulative_sales / grand_total * 100 as cumulative_pct,
CASE
WHEN cumulative_sales / grand_total <= 0.7 THEN 'A'
WHEN cumulative_sales / grand_total <= 0.9 THEN 'B'
ELSE 'C'
END as abc_class
FROM ranked
ORDER BY rank
```
### 5.2 建議圖表
| 圖表名稱 | 類型 | 說明 |
|----------|------|------|
| ABC 分類圓餅圖 | Pie Chart | GROUP BY abc_class |
| ABC 分類商品數 | Bar Chart | COUNT BY abc_class |
| 帕累托曲線 | Dual Axis Line | 銷售額 + 累計百分比 |
| A 類商品列表 | Table | FILTER abc_class = 'A' |
| B 類商品列表 | Table | FILTER abc_class = 'B' |
| C 類商品列表 | Table | FILTER abc_class = 'C' |
| 分類 ABC 分佈 | Stacked Bar | X: category, Y: COUNT, Color: abc_class |
---
## 第六部分:價格趨勢
**對應頁面**: 商品看板價格歷史
### 6.1 使用現有資料集
直接使用 `price_records` 資料集。
### 6.2 建議圖表
| 圖表名稱 | 類型 | 說明 |
|----------|------|------|
| 價格歷史折線圖 | Line Chart | X: timestamp, Y: current_price, Filter: product_id |
| 今日價格變動 | Table | WHERE DATE(timestamp) = CURRENT_DATE |
| 漲價商品數 | Big Number | COUNT WHERE price_change > 0 |
| 降價商品數 | Big Number | COUNT WHERE price_change < 0 |
| 價格變動分佈 | Histogram | price_change_pct 分佈 |
---
## 儀表板建立順序
### 建議順序(由簡到繁)
1. **成長分析儀表板** - 圖表較少,資料結構簡單
2. **月度總結儀表板** - 使用現有資料集
3. **當日業績儀表板** - 需要 DoD/WoW 計算
4. **銷售分析儀表板** - 圖表最多,篩選器複雜
5. **ABC 分析儀表板** - 需要進階 SQL
6. **價格趨勢儀表板** - 需要時間序列處理
---
## 驗證對照表
每個儀表板建立完成後,請與現有頁面比對以下項目:
| 驗證項目 | 檢查點 |
|----------|--------|
| 數據一致性 | KPI 數值是否與現有頁面一致 |
| 圖表呈現 | 圖表類型是否適當呈現資料 |
| 篩選功能 | 篩選器是否正常運作 |
| 效能 | 載入時間是否可接受 |
| 互動性 | 點擊鑽取是否正常 |
---
## 常用 Superset 操作
### 建立圖表快速步驟
1. **Charts****+ Chart**
2. 選擇資料集
3. 選擇圖表類型
4. 設定 Metrics (指標) 和 Dimensions (維度)
5. 設定篩選條件
6. **Run Query** 預覽
7. **Save** 儲存
### 建立儀表板
1. **Dashboards****+ Dashboard**
2. 輸入名稱
3. **Edit Dashboard**
4. 從右側拖曳圖表
5. 調整佈局
6. 新增篩選器
7. **Save**
### 設定篩選器
1. 在儀表板編輯模式
2. 點擊 **+ Add filter**
3. 選擇欄位和類型
4. 設定影響的圖表
---
## 注意事項
1. **欄位名稱**: PostgreSQL 區分大小寫,中文欄位需用雙引號包起來
2. **日期格式**: 確保日期欄位正確轉換為 DATE 類型
3. **效能**: 大資料集建議加入時間篩選限制
4. **快取**: Superset 有快取機制,測試時可能需要清除快取
---
## 故障排除
### 頁面無限載入 (Infinite Loading)
**症狀**: 訪問 Superset 頁面時,畫面顯示無限載入中
**原因**: Superset Docker 映像 (3.1.0/3.1.1) 中的 `theme.5ab95322dc4a489d8e8f.entry.js` 檔案大小為 0 bytes (映像構建問題)
**解決方案**: 已在 docker-compose.yml 的啟動命令中自動修復:
```bash
echo '(function(){console.log("Theme loaded");})();' > /app/superset/static/assets/theme.5ab95322dc4a489d8e8f.entry.js
```
**手動修復** (如果需要):
```bash
docker exec momo-superset sh -c 'echo "(function(){console.log(\"Theme loaded\");})();" > /app/superset/static/assets/theme.5ab95322dc4a489d8e8f.entry.js'
```
### 子路徑 404 錯誤
**症狀**: 訪問 `/superset/` 返回 404
**原因**: Nginx 子路徑配置需要特別處理 URL 重寫
**解決方案**: 參考 `nginx-superset.conf` 配置,關鍵設定:
- `proxy_redirect / /superset/;` - 重寫重定向
- `sub_filter` - 重寫 HTML 中的靜態資源路徑
- `gzip off;` - 禁用 gzip 讓 sub_filter 生效
### 雙重前綴問題 (/superset/superset/) (2026-02-08 修復)
**症狀**:
- 訪問 `https://monitor.wooo.work/superset/` 被重定向到 `/superset/superset/welcome/`
- 頁面無限載入
**根本原因**:
Superset 內部 Flask blueprints 路由已經是 `/superset/...`(例如 `/superset/welcome/`)。
如果 Nginx 使用 `proxy_redirect / /superset/;`,會把 `/superset/welcome/` 再次加前綴變成 `/superset/superset/welcome/`
**解決方案**:
1. **superset_config.py** - 禁用 x_prefix:
```python
ENABLE_PROXY_FIX = True
PROXY_FIX_CONFIG = {
"x_for": 1,
"x_proto": 1,
"x_host": 1,
"x_prefix": 0, # 必須為 0
}
```
2. **Nginx 配置** - 智能 proxy_redirect:
```nginx
location /superset/ {
proxy_pass http://127.0.0.1:8088/;
# 關鍵:已是 /superset/ 開頭的路徑保持不變
proxy_redirect /superset/ /superset/;
# 其他路徑才添加 /superset/ 前綴
proxy_redirect ~^/(?!superset)(.*)$ /superset/$1;
# 只重寫 static 路徑
sub_filter '"/static/' '"/superset/static/';
sub_filter "'/static/" "'/superset/static/";
sub_filter_once off;
}
```
3. **驗證**:
```bash
# 應該返回 302 到 /superset/welcome/ (不是 /superset/superset/welcome/)
curl -sI https://monitor.wooo.work/superset/ | grep -i location
```