/** * UI 组件库 */ const Components = { /** * 格式化金额 */ formatAmount(value) { if (value === null || value === undefined) return '-'; return `¥${Number(value).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; }, /** * 格式化数字 */ formatNumber(value, decimals = 2) { if (value === null || value === undefined) return '-'; return Number(value).toLocaleString('zh-CN', { minimumFractionDigits: decimals, maximumFractionDigits: decimals }); }, /** * 格式化库销比 */ formatRatio(value) { if (value === null || value === undefined || value === 999) return '-'; if (value === 0) return '0.00'; return Number(value).toFixed(2); }, /** * 获取配件标签 * 呆滞:有库存,滚动90天没有销量 * 低频:无库存,滚动90天有出库,月均销量<1 * 缺货:无库存,滚动90天有出库,月均销量≥1 */ getPartTag(validStorage, avgSales) { const storage = Number(validStorage) || 0; const sales = Number(avgSales) || 0; if (storage > 0 && sales === 0) { return { type: 'stagnant', text: '呆滞', class: 'tag-stagnant' }; } if (storage <= 0 && sales > 0 && sales < 1) { return { type: 'low-freq', text: '低频', class: 'tag-low-freq' }; } if (storage <= 0 && sales >= 1) { return { type: 'shortage', text: '缺货', class: 'tag-shortage' }; } return null; }, /** * 渲染配件标签HTML */ renderPartTag(validStorage, avgSales) { const tag = this.getPartTag(validStorage, avgSales); if (!tag) return ''; return `${tag.text}`; }, /** * 格式化时长 */ formatDuration(seconds) { if (!seconds) return '-'; seconds = Math.floor(seconds); if (seconds < 60) return `${seconds}秒`; const minutes = Math.floor(seconds / 60); const secs = seconds % 60; return `${minutes}分${secs}秒`; }, /** * 获取状态徽章 HTML */ getStatusBadge(status, statusText) { const statusMap = { 0: { class: 'badge-info', icon: 'loader-2', text: statusText || '运行中' }, 1: { class: 'badge-success', icon: 'check-circle', text: statusText || '成功' }, 2: { class: 'badge-danger', icon: 'x-circle', text: statusText || '失败' }, }; const config = statusMap[status] || statusMap[0]; return ` ${config.text} `; }, /** * 获取优先级徽章 HTML */ getPriorityBadge(priority) { const priorityMap = { 1: { class: 'priority-high', text: '高' }, 2: { class: 'priority-medium', text: '中' }, 3: { class: 'priority-low', text: '低' }, }; const config = priorityMap[priority] || priorityMap[2]; return `${config.text}`; }, /** * 获取库销比指示器 HTML */ getRatioIndicator(current, base) { if (current === null || current === undefined || current === 999) { return '-'; } const percentage = Math.min((current / (base || 1.5)) * 100, 100); let className = 'ratio-normal'; if (current < 0.5) className = 'ratio-low'; else if (current > 2) className = 'ratio-high'; return `
\s*]*>[\s\\n]*<\/code>\s*<\/pre>/gi, '');
html = html.replace(/[\s\\n]*<\/pre>/gi, '');
html = html.replace(/\s*]*>\n<\/code>\s*<\/pre>/gi, '');
return `${html}`;
}
return `${content}`;
},
/**
* 显示 Toast 通知
*/
showToast(message, type = 'info') {
const container = document.getElementById('toast-container');
const icons = {
success: 'check-circle',
error: 'x-circle',
warning: 'alert-triangle',
info: 'info',
};
const toast = document.createElement('div');
toast.className = `toast ${type}`;
toast.innerHTML = `
`;
container.appendChild(toast);
lucide.createIcons({ icons: { [icons[type]]: lucide.icons[icons[type]] }, attrs: {} });
setTimeout(() => {
toast.style.animation = 'slideIn 0.25s ease reverse';
setTimeout(() => toast.remove(), 250);
}, 3000);
},
/**
* 显示加载遮罩
*/
showLoading() {
document.getElementById('loading-overlay').classList.add('active');
},
/**
* 隐藏加载遮罩
*/
hideLoading() {
document.getElementById('loading-overlay').classList.remove('active');
},
/**
* 显示模态框
*/
showModal(title, content) {
document.getElementById('modal-title').textContent = title;
document.getElementById('modal-body').innerHTML = content;
document.getElementById('modal-overlay').classList.add('active');
lucide.createIcons();
},
/**
* 关闭模态框
*/
closeModal() {
document.getElementById('modal-overlay').classList.remove('active');
},
};
// 导出到全局
window.Components = Components;