Files
ewoooc/templates/ai_recommend.html
OoO eb521fd6d8
All checks were successful
CD Pipeline / deploy (push) Successful in 1m3s
V10.615 AI 推薦頁 Ollama 主路徑文案
2026-06-16 10:16:23 +08:00

450 lines
24 KiB
HTML
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.
{% extends 'ewoooc_base.html' %}
{% block title %}AI 智慧推薦 · EwoooC{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/page-ai-recommend.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/page-ai-recommend-bem.css') }}">
{% endblock %}
{% block ewooo_content %}
{# 頁面執行時會呼叫 page-ai-recommend.js: fetch('/api/ai/generate_copy', ...), fetch('/api/ai/web_search', ...), fetch('/api/ai/product_insights', ...), fetch('/api/ai/gemini_usage?days=30'). #}
<div class="momo-app" data-page-group="ai">
<div class="ai-recommend-page">
{# ── Hero header ─────────────────────────────────── #}
<header class="ai-recommend-hero ar-hero">
<div class="ar-hero__title">
<h1 class="ai-recommend-title">
<i class="fas fa-robot"></i>AI 智慧推薦
</h1>
<small class="ar-hero__sub">根據資料庫商品分類、即時趨勢與 AI 生成紀錄,產出可追蹤的銷售文案。</small>
</div>
<div class="ar-hero__actions">
<span id="ollamaStatus" class="ar-status {{ 'ar-status--ok' if ollama_status else 'ar-status--off' }}">
<i class="fas fa-server"></i> Ollama 主路徑 {{ '檢查中' if ollama_status is none else ('✓' if ollama_status else '✗') }}
</span>
<span id="geminiStatus" class="ar-status {{ 'ar-status--info' if gemini_status else 'ar-status--off' }}">
<i class="fab fa-google"></i> Gemini 備援 {{ '檢查中' if gemini_status is none else ('✓' if gemini_status else '✗') }}
</span>
<button class="btn btn-outline-secondary btn-sm" data-bs-toggle="modal" data-bs-target="#helpModal" title="使用說明">
<i class="fas fa-question-circle"></i>
</button>
</div>
</header>
<div class="row">
{# ── 左側:文案生成 ────────────────────────────── #}
<div class="col-lg-6 col-xl-5 mb-3">
<article class="card ar-card ar-card--gen">
<header class="card-header ar-card__head ar-card__head--accent">
<div class="d-flex justify-content-between align-items-center">
<h6 class="mb-0"><i class="fas fa-magic me-2"></i>文案生成</h6>
<small class="ar-card__step">第 1 步:設定參數</small>
</div>
</header>
<div class="card-body py-3">
{# 商品名稱 #}
<div class="mb-3">
<label class="form-label fw-bold mb-1">
<i class="fas fa-box me-1"></i>商品名稱 <span class="text-danger">*</span>
</label>
<div class="input-group">
<input type="text" class="form-control form-control-lg" id="productName" placeholder="輸入商品名稱...">
<button class="btn btn-outline-primary dropdown-toggle" type="button" data-bs-toggle="dropdown" title="從商品分類快速選取">
<i class="fas fa-list"></i>
</button>
<ul class="dropdown-menu dropdown-menu-end ar-dropdown">
<li><h6 class="dropdown-header">點選分類快速填入</h6></li>
{% for category in product_categories %}
<li><a class="dropdown-item" href="#" onclick="setProduct('{{ category }}')">{{ category }}</a></li>
{% endfor %}
</ul>
</div>
<div class="d-flex justify-content-between mt-1">
<small class="text-muted"><i class="fas fa-lightbulb me-1"></i>可從右側熱銷商品快速選取</small>
<button type="button" class="btn btn-link btn-sm p-0 text-decoration-none" onclick="document.getElementById('productName').value=''">
<small>清除</small>
</button>
</div>
</div>
{# 風格 / 引擎 / 模型 #}
<div class="row g-2 mb-3">
<div class="col-4">
<label class="form-label small fw-bold mb-1">文案風格</label>
<select class="form-select form-select-sm" id="copyStyle">
<option value="吸睛">🎯 吸睛活潑</option>
<option value="專業">🔬 專業權威</option>
<option value="溫馨">💕 溫馨感性</option>
<option value="急迫">⚡ 限時急迫</option>
</select>
</div>
<div class="col-4">
<label class="form-label small fw-bold mb-1">AI 路徑</label>
<select class="form-select form-select-sm" id="aiProvider" onchange="onProviderChange()">
<option value="ollama" {% if default_provider == 'ollama' %}selected{% endif %}>🖥️ Ollama 主路徑</option>
<option value="gemini" disabled>☁️ Gemini 備援(系統自動,不可手動選)</option>
</select>
</div>
<div class="col-4">
<label class="form-label small fw-bold mb-1">AI 模型</label>
<select class="form-select form-select-sm" id="ollamaModelSelect">
{% for model in available_models %}
<option value="{{ model }}" {% if 'gemma3:4b' in model %}selected{% endif %}>{{ model }}</option>
{% endfor %}
</select>
<select class="form-select form-select-sm" id="geminiModelSelect" style="display: none;">
{% for model in gemini_models %}
<option value="{{ model.id }}" {% if loop.first %}selected{% endif %}>{{ model.name }}</option>
{% endfor %}
</select>
</div>
</div>
{# Gemini 用量面板 #}
<div id="geminiUsagePanel" class="alert alert-info py-2 mb-3" style="display: none;">
<div class="d-flex justify-content-between align-items-center">
<small class="fw-bold"><i class="fab fa-google me-1"></i>Gemini 備援本月使用量</small>
<button type="button" class="btn btn-link btn-sm p-0" onclick="loadGeminiUsage()"><i class="fas fa-sync-alt"></i></button>
</div>
<div class="d-flex justify-content-between small mt-1">
<span>費用:<strong id="geminiMonthlyCost">$0.0000</strong></span>
<span>請求:<span id="geminiRequestCount">0</span></span>
<span>權杖:<span id="geminiTokenUsage">0</span></span>
</div>
</div>
{# 關鍵字+節日 #}
<div class="accordion accordion-flush" id="advancedOptions">
<div class="accordion-item border-0">
<h2 class="accordion-header">
<button class="accordion-button collapsed py-2 px-0 bg-transparent" type="button" data-bs-toggle="collapse" data-bs-target="#keywordsCollapse">
<small class="fw-bold"><i class="fas fa-tags me-1"></i>關鍵字與節日 <span class="badge ar-selected-count ms-1" id="selectedKeywordCount">0 個已選</span></small>
</button>
</h2>
<div id="keywordsCollapse" class="accordion-collapse collapse" data-bs-parent="#advancedOptions">
<div class="accordion-body p-0 pt-2">
<div class="mb-2">
<small class="text-muted d-block mb-1">點選標籤加入/移除</small>
<div id="keywordsArea" class="ar-keywords">
{% for category in product_categories[:12] %}
<span class="badge ar-keyword-badge border me-1 mb-1 keyword-badge ar-keyword" onclick="toggleKeyword(this)">{{ category }}</span>
{% endfor %}
</div>
</div>
<div>
<small class="text-muted"><i class="fas fa-calendar-alt me-1"></i>近期節日(自動融入)</small>
<div id="upcomingHolidays" class="small mt-1"></div>
</div>
</div>
</div>
</div>
</div>
<hr class="my-2">
<div class="d-grid">
<button class="btn btn-primary" onclick="generateCopy()" id="generateBtn">
<i class="fas fa-magic me-2"></i>生成文案
</button>
</div>
</div>
</article>
{# 生成結果 #}
<div id="resultArea" class="mt-3" style="display: none;">
<article class="card ar-card ar-card--result">
<header class="card-header ar-card__head ar-card__head--success d-flex justify-content-between align-items-center">
<span><i class="fas fa-sparkles me-2"></i>AI 生成文案</span>
<button class="btn btn-sm btn-light" onclick="copyCopyText()" title="複製全部文案到剪貼簿">
<i class="fas fa-copy me-1"></i>複製
</button>
</header>
<div class="card-body py-2 ar-result__body">
<div id="generatedCopy" class="ar-result__text"></div>
<hr class="my-2">
<small class="text-muted" id="copyMeta"></small>
</div>
</article>
</div>
{# AI 智慧搜尋 #}
<article class="card ar-card mt-3 ar-card--search">
<header class="card-header ar-card__head ar-card__head--accent-soft py-2">
<div>
<h6 class="mb-0"><i class="fas fa-search-dollar me-2"></i>AI 智慧搜尋</h6>
<small class="text-muted">輸入關鍵字AI 分析市場趨勢</small>
</div>
</header>
<div class="card-body py-2">
<div class="input-group input-group-sm mb-2">
<input type="text" class="form-control" id="webSearchQuery" placeholder="輸入搜尋關鍵字...">
<select class="form-select" id="webSearchType" style="max-width: 100px;">
<option value="general">一般</option>
<option value="shopping">商品</option>
<option value="trends">趨勢</option>
<option value="news">新聞</option>
</select>
<button class="btn btn-primary" onclick="doWebSearch()" id="webSearchBtn">
<i class="fas fa-brain"></i>
</button>
</div>
<div class="ar-quick-tags mb-2">
{% for category in product_categories[:4] %}
<span class="badge bg-light text-dark border ar-quick-tag" onclick="quickWebSearch({{ category|tojson }})">{{ category }}</span>
{% endfor %}
</div>
<div id="webSearchResult" style="display: none;">
<hr class="my-2">
<div id="webSearchContent"></div>
</div>
</div>
</article>
{# 商品洞察 #}
<article class="card ar-card mt-3 ar-card--insights">
<header class="card-header ar-card__head ar-card__head--warn-soft d-flex justify-content-between align-items-center py-2">
<div>
<h6 class="mb-0"><i class="fas fa-lightbulb me-2"></i>商品洞察分析</h6>
<small class="text-muted">結合網路搜尋的即時市場分析</small>
</div>
<button class="btn btn-sm btn-warning" onclick="doProductInsights()" id="insightsBtn">
<i class="fas fa-search-dollar me-1"></i>分析商品
</button>
</header>
<div id="productInsightsResult" class="card-body py-3" style="display: none;"></div>
<div id="productInsightsPlaceholder" class="card-body py-3 text-center text-muted">
<i class="fas fa-info-circle me-1"></i>輸入商品名稱後點擊「分析商品」<br>
<small>AI 會先搜尋最新網路資訊,再進行深度分析</small>
</div>
</article>
</div>
{# ── 右側:市場資訊 tabs ──────────────────────── #}
<div class="col-lg-6 col-xl-7">
<ul class="nav nav-pills nav-fill mb-3" id="marketInfoTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active py-2" id="trends-tab" data-bs-toggle="pill" data-bs-target="#trends-panel" type="button" role="tab">
<i class="fas fa-chart-line me-1"></i><span class="d-none d-md-inline">趨勢洞察</span><span class="d-md-none">趨勢</span>
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link py-2" id="bestsellers-tab" data-bs-toggle="pill" data-bs-target="#bestsellers-panel" type="button" role="tab">
<i class="fas fa-fire-alt me-1"></i><span class="d-none d-md-inline">熱銷商品</span><span class="d-md-none">熱銷</span>
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link py-2" id="rankings-tab" data-bs-toggle="pill" data-bs-target="#rankings-panel" type="button" role="tab">
<i class="fas fa-crown me-1"></i><span class="d-none d-md-inline">排行榜</span><span class="d-md-none">排行</span>
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link py-2" id="news-tab" data-bs-toggle="pill" data-bs-target="#news-panel" type="button" role="tab">
<i class="fas fa-newspaper me-1"></i><span class="d-none d-md-inline">趨勢新聞</span><span class="d-md-none">新聞</span>
</button>
</li>
</ul>
<div class="tab-content" id="marketInfoTabContent">
{# 趨勢洞察 #}
<div class="tab-pane fade show active" id="trends-panel" role="tabpanel">
<article class="card ar-card ar-card--trends">
<header class="card-header ar-card__head ar-card__head--soft d-flex justify-content-between align-items-center py-2">
<div>
<h6 class="mb-0"><i class="fas fa-chart-line me-2"></i>即時趨勢洞察</h6>
<small class="text-muted">來自 PTT、Dcard、Google News</small>
</div>
<div class="d-flex gap-1">
<select class="form-select form-select-sm" id="trendSource" style="width: 90px;" onchange="refreshTrends()">
<option value="">全部來源</option>
<option value="google_news">Google</option>
<option value="ptt">PTT</option>
<option value="dcard">Dcard</option>
<option value="youtube">YouTube</option>
</select>
<select class="form-select form-select-sm" id="trendCategory" style="width: 70px;" onchange="refreshTrends()">
<option value="">全部</option>
<option value="美妝">美妝</option>
<option value="3C">3C</option>
<option value="服飾">服飾</option>
<option value="居家">居家</option>
</select>
<button class="btn btn-sm btn-outline-success" onclick="refreshTrends()"><i class="fas fa-sync-alt"></i></button>
</div>
</header>
<div class="card-body py-2">
<div class="mb-2">
<small class="text-muted fw-bold">熱門關鍵字:</small>
<div id="trendKeywordCloud" class="d-flex flex-wrap gap-1 mt-1">
<span class="badge bg-light text-dark border">載入中...</span>
</div>
</div>
<div id="trendListArea" class="ar-scroll-280">
<div class="text-center py-2"><div class="spinner-border spinner-border-sm"></div></div>
</div>
</div>
</article>
</div>
{# 熱銷商品 #}
<div class="tab-pane fade" id="bestsellers-panel" role="tabpanel">
<article class="card ar-card">
<header class="card-header ar-card__head ar-card__head--soft d-flex justify-content-between align-items-center py-2">
<div>
<h6 class="mb-0"><i class="fas fa-fire-alt me-2"></i>熱銷商品參考</h6>
<small class="text-muted">點選商品快速填入</small>
</div>
<div class="d-flex align-items-center gap-1">
<div class="btn-group btn-group-sm">
<input type="radio" class="btn-check" name="platform" id="platformPchome" value="pchome" checked>
<label class="btn btn-outline-primary btn-sm px-2" for="platformPchome">PChome</label>
<input type="radio" class="btn-check" name="platform" id="platformMomo" value="momo" disabled>
<label class="btn btn-outline-secondary btn-sm px-2 ar-disabled" for="platformMomo">MOMO</label>
</div>
<select class="form-select form-select-sm" id="bestsellersCategory" style="width: 80px;" onchange="loadBestsellers()">
<option value="面膜">面膜</option>
<option value="精華液">精華液</option>
<option value="乳液">乳液</option>
<option value="保濕">保濕</option>
<option value="美白">美白</option>
</select>
</div>
</header>
<div class="card-body py-2 ar-scroll-350" id="bestsellersCard">
<div class="text-center py-3"><div class="spinner-border spinner-border-sm"></div></div>
</div>
</article>
</div>
{# 排行榜 #}
<div class="tab-pane fade" id="rankings-panel" role="tabpanel">
<div class="row g-3">
<div class="col-12 col-md-6">
<article class="card ar-card h-100">
<header class="card-header ar-card__head ar-card__head--soft d-flex justify-content-between align-items-center py-2">
<div>
<h6 class="mb-0"><i class="fas fa-crown me-2"></i>COSME</h6>
<small class="text-muted">日本美妝排行</small>
</div>
<select class="form-select form-select-sm" id="cosmeCategory" style="width: 80px;" onchange="loadCosmeRankings()">
<option value="mask">面膜</option>
<option value="serum">精華液</option>
<option value="lotion">乳液</option>
<option value="sunscreen">防曬</option>
<option value="lipstick">唇彩</option>
<option value="foundation">底妝</option>
</select>
</header>
<div class="card-body py-2 ar-scroll-300" id="cosmeCard">
<div class="text-center py-3"><div class="spinner-border spinner-border-sm"></div></div>
</div>
</article>
</div>
<div class="col-12 col-md-6">
<article class="card ar-card h-100">
<header class="card-header ar-card__head ar-card__head--soft d-flex justify-content-between align-items-center py-2">
<div>
<h6 class="mb-0"><i class="fas fa-trophy me-2"></i>mybest</h6>
<small class="text-muted">專業評測</small>
</div>
<select class="form-select form-select-sm" id="mybestCategory" style="width: 80px;" onchange="loadMybestArticles()">
<option value="skincare">保養</option>
<option value="makeup">彩妝</option>
<option value="health">健康</option>
<option value="baby">嬰兒</option>
<option value="maternity">孕婦</option>
<option value="kids">兒童</option>
</select>
</header>
<div class="card-body py-2 ar-scroll-300" id="mybestCard">
<div class="text-center py-3"><div class="spinner-border spinner-border-sm"></div></div>
</div>
</article>
</div>
</div>
</div>
{# 趨勢新聞 #}
<div class="tab-pane fade" id="news-panel" role="tabpanel">
<article class="card ar-card">
<header class="card-header ar-card__head ar-card__head--soft py-2">
<div class="d-flex justify-content-between align-items-center mb-2">
<div>
<h6 class="mb-0"><i class="fas fa-newspaper me-2"></i>趨勢新聞</h6>
<small class="text-muted">點選新聞快速填入商品</small>
</div>
<button class="btn btn-sm btn-outline-secondary" onclick="loadTrends()"><i class="fas fa-sync-alt"></i></button>
</div>
<ul class="nav nav-tabs card-header-tabs" id="trendTabs">
<li class="nav-item">
<a class="nav-link active py-1 px-2" href="#" data-trend-type="news" onclick="switchTrendTab(this, 'news')">
<i class="fas fa-newspaper me-1"></i>新聞
</a>
</li>
<li class="nav-item">
<a class="nav-link py-1 px-2" href="#" data-trend-type="social" onclick="switchTrendTab(this, 'social')">
<i class="fas fa-hashtag me-1"></i>社群
</a>
</li>
<li class="nav-item">
<a class="nav-link py-1 px-2" href="#" data-trend-type="search" onclick="switchTrendTab(this, 'search')">
<i class="fas fa-search me-1"></i>搜尋
</a>
</li>
</ul>
</header>
<div id="newsCard" class="ar-scroll-350">
<div class="text-center py-4"><div class="spinner-border"></div><p class="mt-2 text-muted small">載入中...</p></div>
</div>
</article>
</div>
</div>
</div>
</div>
</div>
</div>
{# ── Help modal ──────────────────────────────────── #}
<div class="modal fade" id="helpModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header py-2">
<h6 class="modal-title"><i class="fas fa-question-circle me-2"></i>使用說明</h6>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body py-3">
<div class="d-flex align-items-start mb-3">
<span class="badge ar-step-badge me-2">1</span>
<div><strong>輸入商品名稱</strong><p class="text-muted small mb-0">可直接輸入或從右側熱銷商品點選</p></div>
</div>
<div class="d-flex align-items-start mb-3">
<span class="badge ar-step-badge me-2">2</span>
<div><strong>選擇文案風格</strong><p class="text-muted small mb-0">吸睛活潑、專業權威、溫馨感性、限時急迫</p></div>
</div>
<div class="d-flex align-items-start mb-3">
<span class="badge ar-step-badge me-2">3</span>
<div><strong>點擊生成文案</strong><p class="text-muted small mb-0">AI 會根據市場趨勢自動生成銷售文案</p></div>
</div>
<hr>
<p class="small text-muted mb-0">
<i class="fas fa-lightbulb me-1"></i>
<strong>小技巧:</strong>使用「AI 智慧搜尋」可獲得更多市場洞察,點選「商品洞察」可分析競品與市場定位。
</p>
</div>
</div>
</div>
</div>
{# ── Loading overlay ─────────────────────────────── #}
<div id="loadingOverlay" class="ar-loading-overlay d-none">
<div class="ar-loading-overlay__inner">
<div class="spinner-border spinner-border-lg mb-3"></div>
<h5 id="loadingText">AI 正在思考中...</h5>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script src="{{ url_for('static', filename='js/page-ai-recommend.js') }}"></script>
{% endblock %}