/** * 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 `
${this.formatRatio(current)}
`; }, /** * 渲染分页控件 */ renderPagination(current, total, pageSize, onChange) { const totalPages = Math.ceil(total / pageSize); const start = (current - 1) * pageSize + 1; const end = Math.min(current * pageSize, total); return ` `; }, /** * 获取分页数字 */ getPaginationNumbers(current, total) { const pages = []; const maxVisible = 5; let start = Math.max(1, current - Math.floor(maxVisible / 2)); let end = Math.min(total, start + maxVisible - 1); start = Math.max(1, end - maxVisible + 1); for (let i = start; i <= end; i++) { pages.push(` `); } return pages.join(''); }, /** * 渲染统计卡片 */ renderStatCard(icon, label, value, iconClass = 'primary', change = null) { let changeHtml = ''; if (change !== null) { const changeClass = change >= 0 ? 'positive' : 'negative'; const changeIcon = change >= 0 ? 'trending-up' : 'trending-down'; changeHtml = `
${Math.abs(change)}%
`; } return `
${label}
${value}
${changeHtml}
`; }, /** * 渲染空状态 */ renderEmptyState(icon = 'inbox', title = '暂无数据', description = '') { return `
${title}
${description ? `
${description}
` : ''}
`; }, /** * 渲染信息列表项 */ renderInfoItem(label, value) { return `
${label} ${value || '-'}
`; }, /** * 渲染 Markdown 内容 */ renderMarkdown(content) { if (!content) return ''; if (typeof marked !== 'undefined') { let html = marked.parse(content); html = html.replace(/
\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 = ` ${message} `; 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;