加速活動看板時段載入
All checks were successful
CD Pipeline / deploy (push) Successful in 57s

This commit is contained in:
OoO
2026-05-13 11:00:44 +08:00
parent 89c400d53e
commit d410677e5e
3 changed files with 40 additions and 29 deletions

View File

@@ -62,7 +62,7 @@ def load_scheduler_stats():
return {}
def _build_promo_dashboard_data(session, page_type, page_name, sort_by, order):
def _build_promo_dashboard_data(session, page_type, page_name, sort_by, order, requested_slot=None):
"""
通用的促銷儀表板數據建構函數
用於 edm 和 festival 兩種頁面類型
@@ -135,20 +135,23 @@ def _build_promo_dashboard_data(session, page_type, page_name, sort_by, order):
return f"{current_slot_hour:02d}:00"
active_tab = get_current_time_slot()
if requested_slot in sorted_grouped_items:
active_tab = requested_slot
if active_tab not in sorted_grouped_items and sorted_grouped_items:
active_tab = next(iter(sorted_grouped_items))
# 7. 計算在架天數與總銷量
all_icodes_in_batch = [item.i_code for item in items_in_batch]
# 7. 僅為首屏目前時段補齊列級資訊;其他時段以連結切換後再載入。
visible_items = sorted_grouped_items.get(active_tab, [])
visible_icodes = [item.i_code for item in visible_items]
product_categories = {}
days_on_shelf_map = {}
total_sold_map = {}
history_map = {}
if all_icodes_in_batch:
if visible_icodes:
# 從主商品表查詢分類
main_products = session.query(Product.i_code, Product.category).filter(
Product.i_code.in_(all_icodes_in_batch)
Product.i_code.in_(visible_icodes)
).all()
product_categories = {p.i_code: p.category for p in main_products}
@@ -159,7 +162,7 @@ def _build_promo_dashboard_data(session, page_type, page_name, sort_by, order):
PromoProduct.i_code,
func.count(func.distinct(func.date(PromoProduct.crawled_at)))
).filter(
PromoProduct.i_code.in_(all_icodes_in_batch),
PromoProduct.i_code.in_(visible_icodes),
PromoProduct.page_type == page_type
).group_by(PromoProduct.i_code).all()
else:
@@ -168,7 +171,7 @@ def _build_promo_dashboard_data(session, page_type, page_name, sort_by, order):
PromoProduct.i_code,
func.count(func.distinct(func.strftime('%Y-%m-%d', PromoProduct.crawled_at)))
).filter(
PromoProduct.i_code.in_(all_icodes_in_batch),
PromoProduct.i_code.in_(visible_icodes),
PromoProduct.page_type == page_type
).group_by(PromoProduct.i_code).all()
days_on_shelf_map = {r[0]: r[1] for r in days_on_shelf_q}
@@ -180,7 +183,7 @@ def _build_promo_dashboard_data(session, page_type, page_name, sort_by, order):
PromoProduct.i_code,
func.min(PromoProduct.id).label('min_id')
).filter(
PromoProduct.i_code.in_(all_icodes_in_batch),
PromoProduct.i_code.in_(visible_icodes),
PromoProduct.remain_qty.isnot(None),
PromoProduct.page_type == 'edm'
).group_by(PromoProduct.i_code).subquery()
@@ -190,7 +193,7 @@ def _build_promo_dashboard_data(session, page_type, page_name, sort_by, order):
).join(first_qty_subq, PromoProduct.id == first_qty_subq.c.min_id).all()
first_qty_map = {r[0]: r[1] for r in first_qty_records}
for item in items_in_batch:
for item in visible_items:
if item.i_code in first_qty_map and item.remain_qty is not None:
initial_qty = first_qty_map[item.i_code]
current_qty = item.remain_qty
@@ -204,7 +207,7 @@ def _build_promo_dashboard_data(session, page_type, page_name, sort_by, order):
PromoProduct.remain_qty,
PromoProduct.crawled_at
).filter(
PromoProduct.i_code.in_(all_icodes_in_batch),
PromoProduct.i_code.in_(visible_icodes),
PromoProduct.crawled_at >= today_start
).order_by(PromoProduct.crawled_at).all()
@@ -216,8 +219,8 @@ def _build_promo_dashboard_data(session, page_type, page_name, sort_by, order):
if not history_map[key] or (history_map[key] and history_map[key][-1]['qty'] != rec.remain_qty):
history_map[key].append({'time': rec.crawled_at.strftime('%H:%M'), 'qty': rec.remain_qty})
# 8. 附加分類資訊到每個 item
for item in items_in_batch:
# 8. 附加分類資訊到首屏可見 item
for item in visible_items:
item.safe_product_url = normalize_momo_product_url(item.url, item.i_code) or build_momo_product_url(item.i_code)
item.main_category = product_categories.get(item.i_code)
if item.main_category:
@@ -226,9 +229,11 @@ def _build_promo_dashboard_data(session, page_type, page_name, sort_by, order):
item.total_sold = total_sold_map.get(item.i_code, 0)
item.qty_history = history_map.get((item.i_code, item.time_slot), [])
# 9. 排序邏輯
# 9. 排序邏輯:首屏只需要排序目前時段
reverse = (order == 'desc')
for time_slot in sorted_grouped_items:
for time_slot in [active_tab]:
if time_slot not in sorted_grouped_items:
continue
if sort_by == 'name':
sorted_grouped_items[time_slot].sort(key=lambda x: x.name or '', reverse=reverse)
elif sort_by == 'remain_qty':
@@ -307,9 +312,10 @@ def edm_dashboard():
sort_by = request.args.get('sort_by', 'default')
order = request.args.get('order', 'desc')
requested_slot = request.args.get('slot')
try:
data = _build_promo_dashboard_data(session, 'edm', '限時搶購', sort_by, order)
data = _build_promo_dashboard_data(session, 'edm', '限時搶購', sort_by, order, requested_slot)
# 建立儀表板頁籤
promo_pages = [
@@ -362,9 +368,10 @@ def festival_dashboard():
sort_by = request.args.get('sort_by', 'default')
order = request.args.get('order', 'desc')
requested_slot = request.args.get('slot')
try:
data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order)
data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order, requested_slot)
# 建立儀表板頁籤
promo_pages = [
@@ -414,9 +421,10 @@ def mothers_day_dashboard():
sort_by = request.args.get('sort_by', 'default')
order = request.args.get('order', 'desc')
requested_slot = request.args.get('slot')
try:
data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order)
data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order, requested_slot)
# 建立儀表板頁籤
promo_pages = [
@@ -466,9 +474,10 @@ def valentine_520_dashboard():
sort_by = request.args.get('sort_by', 'default')
order = request.args.get('order', 'desc')
requested_slot = request.args.get('slot')
try:
data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order)
data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order, requested_slot)
# 建立儀表板頁籤
promo_pages = [
@@ -518,9 +527,10 @@ def labor_day_dashboard():
sort_by = request.args.get('sort_by', 'default')
order = request.args.get('order', 'desc')
requested_slot = request.args.get('slot')
try:
data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order)
data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order, requested_slot)
# 建立儀表板頁籤
promo_pages = [