Files
ewoooc/tests/main_test.py
ogt 1b4f3a7bbe
Some checks failed
CD Pipeline / deploy (push) Failing after 59s
feat: EwoooC 初始化 — 完整專案推版至 Gitea
- 建立 Gitea Actions CD pipeline (.gitea/workflows/cd.yaml)
- 部署模式: rsync Python 檔案至 188 → docker restart (volume mount)
- Dockerfile/requirements 變動時自動重建 Docker image
- 部署通知: Telegram (開始/成功/失敗)
- 健康檢查: https://mo.wooo.work/health (最多 5 次重試)
- 同步最新 CLAUDE.md / ADR-008 / memory (2026-04-19)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 01:21:13 +08:00

124 lines
4.2 KiB
Python
Raw 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.
import os
from flask import Flask, render_template, session, redirect, url_for, send_from_directory
from database.manager import DatabaseManager
from auth import init_auth_routes, login_required
from config import SECRET_KEY, DATA_DIR, LOG_DIR, EXCEL_EXPORT_DIR
# --- 1. 初始化路徑與 Flask ---
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
TEMPLATE_DIR = os.path.join(BASE_DIR, 'web', 'templates')
STATIC_DIR = os.path.join(BASE_DIR, 'web', 'static')
app = Flask(__name__,
template_folder=TEMPLATE_DIR,
static_folder=STATIC_DIR)
app.secret_key = SECRET_KEY
# 初始化權限路由
init_auth_routes(app)
# 初始化資料庫管理員
db_mgr = DatabaseManager()
def get_db_size():
"""獲取資料庫實體檔案大小"""
db_path = os.path.join(DATA_DIR, 'momo_database.db')
if os.path.exists(db_path):
size_bytes = os.path.getsize(db_path)
return f"{size_bytes / (1024 * 1024):.2f} MB"
return "0.00 MB"
# --- 2. 路由定義 ---
@app.route('/')
@login_required
def dashboard():
"""主看板:包含統計數據與商品明細清單"""
stats = {
"total_products": 0,
"price_changes": 0,
"db_size": get_db_size()
}
recent_products = []
session_db = db_mgr.Session()
try:
from database.models import Product, PriceRecord
from datetime import datetime
from sqlalchemy import desc
# A. 計算統計數據
stats["total_products"] = session_db.query(Product).count()
today_start = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
stats["price_changes"] = session_db.query(PriceRecord).filter(
PriceRecord.timestamp >= today_start
).count()
# B. 抓取最新 50 筆商品明細
# 邏輯:抓取 Product並針對每個 Product 找出最後一筆價格
products_query = session_db.query(Product).order_by(Product.id.desc()).limit(50).all()
for p in products_query:
# 取得該商品在 PriceRecord 表中最新的一筆紀錄
latest_price_rec = session_db.query(PriceRecord)\
.filter_by(product_id=p.id)\
.order_by(desc(PriceRecord.timestamp))\
.first()
recent_products.append({
"category": p.category,
"name": p.name,
"price": f"{latest_price_rec.price:,.0f}" if latest_price_rec else "N/A",
"url": p.url,
"time": latest_price_rec.timestamp.strftime('%m/%d %H:%M') if latest_price_rec else "-"
})
except Exception as e:
app.logger.error(f"❌ 看板數據讀取失敗: {e}")
finally:
session_db.close()
return render_template('dashboard.html', stats=stats, products=recent_products)
@app.route('/logs')
@login_required
def view_logs():
"""日誌查看頁面"""
log_path = os.path.join(LOG_DIR, 'system.log')
content = "⚠️ 尚無日誌紀錄。"
if os.path.exists(log_path):
try:
with open(log_path, 'r', encoding='utf-8') as f:
f.seek(0, os.SEEK_END)
size = f.tell()
f.seek(max(0, size - 15000)) # 讀取最後 1.5 萬字元
content = f.read()
except Exception as e:
content = f"讀取日誌出錯: {e}"
return render_template('logs.html', log_content=content)
@app.route('/download/<path:filename>')
@login_required
def download_excel(filename):
"""Excel 報表下載"""
return send_from_directory(EXCEL_EXPORT_DIR, filename)
# --- 3. 啟動自我檢查 ---
if __name__ == '__main__':
print("\n" + "="*50)
print("🚀 MOMO 伺服器啟動中...")
print(f"📂 模板目錄: {TEMPLATE_DIR}")
# 檢查核心檔案
for f in ['dashboard.html', 'login.html']:
path = os.path.join(TEMPLATE_DIR, f)
status = "✅ 存在" if os.path.exists(path) else "❌ 缺失"
size = f"({os.path.getsize(path)} bytes)" if os.path.exists(path) else ""
print(f" - {f}: {status} {size}")
print("="*50 + "\n")
app.run(host='0.0.0.0', port=5888, debug=True)