// performance.js — 绩效模块 window.renderPerformance = () => { const data = state.data; if (!data) return; if (state.perfQuarter === undefined) state.perfQuarter = Math.floor(new Date().getMonth() / 3); const q = state.perfQuarter; const qLabel = ['Q1 (1-3月)', 'Q2 (4-6月)', 'Q3 (7-9月)', 'Q4 (10-12月)']; const qRanges = [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]; const qRange = qRanges[q]; const storageKey = 'opc-performance-Q' + (q + 1); const pfs = (data.projectFinances || []).filter(p => p.status === '已签约'); const sumQ = (field) => { let total = 0; pfs.forEach(p => { try { JSON.parse(p.budget_data || '[]').forEach(b => { const m = parseInt((b.month || '').substring(5)) || 0; if (qRange.includes(m)) total += parseFloat(b[field] || 0); }); } catch (e) {} }); return Math.round(total); }; const signTotal = Math.round(pfs.filter(x => { const m = parseInt((x.sign_month || '0').substring(5)) || 0; return qRange.includes(m); }).reduce((a, p) => a + (p.sign_amount || 0), 0)); const revTotal = sumQ('rev'); const grossTotal = sumQ('gross'); const paymentTotal = sumQ('payment'); const rows = [ { key: 'sign', label: '签约', complete: signTotal, icon: 'file-text', defWeight: 10 }, { key: 'rev', label: '收入', complete: revTotal, icon: 'dollar-sign', defWeight: 20 }, { key: 'gross', label: '毛利', complete: grossTotal, icon: 'trending-up', defWeight: 50 }, { key: 'payment', label: '回款', complete: paymentTotal, icon: 'coins', defWeight: 20 }, ]; const saved = JSON.parse(localStorage.getItem(storageKey) || '{}'); function val(key, field, def) { const r = saved[key] || {}; return r[field] !== undefined && r[field] !== '' ? Number(r[field]) : def; } function moneyWan(v) { if (v >= 10000) return (v / 10000).toFixed(1) + '万'; return v.toLocaleString(); } let totalScore = 0; const tableRows = rows.map(r => { const targetWan = val(r.key, 'targetWan', 0); const target = Math.round(targetWan * 10000); const weight = val(r.key, 'weight', r.defWeight); const score = target > 0 ? Math.round((r.complete / target) * weight * 10) / 10 : 0; totalScore += score; return ` ${r.label}
${moneyWan(r.complete)}
${score.toFixed(1)} `; }).join(''); const quarterTabs = `
` + qLabel.map((l, i) => { return ``; }).join('') + `
`; document.querySelector("#performance").innerHTML = `
${quarterTabs}
${tableRows}
指标 目标(万) 完成情况 权重 评分
合计 100 ${totalScore.toFixed(1)}
`; if (window.lucide) window.lucide.createIcons(); }; window.switchPerfQuarter = (q) => { state.perfQuarter = q; renderPerformance(); }; window.updatePerfScore = (key, field, value) => { const q = state.perfQuarter || 0; const storageKey = 'opc-performance-Q' + (q + 1); const saved = JSON.parse(localStorage.getItem(storageKey) || '{}'); saved[key] = saved[key] || {}; saved[key][field] = value; localStorage.setItem(storageKey, JSON.stringify(saved)); renderPerformance(); };