Files
ewoooc/templates/abc_analysis_detail.html
OoO 9dfb7d1514
All checks were successful
CD Pipeline / deploy (push) Successful in 58s
統一登入與廠商工具頁新版設計
2026-05-14 20:43:21 +08:00

185 lines
7.3 KiB
HTML

{% extends "ewoooc_base.html" %}
{% block title %}ABC 分析詳情 - {{ info.title if info else '資料準備中' }} - EwoooC{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="https://cdn.datatables.net/1.11.5/css/dataTables.bootstrap5.min.css">
<link rel="stylesheet" href="{{ url_for('static', filename='css/page-abc-analysis-detail.css') }}">
{% endblock %}
{% block content %}
<section class="abc-detail-page">
{% if loading_state|default(false) %}
<div class="abc-loading-card">
<div class="abc-loading-spinner" aria-hidden="true"></div>
<div>
<h1 class="h4 mb-2">數據準備中</h1>
<p class="text-muted mb-0">正在重新載入業績分析快取,稍後會自動重試。</p>
</div>
<a class="btn btn-outline-secondary" href="/sales_analysis">回業績分析</a>
</div>
{% else %}
<header class="abc-detail-header">
<div>
<span class="abc-detail-kicker">
<i class="fas fa-layer-group" aria-hidden="true"></i>
ABC Analysis
</span>
<h1>{{ info.title }}</h1>
<p>{{ info.desc }}</p>
<div class="abc-detail-statline">
<span class="abc-detail-pill">
<i class="fas fa-coins" aria-hidden="true"></i>
總營收 ${{ "{:,.0f}".format(total_revenue|default(0)) }}
</span>
<span class="abc-detail-pill">
<i class="fas fa-cubes" aria-hidden="true"></i>
{{ items|length }} 個商品
</span>
</div>
</div>
<div class="abc-detail-actions">
<div class="abc-factor-control input-group input-group-sm">
<span class="input-group-text">補貨 x</span>
<input type="number" id="restockFactor" class="form-control text-center" value="{{ current_factor }}" step="0.1" min="0" aria-label="補貨係數">
<button class="btn btn-outline-primary" type="button" onclick="applyFactor()">套用</button>
</div>
<a href="/api/export/excel/abc?class={{ target_class }}&factor={{ current_factor }}&{{ query_string }}" class="btn btn-primary btn-sm">
<i class="fas fa-file-excel me-2" aria-hidden="true"></i>匯出報表
</a>
<a href="/sales_analysis" class="btn btn-outline-secondary btn-sm">
<i class="fas fa-arrow-left me-2" aria-hidden="true"></i>回分析頁
</a>
</div>
</header>
<div class="abc-detail-card">
<div class="abc-detail-card__head">
<h2>商品明細</h2>
<span class="abc-detail-pill">{{ target_class }} 類排序</span>
</div>
<div class="abc-detail-table">
<div class="table-responsive">
<table id="dataTable" class="table table-hover align-middle mb-0">
<thead>
<tr>
<th class="text-center">排名</th>
{% if cols.pid %}<th>商品 ID</th>{% endif %}
<th>商品名稱</th>
{% if cols.brand %}<th>品牌</th>{% endif %}
{% if cols.vendor %}<th>廠商名稱</th>{% endif %}
{% if cols.cat %}<th>分類</th>{% endif %}
{% if cols.cost or cols.profit %}<th>毛利率</th>{% endif %}
{% if cols.qty %}<th>平均單價</th>{% endif %}
{% if cols.qty %}<th class="text-end">銷售數量</th>{% endif %}
{% if cols.qty %}<th class="text-end">建議補貨</th>{% endif %}
<th class="text-end">銷售金額</th>
<th class="text-end">累積營收佔比</th>
</tr>
</thead>
<tbody>
{% for item in items %}
<tr>
<td class="text-center fw-bold text-muted">{{ loop.index }}</td>
{% if cols.pid %}
<td class="small text-muted">{{ item[cols.pid] }}</td>
{% endif %}
<td>
<div class="abc-product-name" title="{{ item[cols.name] | e }}">
{{ item[cols.name] | e }}
</div>
</td>
{% if cols.brand %}
<td class="small text-muted">{{ item[cols.brand] }}</td>
{% endif %}
{% if cols.vendor %}
<td class="small text-muted">{{ item[cols.vendor] }}</td>
{% endif %}
{% if cols.cat %}
<td><span class="badge bg-light text-dark border">{{ item[cols.cat] }}</span></td>
{% endif %}
{% if cols.cost or cols.profit %}
<td>
{% set margin = item['calculated_margin_rate'] %}
<span class="{{ 'text-success' if margin >= 30 else ('text-danger' if margin < 10 else 'text-dark') }} fw-bold">
{{ "{:.1f}%".format(margin) }}
</span>
</td>
{% endif %}
{% if cols.qty %}
<td class="small">${{ "{:,.0f}".format(item['avg_unit_price']) }}</td>
<td class="text-end">{{ "{:,.0f}".format(item[cols.qty]) }}</td>
<td class="text-end fw-bold">
{% if item['suggested_restock'] > 0 %}
{{ "{:,.0f}".format(item['suggested_restock']) }}
{% else %}
<span class="text-muted small">建議清倉</span>
{% endif %}
</td>
{% endif %}
<td class="text-end fw-bold text-danger">
${{ "{:,.0f}".format(item[cols.amount]) }}
</td>
<td class="text-end text-muted small">
{{ "{:.2f}%".format(item['cumulative_pct']) }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endif %}
</section>
{% endblock %}
{% block extra_js %}
{% if loading_state|default(false) %}
<script>
setTimeout(function () {
window.location.reload();
}, 1500);
const retryCount = parseInt(sessionStorage.getItem('abc_retry') || '0', 10);
if (retryCount > 3) {
sessionStorage.removeItem('abc_retry');
window.location.href = '/sales_analysis';
} else {
sessionStorage.setItem('abc_retry', String(retryCount + 1));
}
</script>
{% else %}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.11.5/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.11.5/js/dataTables.bootstrap5.min.js"></script>
<script>
const sortColIndex = parseInt("{{ sort_col_index }}", 10);
$(document).ready(function () {
$('#dataTable').DataTable({
language: {
url: '//cdn.datatables.net/plug-ins/1.11.5/i18n/zh-HANT.json',
paginate: {
previous: '上一頁',
next: '下一頁'
}
},
pageLength: 25,
lengthMenu: [[10, 25, 50, 100, -1], [10, 25, 50, 100, '全部']],
order: [[sortColIndex, 'desc']],
paging: true,
info: true
});
});
function applyFactor() {
const factor = document.getElementById('restockFactor').value;
const url = new URL(window.location.href);
url.searchParams.set('factor', factor);
window.location.href = url.toString();
}
</script>
{% endif %}
{% endblock %}