240 lines
11 KiB
JavaScript
240 lines
11 KiB
JavaScript
/**
|
|
* 企业级页面渲染模块。
|
|
* 负责企业总览、企业指标分析、项目图表和项目清单弹窗,数据来自企业监控接口。
|
|
*/
|
|
function renderEnterpriseView() {
|
|
const enterprise = getEnterprise(state.enterpriseName);
|
|
const summary = getProjectMasterSummary();
|
|
const indicators = getWarningIndicators();
|
|
const analysisIndicators = projectMasterDataState.metricDatas.length ? projectMasterDataState.metricDatas : indicators;
|
|
const projects = (projectMasterDataState.projectAnalysises || []).map((item) => ({
|
|
id: item.projectId,
|
|
unitId: item.unitId,
|
|
unit: enterprise.name,
|
|
name: item.name,
|
|
created: item.isOnline,
|
|
usageRate: item.usageRate,
|
|
accuracyRate: item.accuracyRate,
|
|
warningCount: item.usageRate < 80 ? 1 : 0,
|
|
systemStatus: item.isOnline ? "已上线" : "未上线",
|
|
lastUpdate: summary.dataDate || "",
|
|
owner: "-",
|
|
risk: item.usageRate < 65 ? "高" : item.usageRate < 80 ? "中" : "低"
|
|
}));
|
|
const enterpriseOnlineRate = summary.onlineRate;
|
|
const belowStandardProjects = summary.failProjectNum;
|
|
|
|
if (projectMasterDataState.loading) {
|
|
app.innerHTML = '<div class="empty-state">正在获取企业监控数据...</div>';
|
|
return;
|
|
}
|
|
if (!projects.length && projectMasterDataState.error) {
|
|
app.innerHTML = `
|
|
<section class="panel">
|
|
<div class="panel-header">
|
|
<div>
|
|
<h2 class="panel-title">${enterprise.name} · ${dimLabel()}看板</h2>
|
|
<div class="panel-note">${projectMasterDataState.error}</div>
|
|
</div>
|
|
</div>
|
|
<div class="empty-state">企业监控接口数据加载失败。</div>
|
|
</section>
|
|
`;
|
|
return;
|
|
}
|
|
|
|
app.innerHTML = `
|
|
<section class="metric-cards">
|
|
${miniMetric("项目上线率", summary.proInfoText, "", `上线率 ${fmtFixedPercent(enterpriseOnlineRate, 2)}`, "group-online-stats")}
|
|
${miniMetric("预立项项目数", summary.preProjectTotal, "个", "点击查看项目上线统计", "group-online-stats")}
|
|
${miniMetric("待建项目数", summary.pendingTotal, "个", "点击查看项目上线统计", "group-online-stats")}
|
|
${miniMetric("未达标项目数", belowStandardProjects, "个", "指标使用率低于 80% 的项目", "below-standard-projects")}
|
|
${miniMetric("项目指标使用率", fmtPercent(summary.usageRate), "", "指标使用率低于 80% 的项目计入未达标项目")}
|
|
${miniMetric("项目指标准确率", fmtPercent(summary.accuracyRate), "", "")}
|
|
</section>
|
|
|
|
<section class="indicator-strip">
|
|
${renderFocusIndicators(indicators.slice(0, 8), 0, { highlightHigh: false })}
|
|
</section>
|
|
|
|
<article class="panel trend-panel enterprise-trend-panel">
|
|
<div class="panel-header">
|
|
<div>
|
|
<h2 class="panel-title">企业三率趋势曲线</h2>
|
|
<div class="panel-note">近 7 日${enterprise.name}上线率、使用率、准确率变化。</div>
|
|
</div>
|
|
<div class="legend">
|
|
<span class="legend-item"><span class="dot" style="background:${COLORS.online}"></span>上线</span>
|
|
<span class="legend-item"><span class="dot" style="background:${COLORS.usage}"></span>使用</span>
|
|
<span class="legend-item"><span class="dot" style="background:${COLORS.accuracy}"></span>准确</span>
|
|
</div>
|
|
</div>
|
|
<div class="chart-box">${renderTrendChart({
|
|
date: projectMasterDataState.trendCurve?.Date || [],
|
|
online: projectMasterDataState.trendCurve?.OnlineRate || [],
|
|
usage: projectMasterDataState.trendCurve?.UsageRate || [],
|
|
accuracy: projectMasterDataState.trendCurve?.AccuracyRate || []
|
|
}, 1840, 112)}</div>
|
|
</article>
|
|
|
|
<section class="dashboard-grid enterprise-overview">
|
|
<article class="panel">
|
|
<div class="panel-header">
|
|
<div>
|
|
<h2 class="panel-title">${enterprise.name} · 项目分析</h2>
|
|
<div class="panel-note">项目级不统计上线率,底部圆点表示是否上线;点击项目下钻到字段追踪。</div>
|
|
</div>
|
|
<div class="legend">
|
|
<span class="legend-item"><span class="dot" style="background:${COLORS.usage}"></span>使用率</span>
|
|
<span class="legend-item"><span class="dot" style="background:${COLORS.accuracy}"></span>准确率</span>
|
|
<span class="legend-item"><span class="dot" style="background:${COLORS.cyan}"></span>已上线</span>
|
|
</div>
|
|
</div>
|
|
<div class="chart-box">${renderProjectRateChart(projects, { height: 210 })}</div>
|
|
<div class="explain">企业层用于回答:本单位哪些项目未上线、哪些项目上线后未使用指标、哪些项目数据连续未更新。</div>
|
|
</article>
|
|
|
|
<article class="panel">
|
|
<div class="panel-header">
|
|
<div>
|
|
<h2 class="panel-title">指标分析</h2>
|
|
<div class="panel-note">按${enterprise.name}指标预警项目数、使用率和数据状态展示责任短板。</div>
|
|
</div>
|
|
<div class="panel-tools">
|
|
<button type="button" class="more-btn" data-action="enterprise-more-indicators">更多</button>
|
|
</div>
|
|
</div>
|
|
${renderEnterpriseIndicatorAnalysis(analysisIndicators)}
|
|
</article>
|
|
</section>
|
|
`;
|
|
}
|
|
|
|
/**
|
|
* 企业页顶部小指标卡。
|
|
* action 不为空时会写入 data-action,事件代理据此打开项目清单或未上线项目清单弹窗。
|
|
*/
|
|
function miniMetric(label, value, unit, desc, action = "") {
|
|
return `
|
|
<article class="mini-panel" ${action ? `data-action="${action}"` : ""}>
|
|
<div class="mini-label">${label}</div>
|
|
<div class="mini-value">${value}<span class="kpi-unit">${unit}</span></div>
|
|
<div class="mini-desc">${desc}</div>
|
|
</article>
|
|
`;
|
|
}
|
|
|
|
/**
|
|
* 企业项目风险表。
|
|
* 每行带 data-project,点击后切换到项目明细页;表格主要用于从企业层快速定位异常项目。
|
|
*/
|
|
function renderProjectTable(projectRiskList) {
|
|
return `
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>项目名称</th>
|
|
<th>是否上线</th>
|
|
<th>使用率</th>
|
|
<th>准确率</th>
|
|
<th>预警项</th>
|
|
<th>最近更新</th>
|
|
<th>风险</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
${projectRiskList.map(({ project }) => `
|
|
<tr class="clickable-row" data-project="${project.id}">
|
|
<td>${project.name}</td>
|
|
<td>${project.created ? '<span class="status-pill ok">已上线</span>' : '<span class="status-pill bad">未上线</span>'}</td>
|
|
<td class="num">${fmtPercent(project.usageRate)}</td>
|
|
<td class="num">${fmtPercent(project.accuracyRate)}</td>
|
|
<td class="num">${project.warningCount}</td>
|
|
<td>${project.lastUpdate}</td>
|
|
<td>${riskPill(project.risk)}</td>
|
|
</tr>
|
|
`).join("")}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
/**
|
|
* 企业项目清单弹窗。
|
|
* type=offline 时只展示未建档/未上线项目;其他情况展示当前维度下所有生成项目。
|
|
*/
|
|
function renderEnterpriseProjectListModal(type) {
|
|
const enterprise = getEnterprise(state.enterpriseName);
|
|
const projects = (projectMasterDataState.projectAnalysises || []).map((item) => ({
|
|
id: item.projectId,
|
|
unitId: item.unitId,
|
|
name: item.name,
|
|
created: item.isOnline,
|
|
usageRate: item.usageRate,
|
|
accuracyRate: item.accuracyRate,
|
|
warningCount: item.usageRate < 80 ? 1 : 0,
|
|
lastUpdate: getProjectMasterSummary().dataDate || "-",
|
|
owner: "-",
|
|
risk: item.usageRate < 65 ? "高" : item.usageRate < 80 ? "中" : "低"
|
|
}));
|
|
const rows = type === "offline"
|
|
? projects.filter((project) => !project.created)
|
|
: projects;
|
|
const title = type === "offline" ? "未上线项目清单" : "所有项目清单";
|
|
const emptyText = type === "offline" ? "当前企业暂无未上线项目。" : "当前企业暂无项目。";
|
|
if (!rows.length) {
|
|
return `
|
|
<section class="panel drill-panel">
|
|
<div class="panel-header">
|
|
<div>
|
|
<h2 class="panel-title">${enterprise.name} · ${title}</h2>
|
|
</div>
|
|
</div>
|
|
<div class="empty-state">${emptyText}</div>
|
|
</section>
|
|
`;
|
|
}
|
|
return `
|
|
<section class="panel drill-panel">
|
|
<div class="panel-header">
|
|
<div>
|
|
<h2 class="panel-title">${enterprise.name} · ${title}</h2>
|
|
<div class="panel-note">点击项目行进入项目级看板。</div>
|
|
</div>
|
|
</div>
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>项目名称</th>
|
|
<th>是否上线</th>
|
|
<th>使用率</th>
|
|
<th>准确率</th>
|
|
<th>预警项</th>
|
|
<th>最近更新</th>
|
|
<th>责任人</th>
|
|
<th>风险</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
${rows.map((project) => `
|
|
<tr class="clickable-row" data-project="${project.id}" data-project-unit-id="${escapeHtmlAttr(project.unitId || "")}">
|
|
<td>${project.name}</td>
|
|
<td>${project.created ? '<span class="status-pill ok">已上线</span>' : '<span class="status-pill bad">未上线</span>'}</td>
|
|
<td class="num">${fmtPercent(project.usageRate)}</td>
|
|
<td class="num">${fmtPercent(project.accuracyRate)}</td>
|
|
<td class="num">${project.warningCount}</td>
|
|
<td>${project.lastUpdate}</td>
|
|
<td>${project.owner}</td>
|
|
<td>${riskPill(project.risk)}</td>
|
|
</tr>
|
|
`).join("")}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
`;
|
|
}
|