fix(mgmt-perf): /mgmt-perf 정적 제공, Chart.js 동봉, 파일명 복원·차트 리플로
- Express에 /mgmt-perf → public/mgmt-perf 정적 마운트(기존 뷰 경로와 일치) - jsdelivr 대신 chart.umd.min.js 동봉으로 CDN 차단·오프라인 대응 - decodeMultipartFilename: Latin-1→UTF-8 복원 시 한글 검사 제거(ASCII·깨진 문자열 모두) - 페이로드/Chart 실패 시 사용자에게 빨간 안내, 차트 resize 이중 rAF Made-with: Cursor
This commit is contained in:
14
public/mgmt-perf/chart.umd.min.js
vendored
Normal file
14
public/mgmt-perf/chart.umd.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,7 +1,22 @@
|
||||
(function () {
|
||||
function showMgmtPerfEmbedError(msg) {
|
||||
var root = document.querySelector(".mgmt-perf-embed");
|
||||
if (!root) return;
|
||||
var prev = document.getElementById("mgmt-perf-embed-error");
|
||||
if (prev) prev.remove();
|
||||
var el = document.createElement("div");
|
||||
el.id = "mgmt-perf-embed-error";
|
||||
el.setAttribute("role", "alert");
|
||||
el.style.cssText =
|
||||
"background:#ffebee;color:#b71c1c;padding:12px;margin:8px;border-radius:8px;font-size:13px;";
|
||||
el.textContent = msg;
|
||||
root.insertBefore(el, root.firstChild);
|
||||
}
|
||||
|
||||
const payloadEl = document.getElementById("mgmt-perf-payload-json");
|
||||
if (!payloadEl || !payloadEl.textContent.trim()) {
|
||||
console.error("mgmt-perf: missing payload");
|
||||
showMgmtPerfEmbedError("대시보드 데이터(JSON)가 없습니다. 서버 배포·페이지 소스를 확인하세요.");
|
||||
return;
|
||||
}
|
||||
let P;
|
||||
@@ -9,15 +24,20 @@
|
||||
P = JSON.parse(payloadEl.textContent);
|
||||
} catch (err) {
|
||||
console.error("mgmt-perf: invalid JSON", err);
|
||||
showMgmtPerfEmbedError("대시보드 데이터 JSON 파싱에 실패했습니다.");
|
||||
return;
|
||||
}
|
||||
if (typeof Chart === "undefined") {
|
||||
console.error("mgmt-perf: Chart.js not loaded");
|
||||
showMgmtPerfEmbedError(
|
||||
"Chart.js를 불러오지 못했습니다. /mgmt-perf/chart.umd.min.js 경로·방화벽을 확인하세요."
|
||||
);
|
||||
return;
|
||||
}
|
||||
const UM = P.UM;
|
||||
if (!UM || typeof UM !== "object") {
|
||||
console.error("mgmt-perf: payload missing UM");
|
||||
showMgmtPerfEmbedError("페이로드에 UM(매출 집계)이 없습니다. 스냅샷·기본 JSON을 확인하세요.");
|
||||
return;
|
||||
}
|
||||
const ORDER_CAT = P.ORDER_CAT;
|
||||
@@ -124,6 +144,18 @@ let state = {
|
||||
}
|
||||
}
|
||||
|
||||
/** 숨김 탭·레이아웃 직후 캔버스 크기 0인 경우 대비 */
|
||||
function scheduleChartReflow() {
|
||||
requestAnimationFrame(function () {
|
||||
requestAnimationFrame(function () {
|
||||
Object.keys(state.charts).forEach(function (id) {
|
||||
var ch = state.charts[id];
|
||||
if (ch && typeof ch.resize === "function") ch.resize();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Division-to-order-key mapping
|
||||
const DIV_TO_ORDER = {
|
||||
fscan: ['fscan'],
|
||||
@@ -156,6 +188,7 @@ let state = {
|
||||
renderSalesModelCharts(monthIdx);
|
||||
}
|
||||
renderSalesCategoryCharts(monthIdx);
|
||||
scheduleChartReflow();
|
||||
}
|
||||
|
||||
const omr = document.getElementById("orderModelRow");
|
||||
@@ -165,9 +198,11 @@ let state = {
|
||||
|
||||
if (isSectionActive(SECTION.ORDER)) {
|
||||
renderOrderSection();
|
||||
scheduleChartReflow();
|
||||
}
|
||||
if (isSectionActive(SECTION.FORECAST)) {
|
||||
renderForecastSection();
|
||||
scheduleChartReflow();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user