(async function () {
const INITIAL_HASH = location.hash;
const VERSION = new URLSearchParams(location.search).get("v") || "";
const STYLE_HREFS = [
"/hc-etms.sqygj.cn/static/css/chunk-elementUI.db8918ff.css",
"/hc-etms.sqygj.cn/static/css/chunk-libs.3dfb7769.css",
"/hc-etms.sqygj.cn/static/css/app.b5657ae9.css"
];
const SCRIPT_SRCS = [
"./webpack-runtime.js",
"/hc-etms.sqygj.cn/static/js/chunk-elementUI.19e378d9.js",
"/hc-etms.sqygj.cn/static/js/chunk-libs.d8d09258.js",
"/hc-etms.sqygj.cn/static/js/app.8e16015e.js"
];
let storageSeed = {};
let routeMap = {};
const MICROBRAIN_PRESETS = {
finance: {
eyebrow: "经营总览",
headline: "财务看板",
summary: "围绕收入、利润、现金与应收四个维度生成静态仪表盘,用于替代空态页。",
accent: "#2d76ff",
accentSoft: "rgba(45, 118, 255, 0.16)",
metrics: [
{ label: "本年累计收入", value: "¥2,056,000", delta: "较上月 +8.4%" },
{ label: "净利润率", value: "19.6%", delta: "经营状态良好" },
{ label: "经营现金流", value: "¥386,000", delta: "回款率 93.8%" },
{ label: "应收账款余额", value: "¥126,800", delta: "逾期项目 3 个" }
],
trendLabels: ["1月", "2月", "3月", "4月", "5月", "6月"],
trendSeries: [
{ label: "收入", color: "#2d76ff", values: [128, 136, 142, 156, 163, 172] },
{ label: "利润", color: "#2fc1a8", values: [22, 24, 26, 29, 31, 34] }
],
segments: [
{ label: "物业费", value: "54%", tone: "#2d76ff" },
{ label: "停车费", value: "21%", tone: "#20c997" },
{ label: "增值服务", value: "15%", tone: "#ffb74d" },
{ label: "其他收入", value: "10%", tone: "#a78bfa" }
],
rankingTitle: "项目贡献排行",
rankingRows: [
["循环花园一期", "¥462,000", "22.5%"],
["博万物", "¥318,000", "15.5%"],
["深圳市美好花园", "¥286,000", "13.9%"],
["循环科技三期", "¥244,000", "11.9%"]
],
alertsTitle: "财务提示",
alerts: [
{ title: "广州三俊物业管理有限公司", detail: "本月票据待核销 2 笔,建议财务复核。", level: "关注" },
{ title: "循环花园一期", detail: "停车费回款偏慢,较预算少 6.2%。", level: "预警" },
{ title: "江南世家", detail: "成本支出稳定,预算执行率 91%。", level: "正常" }
]
},
equipment: {
eyebrow: "资产运行",
headline: "设备看板",
summary: "补齐设备资产、维保执行、故障预警与能耗概览,替代原始“敬请期待”页面。",
accent: "#00a870",
accentSoft: "rgba(0, 168, 112, 0.16)",
metrics: [
{ label: "设备总台账", value: "1,286", delta: "在线率 97.3%" },
{ label: "本月维保完成", value: "214", delta: "完成率 92.1%" },
{ label: "待处理预警", value: "18", delta: "一级预警 3 条" },
{ label: "本月能耗", value: "18.6万kWh", delta: "较上月 -4.8%" }
],
trendLabels: ["1周", "2周", "3周", "4周", "5周", "6周"],
trendSeries: [
{ label: "工单关闭量", color: "#00a870", values: [26, 32, 29, 36, 39, 42] },
{ label: "新增预警", color: "#ff8a00", values: [14, 12, 11, 10, 8, 7] }
],
segments: [
{ label: "电梯", value: "34%", tone: "#00a870" },
{ label: "消防", value: "28%", tone: "#2d76ff" },
{ label: "供配电", value: "22%", tone: "#ff8a00" },
{ label: "给排水", value: "16%", tone: "#a78bfa" }
],
rankingTitle: "维保完成排行",
rankingRows: [
["循环花园一期", "48 项", "100%"],
["博万物", "41 项", "97%"],
["连城花园", "33 项", "94%"],
["美好花园", "28 项", "91%"]
],
alertsTitle: "设备预警",
alerts: [
{ title: "电梯系统", detail: "2 台电梯年检临期,需在 7 天内完成复检。", level: "预警" },
{ title: "消防泵房", detail: "巡检记录缺失 1 次,已通知项目负责人补录。", level: "关注" },
{ title: "供配电房", detail: "夜间负荷恢复正常,建议继续观察。", level: "正常" }
]
},
parkingLot: {
eyebrow: "车场经营",
headline: "车场看板",
summary: "展示车位利用、出入流量、收费表现与异常车牌,补齐停车运营视图。",
accent: "#7c4dff",
accentSoft: "rgba(124, 77, 255, 0.16)",
metrics: [
{ label: "总车位数", value: "2,146", delta: "固定车位 1,382" },
{ label: "当前占用率", value: "81.4%", delta: "较昨日 +2.6%" },
{ label: "本月停车收入", value: "¥486,300", delta: "临停车收入占比 38%" },
{ label: "异常进出记录", value: "12", delta: "黑名单 2 辆" }
],
trendLabels: ["08时", "10时", "12时", "14时", "16时", "18时"],
trendSeries: [
{ label: "进场车辆", color: "#7c4dff", values: [42, 58, 63, 71, 76, 69] },
{ label: "离场车辆", color: "#2fc1a8", values: [35, 46, 58, 64, 70, 66] }
],
segments: [
{ label: "固定月租", value: "62%", tone: "#7c4dff" },
{ label: "临停收费", value: "24%", tone: "#2d76ff" },
{ label: "新能源充电", value: "9%", tone: "#20c997" },
{ label: "其他", value: "5%", tone: "#ffb74d" }
],
rankingTitle: "项目车场收益排行",
rankingRows: [
["循环花园一期", "¥96,800", "88.4%"],
["博万物", "¥74,200", "82.7%"],
["美好花园", "¥68,500", "79.3%"],
["连城花园", "¥61,900", "75.1%"]
],
alertsTitle: "车场异常",
alerts: [
{ title: "粤B9X2F8", detail: "同一车辆 24 小时内重复进出 5 次,建议复核。", level: "关注" },
{ title: "循环花园一期", detail: "北门道闸离线 18 分钟,已恢复在线。", level: "预警" },
{ title: "博万物", detail: "新能源桩周转率较高,可考虑扩容。", level: "正常" }
]
},
supplierMicrobrain: {
eyebrow: "供应协同",
headline: "供应商微脑",
summary: "围绕供应商覆盖、履约、结算与风险预警生成静态仪表盘,替代空态页。",
accent: "#f97316",
accentSoft: "rgba(249, 115, 22, 0.16)",
metrics: [
{ label: "合作供应商", value: "86", delta: "活跃供应商 63 家" },
{ label: "本月履约率", value: "91.8%", delta: "较上月 +2.1%" },
{ label: "待结算金额", value: "¥268,400", delta: "本周待审核 7 笔" },
{ label: "风险预警", value: "6", delta: "高风险 2 家" }
],
trendLabels: ["1周", "2周", "3周", "4周", "5周", "6周"],
trendSeries: [
{ label: "履约评分", color: "#f97316", values: [78, 81, 84, 86, 88, 91] },
{ label: "结算完成率", color: "#2d76ff", values: [62, 66, 71, 75, 79, 83] }
],
segments: [
{ label: "保洁服务", value: "34%", tone: "#f97316" },
{ label: "安防服务", value: "26%", tone: "#2d76ff" },
{ label: "设备维保", value: "24%", tone: "#20c997" },
{ label: "绿化养护", value: "16%", tone: "#a78bfa" }
],
rankingTitle: "供应商履约排行",
rankingRows: [
["星河保洁服务有限公司", "96 分", "98%"],
["万嘉设备维保有限公司", "93 分", "94%"],
["城安安防科技有限公司", "91 分", "92%"],
["绿景园林服务有限公司", "89 分", "90%"]
],
alertsTitle: "供应风险提示",
alerts: [
{ title: "广州市三俊物业管理有限公司", detail: "2 笔结算资料待补充,建议本周内完成复核。", level: "关注" },
{ title: "万嘉设备维保有限公司", detail: "一项维保任务已逾期 3 天,需供应商经理跟进。", level: "预警" },
{ title: "星河保洁服务有限公司", detail: "本月履约稳定,建议纳入优质供应商池。", level: "正常" }
]
}
};
const CLOUD_REPORT_PRESETS = {
propertyFeeReport: {
title: "物业费收缴明细表",
eyebrow: "收费经营",
accent: "#2d76ff",
accentSoft: "rgba(45, 118, 255, 0.14)",
cards: [
{ label: "年度预算收缴", value: "¥4,268,000", detail: "预算达成 88.2%" },
{ label: "本月实收当月", value: "¥356,800", detail: "较上月 +6.5%" },
{ label: "本月收缴率", value: "92.4%", detail: "欠费项目 3 个" },
{ label: "本年累计收缴率", value: "89.6%", detail: "回款节奏稳定" }
],
headers: ["项目名称", "省/市/区", "年度预算收缴金额", "往年欠费金额", "往月欠费金额", "本月收缴往年欠费金额", "本月收缴往月欠费金额", "本月预收缴金额", "本月实收当月金额", "本月收缴率", "本年累计收缴率"],
rows: [
["循环花园一期", "湖北省/黄石市/下陆区", "¥886,000", "¥42,800", "¥31,500", "¥12,600", "¥9,800", "¥28,500", "¥74,300", "93.8%", "91.2%"],
["博万物", "广东省/深圳市/龙华区", "¥712,000", "¥36,400", "¥28,900", "¥8,200", "¥6,100", "¥21,600", "¥58,400", "89.5%", "87.1%"],
["美好花园", "广东省/深圳市/福田区", "¥658,000", "¥18,600", "¥22,300", "¥6,500", "¥5,400", "¥19,100", "¥54,900", "94.2%", "90.8%"],
["连城花园", "湖南省/长沙市/芙蓉区", "¥624,000", "¥15,900", "¥18,600", "¥4,600", "¥3,900", "¥16,700", "¥49,500", "91.7%", "88.5%"],
["循环科技三期", "天津市/河东区", "¥592,000", "¥12,300", "¥15,800", "¥3,800", "¥3,500", "¥15,200", "¥46,200", "90.6%", "86.9%"],
["江南世家一期", "湖北省/黄石市/下陆区", "¥516,000", "¥10,800", "¥13,600", "¥2,700", "¥2,100", "¥12,600", "¥41,700", "88.4%", "85.7%"]
]
},
parkingLotReport: {
title: "车场列表",
eyebrow: "车场运营",
accent: "#7c4dff",
accentSoft: "rgba(124, 77, 255, 0.14)",
cards: [
{ label: "今日进出总量", value: "612 / 584", detail: "高峰出现在 16:00" },
{ label: "本月临停费", value: "¥186,400", detail: "较上月 +8.1%" },
{ label: "本月月卡费", value: "¥302,800", detail: "固定车位 1,382 个" },
{ label: "异常开闸率", value: "1.8%", detail: "可疑收费 4 笔" }
],
headers: ["小区名称", "省/市/区", "今日进出数量", "今日临停费", "本月临停费", "本月月卡费", "今日异常开闸数", "今日可疑收费", "累计异常开闸次数", "累计可疑收费", "运维工单", "当月收缴率", "累计收缴率", "异常开闸率"],
rows: [
["循环花园一期", "湖北省/黄石市/下陆区", "126 / 118", "¥6,420", "¥39,800", "¥62,400", "2", "1", "16", "4", "3", "95.6%", "93.4%", "1.6%"],
["博万物", "广东省/深圳市/龙华区", "98 / 96", "¥4,980", "¥32,600", "¥58,300", "1", "0", "9", "2", "2", "92.3%", "90.8%", "1.1%"],
["美好花园", "广东省/深圳市/福田区", "114 / 105", "¥5,760", "¥36,900", "¥61,700", "3", "1", "21", "6", "4", "94.1%", "91.7%", "2.4%"],
["连城花园", "湖南省/长沙市/芙蓉区", "87 / 82", "¥4,120", "¥28,300", "¥54,800", "2", "1", "13", "3", "2", "90.7%", "88.9%", "1.9%"],
["循环科技三期", "天津市/河东区", "73 / 69", "¥3,560", "¥24,800", "¥49,600", "1", "1", "8", "2", "1", "89.8%", "87.2%", "1.4%"]
]
},
planTaskReport: {
title: "计划工单执行总览",
eyebrow: "计划执行",
accent: "#00a870",
accentSoft: "rgba(0, 168, 112, 0.14)",
cards: [
{ label: "本月应完成", value: "1,286", detail: "全部项目口径" },
{ label: "本月完成", value: "1,214", detail: "完成率 94.4%" },
{ label: "超时仍未完成", value: "28", detail: "需持续跟进" },
{ label: "人工验收合格率", value: "96.2%", detail: "工作达标率 91.8%" }
],
headers: ["项目名称", "本月应完成", "本月未完成", "本月完成", "完成率", "已报备工单数", "实际完成率", "提前完成", "超时完成", "超时仍未完成", "应验收", "人工合格", "合格", "未验收", "工作达标率"],
rows: [
["循环花园一期", "268", "12", "256", "95.5%", "18", "94.8%", "162", "24", "6", "238", "228", "231", "7", "93.2%"],
["博万物", "214", "15", "199", "93.0%", "16", "91.8%", "116", "29", "8", "184", "175", "178", "6", "89.7%"],
["美好花园", "198", "9", "189", "95.4%", "11", "94.0%", "121", "18", "5", "176", "169", "170", "4", "92.5%"],
["连城花园", "176", "14", "162", "92.0%", "13", "90.6%", "94", "26", "7", "150", "143", "145", "5", "88.9%"],
["循环科技三期", "164", "11", "153", "93.3%", "9", "92.7%", "88", "22", "2", "141", "136", "137", "3", "90.4%"],
["江南世家一期", "146", "11", "135", "92.5%", "7", "91.2%", "73", "19", "0", "129", "124", "125", "2", "91.1%"]
]
},
workOrderReport: {
title: "非计划工单执行概览",
eyebrow: "服务响应",
accent: "#ff8a00",
accentSoft: "rgba(255, 138, 0, 0.14)",
cards: [
{ label: "来自住户工单", value: "126", detail: "本月新增 18 单" },
{ label: "来自内控工单", value: "284", detail: "闭环率 83.5%" },
{ label: "历史未完成", value: "58", detail: "较上周 -7 单" },
{ label: "综合执行率", value: "86.9%", detail: "重点项目需跟进" }
],
headers: ["项目名称", "来自住户", "已完成", "未完成", "执行率", "历史未完成数", "历史当月完成数", "来自内控", "已完成", "未完成", "执行率"],
rows: [
["博万物", "23", "18", "5", "78.3%", "46", "12", "80", "69", "11", "86.3%"],
["江南世家一期", "16", "15", "1", "93.8%", "4", "3", "21", "18", "3", "85.7%"],
["循环花园一期", "28", "24", "4", "85.7%", "3", "4", "64", "56", "8", "87.5%"],
["美好花园", "19", "17", "2", "89.5%", "2", "1", "43", "37", "6", "86.0%"],
["连城花园", "14", "12", "2", "85.7%", "1", "0", "31", "27", "4", "87.1%"]
]
},
dataReport: {
title: "工单耗时统计总览",
eyebrow: "履约时效",
accent: "#20c997",
accentSoft: "rgba(32, 201, 151, 0.14)",
cards: [
{ label: "工单总数量", value: "418", detail: "非计划 + 服务工单" },
{ label: "平均受理耗时", value: "00:18:42", detail: "低于标准 12.6%" },
{ label: "平均处理耗时", value: "03:16:28", detail: "本月效率稳定" },
{ label: "平均完成耗时", value: "08:42:10", detail: "满意度 94.1%" }
],
headers: ["项目名称", "工单总数量", "受理工单数量", "规定受理耗时", "实际受理平均耗时", "处理工单数量", "规定处理耗时", "实际处理平均耗时", "已评价工单数量", "规定完成耗时", "实际完成平均耗时"],
rows: [
["循环花园一期", "84", "82", "00:30:00", "00:16:40", "80", "04:00:00", "03:12:15", "76", "12:00:00", "08:31:12"],
["美好花园", "73", "71", "00:30:00", "00:18:05", "70", "04:00:00", "03:08:49", "65", "12:00:00", "08:12:44"],
["循环科技一期", "62", "60", "00:30:00", "00:19:14", "58", "04:00:00", "03:26:37", "54", "12:00:00", "08:55:10"],
["连城花园", "57", "56", "00:30:00", "00:17:28", "55", "04:00:00", "03:11:26", "51", "12:00:00", "08:20:53"],
["博万物", "96", "93", "00:30:00", "00:20:32", "90", "04:00:00", "03:48:21", "83", "12:00:00", "09:04:15"]
]
},
consumeReport: {
title: "耗能报表总览",
eyebrow: "能耗经营",
accent: "#14b8a6",
accentSoft: "rgba(20, 184, 166, 0.14)",
cards: [
{ label: "本月总耗能", value: "186.4万kWh", detail: "较上月 -4.3%" },
{ label: "单位面积能耗", value: "6.45", detail: "kWh/㎡" },
{ label: "高耗能项目", value: "3", detail: "需重点跟进" },
{ label: "节能改善率", value: "7.8%", detail: "季度目标达成" }
],
headers: ["项目名称", "区域", "本月电耗", "本月水耗", "本月气耗", "单位面积能耗", "同比变化", "节能措施完成率"],
rows: [
["循环花园一期", "湖北省/黄石市/下陆区", "38.6万kWh", "12,860m³", "4,320m³", "6.22", "-5.1%", "92%"],
["博万物", "广东省/深圳市/龙华区", "31.4万kWh", "10,240m³", "3,280m³", "6.58", "-3.6%", "88%"],
["美好花园", "广东省/深圳市/福田区", "28.2万kWh", "8,930m³", "2,960m³", "6.11", "-6.4%", "91%"],
["连城花园", "湖南省/长沙市/芙蓉区", "24.8万kWh", "7,860m³", "2,540m³", "6.37", "-2.1%", "84%"],
["循环科技三期", "天津市/河东区", "19.7万kWh", "6,220m³", "1,980m³", "6.03", "-4.8%", "86%"]
]
},
jobGridReport: {
title: "作业网格台账报表",
eyebrow: "网格履约",
accent: "#6366f1",
accentSoft: "rgba(99, 102, 241, 0.14)",
cards: [
{ label: "本月应完成数", value: "2,184", detail: "覆盖 126 个网格" },
{ label: "本月完成次数", value: "2,046", detail: "完成率 93.7%" },
{ label: "需保持跟进", value: "64", detail: "重点对象 9 个" },
{ label: "评分均分", value: "4.72", detail: "低分评价 13 条" }
],
headers: ["项目名称", "空间", "网格", "场景归属", "作业对象类型", "作业对象", "所属月份", "SPU数量", "本月应完成数", "本月完成次数", "本月提前完成", "本月超时完成", "需保持跟进", "完成基础云豆R1价值", "评分均分"],
rows: [
["循环花园一期", "公共区域", "A-01", "清洁卫生", "楼栋", "1号楼", "2026-04", "18", "186", "174", "112", "18", "6", "12,680", "4.86"],
["博万物", "设备间", "E-08", "设备管理", "设备", "消防泵房", "2026-04", "12", "148", "136", "79", "22", "5", "10,240", "4.68"],
["美好花园", "车行流线", "P-03", "车场运营", "车位", "地下二层", "2026-04", "15", "164", "156", "96", "17", "4", "11,360", "4.71"],
["连城花园", "外围道路", "S-12", "安防管理", "巡更点", "北门岗亭", "2026-04", "9", "132", "121", "73", "16", "8", "8,920", "4.55"],
["循环科技三期", "绿化区域", "G-06", "绿化管理", "绿植", "中央花园", "2026-04", "11", "118", "109", "68", "13", "5", "7,860", "4.79"]
]
},
contractPlanReport: {
title: "合同计划执行报表",
eyebrow: "合同履约",
accent: "#f97316",
accentSoft: "rgba(249, 115, 22, 0.14)",
cards: [
{ label: "本月应完成工单", value: "864", detail: "合同口径" },
{ label: "本月完成工单", value: "803", detail: "完成率 92.9%" },
{ label: "超时仍未完成", value: "19", detail: "需持续跟进" },
{ label: "已完成云豆价值", value: "¥182,400", detail: "较上月 +5.8%" }
],
headers: ["项目名称", "合同名称", "计划类型", "本月应完成工单数", "本月完成工单数", "本月未完成工单数", "本月提前工单数", "本月超时完成工单数", "本月超时仍未完成", "需保持跟进", "已完成基础云豆R1价值", "评分均分"],
rows: [
["循环花园一期", "循环花园物业服务合同", "全部", "186", "176", "10", "102", "14", "3", "4", "¥46,800", "4.83"],
["博万物", "博万物物业服务合同", "全部", "154", "141", "13", "78", "19", "4", "6", "¥39,200", "4.61"],
["美好花园", "美好花园综合服务合同", "全部", "148", "139", "9", "82", "17", "2", "5", "¥34,600", "4.76"],
["连城花园", "连城花园基础服务合同", "全部", "132", "121", "11", "69", "16", "5", "3", "¥31,900", "4.52"],
["循环科技三期", "循环科技三期运营合同", "全部", "126", "118", "8", "67", "15", "5", "1", "¥29,900", "4.69"]
]
},
contractGuaranteeReport: {
title: "合同保障报表",
eyebrow: "合同保障",
accent: "#ef4444",
accentSoft: "rgba(239, 68, 68, 0.14)",
cards: [
{ label: "有效合同数", value: "42", detail: "覆盖 11 个项目" },
{ label: "有效作业区域", value: "186", detail: "PTU 总数 94" },
{ label: "基础作业时长", value: "9,842h", detail: "合同保障口径" },
{ label: "基础云豆价值", value: "¥168,320", detail: "较上月 +4.2%" }
],
headers: ["项目名称", "合同名称", "合同SPU", "有效作业区域", "有效PTU", "有效作业人数", "基础作业时长", "基础云豆R1价值", "清洁计划数", "设备计划数", "电梯计划数", "主动服务计划数"],
rows: [
["博万物", "博万物物业服务合同", "162", "9", "11", "36", "4,960h", "¥71,512", "27", "5", "0", "1"],
["美好花园", "美好花园综合服务合同", "148", "10", "10", "29", "3,820h", "¥52,360", "18", "4", "1", "2"],
["循环花园一期", "循环花园基础合同", "136", "8", "9", "24", "2,940h", "¥24,180", "16", "3", "1", "2"],
["连城花园", "连城花园服务合同", "118", "7", "8", "21", "2,186h", "¥15,940", "12", "2", "1", "1"],
["循环科技三期", "循环科技三期运营合同", "102", "6", "7", "18", "1,968h", "¥13,420", "10", "2", "0", "1"]
]
},
detailedContractGuaranteeReport: {
title: "合同保障明细报表",
eyebrow: "合同明细",
accent: "#f59e0b",
accentSoft: "rgba(245, 158, 11, 0.14)",
cards: [
{ label: "合同计划SPU", value: "286", detail: "全部计划类型" },
{ label: "计划数量", value: "248", detail: "执行口径汇总" },
{ label: "有效作业人数", value: "96", detail: "多项目覆盖" },
{ label: "基础云豆价值", value: "¥112,480", detail: "较上月 +3.6%" }
],
headers: ["项目名称", "合同名称", "计划类型", "合同计划SPU", "计划数量", "有效作业区域", "有效作业人数", "基础作业时长", "基础云豆R1价值"],
rows: [
["博万物", "博万物物业服务合同", "全部", "42", "35", "9", "36", "4,960h", "¥71,512"],
["美好花园", "美好花园综合服务合同", "全部", "31", "26", "8", "29", "3,820h", "¥52,360"],
["循环花园一期", "循环花园基础合同", "全部", "24", "22", "7", "24", "2,940h", "¥24,180"],
["连城花园", "连城花园服务合同", "全部", "18", "16", "6", "21", "2,186h", "¥15,940"],
["循环科技三期", "循环科技三期运营合同", "全部", "15", "13", "5", "18", "1,968h", "¥13,420"]
]
},
officialAccount: {
title: "公众号拉新报表",
eyebrow: "客户运营",
accent: "#06b6d4",
accentSoft: "rgba(6, 182, 212, 0.14)",
cards: [
{ label: "区间新增数", value: "186", detail: "近 30 天" },
{ label: "已绑住户数", value: "1,428", detail: "绑定率 76.9%" },
{ label: "员工绑定数", value: "214", detail: "员工绑定率 93.1%" },
{ label: "未绑住户数", value: "428", detail: "重点项目待推进" }
],
headers: ["项目名称", "区间新增数", "总房屋数", "总住户数", "已绑住户数", "未绑住户数", "员工应绑定数", "员工绑定数", "员工绑定率"],
rows: [
["江南世家一期", "42", "286", "418", "352", "66", "24", "23", "95.8%"],
["博万物", "38", "254", "396", "301", "95", "28", "25", "89.3%"],
["循环花园一期", "34", "232", "348", "276", "72", "22", "21", "95.5%"],
["美好花园", "29", "218", "315", "248", "67", "19", "18", "94.7%"],
["连城花园", "22", "184", "268", "191", "77", "17", "15", "88.2%"]
]
},
collectionTracking: {
title: "催收跟踪报表",
eyebrow: "收费跟踪",
accent: "#8b5cf6",
accentSoft: "rgba(139, 92, 246, 0.14)",
cards: [
{ label: "催收户数", value: "412", detail: "重点欠费房屋 86 户" },
{ label: "及时拜访数量", value: "186", detail: "拜访及时率 71.5%" },
{ label: "电话 / 微信", value: "268 / 94", detail: "多通道覆盖" },
{ label: "律师函 / 起诉", value: "18 / 6", detail: "高风险项目跟进" }
],
headers: ["项目名称", "催收户数", "欠费房屋数", "普通实收", "转实收", "电话", "微信", "上门", "短信", "律师函", "起诉", "及时拜访数量", "拜访数量", "拜访及时率"],
rows: [
["沈鑫小区", "38", "42", "12", "6", "24", "10", "5", "18", "2", "0", "21", "28", "75.0%"],
["龚浪小区", "64", "87", "16", "8", "36", "14", "9", "22", "3", "1", "31", "44", "70.5%"],
["陈丽娟小区", "29", "24", "8", "3", "18", "6", "2", "11", "1", "0", "12", "17", "70.6%"],
["谷粒多小区", "18", "16", "4", "1", "12", "3", "1", "7", "0", "0", "8", "12", "66.7%"],
["博万物", "96", "118", "26", "12", "58", "21", "15", "33", "5", "2", "44", "63", "69.8%"]
]
},
collectionRate: {
title: "企业收费项报表",
eyebrow: "收费分析",
accent: "#3b82f6",
accentSoft: "rgba(59, 130, 246, 0.14)",
cards: [
{ label: "应收合计", value: "¥1,826,400", detail: "本年 + 往年" },
{ label: "实收合计", value: "¥1,543,800", detail: "综合收缴率 84.5%" },
{ label: "欠费合计", value: "¥282,600", detail: "环比 -5.4%" },
{ label: "户数收缴率", value: "81.3%", detail: "实时校验已开" }
],
headers: ["项目名称", "收费项目", "本月应收", "本年应收", "往年应收", "应收合计", "本月实收", "本年实收", "往年实收", "欠费合计", "实收合计", "综合收缴率", "户数收缴率"],
rows: [
["博万物", "住宅水电", "¥82,600", "¥426,000", "¥18,400", "¥444,400", "¥71,200", "¥382,600", "¥9,800", "¥52,000", "¥392,400", "88.3%", "83.2%"],
["循环花园一期", "物业管理费", "¥96,800", "¥518,000", "¥26,200", "¥544,200", "¥84,900", "¥462,800", "¥13,600", "¥67,800", "¥476,400", "87.5%", "84.7%"],
["美好花园", "停车服务费", "¥68,500", "¥392,000", "¥14,800", "¥406,800", "¥57,200", "¥338,400", "¥9,200", "¥59,200", "¥347,600", "85.4%", "80.9%"],
["连城花园", "综合服务费", "¥54,200", "¥286,000", "¥9,600", "¥295,600", "¥46,300", "¥242,700", "¥6,800", "¥46,100", "¥249,500", "84.4%", "79.8%"],
["江南世家一期", "园区服务费", "¥43,100", "¥204,600", "¥6,800", "¥211,400", "¥36,800", "¥174,900", "¥5,600", "¥30,900", "¥180,500", "85.4%", "78.6%"]
]
},
visitWorkReport: {
title: "拜访工作报表",
eyebrow: "客户拜访",
accent: "#22c55e",
accentSoft: "rgba(34, 197, 94, 0.14)",
cards: [
{ label: "应拜访总数", value: "214", detail: "电话 + 上门" },
{ label: "按时拜访", value: "162", detail: "及时率 75.7%" },
{ label: "已回款金额", value: "¥286,400", detail: "回款户数 118" },
{ label: "超时拜访", value: "24", detail: "未拜访 28 户" }
],
headers: ["项目名称", "拜访方式", "来源", "应拜访", "应付金额(元)", "未拜访", "按时拜访", "超时拜访", "未回款(户)", "已回款(户)", "已回款金额(元)"],
rows: [
["博万物", "上门", "拜访智能体", "18", "¥32,600", "3", "12", "3", "9", "9", "¥18,400"],
["博万物", "电话", "分类布置智能体", "36", "¥58,900", "8", "22", "6", "18", "18", "¥41,600"],
["循环花园一期", "电话", "拜访智能体", "42", "¥64,200", "6", "31", "5", "17", "25", "¥58,900"],
["美好花园", "上门", "拜访智能体", "27", "¥41,800", "4", "19", "4", "11", "16", "¥36,700"],
["连城花园", "电话", "分类布置智能体", "24", "¥37,300", "7", "16", "1", "14", "10", "¥24,100"]
]
}
};
const STATIC_PAGE_PRESETS = {
qualification: {
eyebrow: "资质匹配",
title: "人员资质匹配总览",
summary: "补齐人员证书、岗位要求与到期预警,替代空态页。",
accent: "#2563eb",
accentSoft: "rgba(37, 99, 235, 0.14)",
cards: [
{ label: "在岗人员", value: "186", detail: "参与资质校验" },
{ label: "即将到期证书", value: "12", detail: "30 天内到期" },
{ label: "岗位匹配率", value: "94.8%", detail: "高于月目标" },
{ label: "缺证人数", value: "7", detail: "需尽快补齐" }
],
headers: ["项目名称", "姓名", "岗位", "证书名称", "证书到期日", "匹配状态", "整改建议"],
rows: [
["循环花园一期", "郭晓", "环境巡查管家", "消防设施操作员", "2026-05-12", "匹配", "保持跟进"],
["博万物", "何琪", "设备管理员", "特种设备安全管理员", "2026-04-18", "预警", "安排续证"],
["美好花园", "陈谷先", "财务中心负责人", "会计从业资格", "2026-09-30", "匹配", "正常"],
["连城花园", "蒋琦", "java 开发工程师", "信息系统项目管理师", "2026-07-08", "匹配", "正常"],
["江南世家一期", "曾丽娜", "客服巡查管家", "物业管理员", "2026-04-22", "待补齐", "补齐岗位证书"]
]
},
employeeQuitReport: {
eyebrow: "人员流动",
title: "员工离任报告",
summary: "汇总离任人员、离任类型与交接完成情况,替代空态页。",
accent: "#dc2626",
accentSoft: "rgba(220, 38, 38, 0.14)",
cards: [
{ label: "本月离任人数", value: "9", detail: "较上月 -2" },
{ label: "高风险离任", value: "2", detail: "核心岗位需接替" },
{ label: "交接完成率", value: "88.9%", detail: "资料回收正常" },
{ label: "平均在岗月数", value: "16.4", detail: "整体稳定" }
],
headers: ["项目名称", "姓名", "岗位", "离任类型", "离任日期", "交接状态", "备注"],
rows: [
["循环花园一期", "张磊", "客服巡查管家", "主动离职", "2026-04-02", "已完成", "已完成物资交接"],
["博万物", "林婉", "设备管理员", "岗位调整", "2026-03-29", "进行中", "待设备台账确认"],
["美好花园", "刘鑫", "市场专员", "合同到期", "2026-03-27", "已完成", "无异常"],
["连城花园", "周宇", "保洁班长", "主动离职", "2026-03-25", "已完成", "补充访谈记录"],
["江南世家一期", "何丽", "财务专员", "试用期离岗", "2026-03-20", "待处理", "安排补岗"]
]
},
operationLog: {
eyebrow: "系统管理",
title: "操作日志总览",
summary: "补齐关键操作日志、用户行为与风险动作提示,替代空态页。",
accent: "#7c3aed",
accentSoft: "rgba(124, 58, 237, 0.14)",
cards: [
{ label: "今日操作次数", value: "428", detail: "登录用户 36 人" },
{ label: "高风险操作", value: "5", detail: "重点复核" },
{ label: "模块覆盖数", value: "18", detail: "近 24 小时" },
{ label: "最近同步", value: "15:32", detail: "日志服务正常" }
],
headers: ["时间", "用户", "模块", "动作", "IP", "结果", "说明"],
rows: [
["2026-04-04 15:28:32", "循环科技企业管理后台", "角色权限管理", "编辑角色", "113.88.21.6", "成功", "更新项目角色权限"],
["2026-04-04 14:57:10", "郭晓", "人事档案", "导入档案", "113.88.21.9", "成功", "导入 12 条记录"],
["2026-04-04 14:33:48", "陈谷先", "财务数据", "修改指标", "113.88.21.12", "成功", "更新利润口径"],
["2026-04-04 13:49:05", "林婉", "分公司管理", "新增分公司", "113.88.21.7", "待审核", "创建广州运营主体"],
["2026-04-04 11:16:26", "何琪", "设备看板", "导出报表", "113.88.21.15", "成功", "导出设备月报"]
]
},
questionBank: {
eyebrow: "满意度题库",
title: "调查题库总览",
summary: "重建题库统计、题目类型与启用状态,替代空态页。",
accent: "#0ea5e9",
accentSoft: "rgba(14, 165, 233, 0.14)",
cards: [
{ label: "题库总数", value: "128", detail: "启用题目 116" },
{ label: "评分题", value: "36", detail: "权重题 8 个" },
{ label: "低分标签", value: "14", detail: "用于整改跟踪" },
{ label: "最近更新", value: "04-03", detail: "客户运营同步" }
],
headers: ["题目名称", "题型", "适用场景", "权重", "状态", "最近更新", "维护人"],
rows: [
["您对客服响应速度是否满意?", "评分题", "工单服务", "15%", "启用", "2026-04-03", "李佑聪"],
["您对停车秩序是否满意?", "评分题", "车场运营", "10%", "启用", "2026-04-02", "循环科技企业管理后台"],
["保洁服务是否达到预期?", "单选题", "环境管理", "8%", "启用", "2026-03-28", "郭晓"],
["是否愿意继续推荐本项目?", "NPS题", "综合满意度", "20%", "启用", "2026-03-22", "陈谷先"],
["请填写需要改进的问题", "文本题", "整改跟踪", "-", "草稿", "2026-03-18", "何琪"]
]
},
report: {
eyebrow: "满意度分析",
title: "调查报告总览",
summary: "按项目汇总问卷样本、满意度得分与低分预警,替代空态页。",
accent: "#14b8a6",
accentSoft: "rgba(20, 184, 166, 0.14)",
cards: [
{ label: "有效样本", value: "2,418", detail: "近 30 天" },
{ label: "综合满意度", value: "4.63", detail: "较上月 +0.08" },
{ label: "低分预警", value: "18", detail: "需跟进整改" },
{ label: "整改完成率", value: "82.4%", detail: "闭环改善中" }
],
headers: ["项目名称", "问卷名称", "样本数", "满意度", "低分数量", "整改任务", "状态"],
rows: [
["循环花园一期", "4 月综合满意度", "486", "4.72", "2", "4", "已发布"],
["博万物", "4 月停车服务满意度", "362", "4.58", "5", "7", "已发布"],
["美好花园", "4 月客服满意度", "318", "4.66", "3", "5", "已发布"],
["连城花园", "4 月环境满意度", "276", "4.49", "6", "8", "整改中"],
["江南世家一期", "4 月综合满意度", "241", "4.53", "2", "3", "已发布"]
]
},
tracking: {
eyebrow: "整改闭环",
title: "整改跟踪总览",
summary: "聚合低分问题、责任人和整改进度,替代空态页。",
accent: "#f97316",
accentSoft: "rgba(249, 115, 22, 0.14)",
cards: [
{ label: "待整改问题", value: "26", detail: "逾期 4 项" },
{ label: "本周关闭", value: "18", detail: "闭环效率提升" },
{ label: "责任人数量", value: "11", detail: "跨项目协同" },
{ label: "按期完成率", value: "84.6%", detail: "需持续跟进" }
],
headers: ["项目名称", "问题类型", "责任人", "整改截止日", "整改进度", "状态", "备注"],
rows: [
["循环花园一期", "客服响应慢", "郭晓", "2026-04-10", "80%", "处理中", "需补充回访"],
["博万物", "停车秩序差", "何琪", "2026-04-08", "60%", "预警", "晚高峰加派巡查"],
["美好花园", "保洁质量波动", "曾丽娜", "2026-04-09", "100%", "已完成", "已复检通过"],
["连城花园", "绿化修剪不及时", "周宇", "2026-04-12", "40%", "处理中", "待供应商进场"],
["江南世家一期", "工单回访不充分", "陈谷先", "2026-04-11", "90%", "待验证", "等待客户确认"]
]
},
assessment: {
eyebrow: "人才测评",
title: "人才测评总览",
summary: "聚合测评对象、岗位画像与测评分布,替代空态页。",
accent: "#8b5cf6",
accentSoft: "rgba(139, 92, 246, 0.14)",
cards: [
{ label: "测评人数", value: "142", detail: "近 30 天" },
{ label: "综合胜任度", value: "84.2", detail: "百分制" },
{ label: "高潜人才", value: "18", detail: "建议重点培养" },
{ label: "待复评人数", value: "9", detail: "低于岗位基线" }
],
headers: ["项目名称", "姓名", "岗位", "能力模型", "测评得分", "胜任等级", "建议动作"],
rows: [
["循环花园一期", "郭晓", "环境巡查管家", "服务履约模型", "88", "优秀", "纳入主管培养"],
["博万物", "何琪", "设备管理员", "设备运营模型", "82", "良好", "补充故障诊断训练"],
["美好花园", "陈谷先", "财务中心负责人", "经营管理模型", "91", "优秀", "承担跨项目辅导"],
["连城花园", "蒋琦", "java 开发工程师", "技术支持模型", "86", "良好", "推进专项项目实践"],
["江南世家一期", "曾丽娜", "客服巡查管家", "客户服务模型", "74", "关注", "安排二次复评"]
]
}
};
function hydrateCompanyInfoFrame(doc) {
try {
const companyInfo = JSON.parse(storageSeed.companyInfo || "{}");
const userInfo = JSON.parse(storageSeed.userInfo || "{}");
const labelMap = {
"企业全称": companyInfo.fullName || "",
"企业简称": companyInfo.abbreviation || "",
"企业ID": companyInfo.id || "",
"法人代表联系方式": companyInfo.mobile || "",
"企业付款人": companyInfo.payer || "",
"开户行": companyInfo.publicBank || "",
"企业地址": companyInfo.address || "",
"企业微信密钥": companyInfo.weixinSecret || "",
"企业统一社会信用代码": companyInfo.creditCode || "",
"企业法人代表": companyInfo.legalPerson || "",
"企业创建人账号": userInfo.accountName || storageSeed.fromPhone || "",
"企业邮编": companyInfo.postalCode || "",
"付款人联系电话": companyInfo.payerMobile || "",
"银行账号": companyInfo.publicBankNo || "",
"企业微信ID(CorpID)": companyInfo.weixinCorpId || ""
};
doc.querySelectorAll(".el-form-item").forEach((item) => {
const labelEl = item.querySelector(".el-form-item__label");
const inputEl = item.querySelector("input.el-input__inner");
if (!labelEl || !inputEl) {
return;
}
const label = (labelEl.textContent || "").trim();
if (!(label in labelMap)) {
return;
}
const value = String(labelMap[label] ?? "");
inputEl.value = value;
inputEl.setAttribute("value", value);
inputEl.placeholder = value;
inputEl.style.color = "#2c3e50";
inputEl.style.fontWeight = "500";
inputEl.style.backgroundColor = "#fff";
});
const infoImages = [...doc.querySelectorAll(".companyMain .companyInfo img.img")];
if (infoImages[0] && companyInfo.logo) {
infoImages[0].src = companyInfo.logo;
}
if (infoImages[1] && companyInfo.miniCode) {
infoImages[1].src = companyInfo.miniCode;
}
} catch (_error) {
// ignore
}
}
function buildLinePath(values, width, height, padding) {
const max = Math.max(...values);
const min = Math.min(...values);
const span = Math.max(max - min, 1);
return values
.map((value, index) => {
const x = padding + (index * (width - padding * 2)) / Math.max(values.length - 1, 1);
const y = height - padding - ((value - min) / span) * (height - padding * 2);
return `${index === 0 ? "M" : "L"}${x.toFixed(1)} ${y.toFixed(1)}`;
})
.join(" ");
}
function buildAreaPoints(values, width, height, padding) {
const max = Math.max(...values);
const min = Math.min(...values);
const span = Math.max(max - min, 1);
const points = values.map((value, index) => {
const x = padding + (index * (width - padding * 2)) / Math.max(values.length - 1, 1);
const y = height - padding - ((value - min) / span) * (height - padding * 2);
return `${x.toFixed(1)},${y.toFixed(1)}`;
});
points.push(`${width - padding},${height - padding}`, `${padding},${height - padding}`);
return points.join(" ");
}
function buildTrendSvg(seriesList, labels) {
const width = 560;
const height = 220;
const padding = 24;
const allValues = seriesList.flatMap((item) => item.values);
const max = Math.max(...allValues);
const min = Math.min(...allValues);
const span = Math.max(max - min, 1);
const guides = [0, 0.25, 0.5, 0.75, 1].map((ratio) => {
const y = padding + ratio * (height - padding * 2);
const value = Math.round(max - ratio * span);
return `
${value}
`;
});
const xLabels = labels
.map((label, index) => {
const x = padding + (index * (width - padding * 2)) / Math.max(labels.length - 1, 1);
return `${label}`;
})
.join("");
const paths = seriesList
.map((item, index) => {
const areaOpacity = index === 0 ? 0.14 : 0.08;
return `
${item.values
.map((value, valueIndex) => {
const x = padding + (valueIndex * (width - padding * 2)) / Math.max(item.values.length - 1, 1);
const y = height - padding - ((value - min) / span) * (height - padding * 2);
return ``;
})
.join("")}
`;
})
.join("");
return `
`;
}
function renderMicrobrainDashboard(doc, type) {
const preset = MICROBRAIN_PRESETS[type];
if (!preset) {
return;
}
const host =
doc.querySelector(".app-main > div") ||
doc.querySelector(".app-main > section") ||
doc.querySelector(".app-main") ||
doc.body;
if (!host) {
return;
}
if (!doc.getElementById("__codex_microbrain_style__")) {
const style = doc.createElement("style");
style.id = "__codex_microbrain_style__";
style.textContent = `
.waitMain {
display: none !important;
}
#__codex_microbrain_dashboard__ {
margin-top: 18px;
padding: 20px 22px 24px;
border-radius: 20px;
background:
radial-gradient(circle at top right, rgba(45, 118, 255, 0.12), transparent 28%),
linear-gradient(180deg, #ffffff 0%, #f7faff 100%);
border: 1px solid rgba(17, 37, 63, 0.06);
box-shadow: 0 18px 42px rgba(17, 37, 63, 0.08);
}
.codex-microbrain-head {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 20px;
margin-bottom: 20px;
}
.codex-microbrain-eyebrow {
display: inline-flex;
align-items: center;
padding: 4px 10px;
border-radius: 999px;
margin-bottom: 10px;
font-size: 12px;
color: #5b6f92;
background: rgba(17, 37, 63, 0.06);
}
.codex-microbrain-head h3 {
margin: 0 0 6px;
font-size: 28px;
color: #12233d;
}
.codex-microbrain-head p {
margin: 0;
max-width: 660px;
color: #6d7d97;
font-size: 14px;
}
.codex-microbrain-badge {
padding: 10px 14px;
border-radius: 14px;
color: #35517d;
font-size: 12px;
background: rgba(255,255,255,0.8);
border: 1px solid rgba(17,37,63,0.08);
box-shadow: inset 0 1px 0 rgba(255,255,255,0.8);
}
.codex-microbrain-metrics {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 14px;
margin-bottom: 18px;
}
.codex-microbrain-metric {
padding: 16px 18px;
border-radius: 18px;
background: rgba(255,255,255,0.82);
border: 1px solid rgba(17,37,63,0.06);
box-shadow: 0 12px 28px rgba(17,37,63,0.06);
}
.codex-microbrain-metric span {
display: block;
color: #7d8ca5;
font-size: 13px;
}
.codex-microbrain-metric strong {
display: block;
margin: 8px 0 6px;
color: #12233d;
font-size: 28px;
line-height: 1.1;
}
.codex-microbrain-metric small {
color: #4e6b98;
font-size: 12px;
}
.codex-microbrain-layout {
display: grid;
grid-template-columns: minmax(0, 1.6fr) minmax(320px, 0.95fr);
gap: 16px;
}
.codex-microbrain-panel {
padding: 18px 18px 16px;
border-radius: 18px;
background: rgba(255,255,255,0.92);
border: 1px solid rgba(17,37,63,0.06);
}
.codex-microbrain-panel h4 {
margin: 0 0 14px;
color: #152742;
font-size: 16px;
}
.codex-microbrain-legend {
display: flex;
gap: 14px;
flex-wrap: wrap;
margin-bottom: 12px;
}
.codex-microbrain-legend span {
display: inline-flex;
align-items: center;
gap: 6px;
color: #71829d;
font-size: 12px;
}
.codex-microbrain-dot {
width: 9px;
height: 9px;
border-radius: 50%;
}
.codex-microbrain-chart {
width: 100%;
height: 238px;
}
.codex-microbrain-segments {
display: grid;
gap: 12px;
}
.codex-microbrain-segment {
display: grid;
grid-template-columns: 88px 1fr 48px;
align-items: center;
gap: 10px;
color: #4d607f;
font-size: 13px;
}
.codex-microbrain-track {
overflow: hidden;
height: 10px;
border-radius: 999px;
background: #eef3fb;
}
.codex-microbrain-fill {
height: 100%;
border-radius: inherit;
}
.codex-microbrain-table table {
width: 100%;
border-collapse: collapse;
}
.codex-microbrain-table th,
.codex-microbrain-table td {
padding: 12px 8px;
border-bottom: 1px solid rgba(17,37,63,0.06);
text-align: left;
color: #3f5477;
font-size: 13px;
}
.codex-microbrain-table th {
color: #8b9ab3;
font-size: 12px;
font-weight: 500;
}
.codex-microbrain-alerts {
display: grid;
gap: 10px;
}
.codex-microbrain-alert {
padding: 14px 14px 13px;
border-radius: 14px;
background: #f8fbff;
border: 1px solid rgba(17,37,63,0.06);
}
.codex-microbrain-alert b {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 6px;
color: #152742;
font-size: 14px;
}
.codex-microbrain-alert p {
margin: 0;
color: #6d7d97;
font-size: 12px;
line-height: 1.6;
}
.codex-microbrain-level {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 4px 8px;
border-radius: 999px;
font-size: 11px;
font-weight: 600;
}
.codex-microbrain-level-正常 {
color: #067647;
background: rgba(6, 118, 71, 0.12);
}
.codex-microbrain-level-关注 {
color: #975a16;
background: rgba(255, 183, 77, 0.18);
}
.codex-microbrain-level-预警 {
color: #c92a2a;
background: rgba(255, 107, 107, 0.16);
}
@media (max-width: 1080px) {
.codex-microbrain-metrics {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.codex-microbrain-layout {
grid-template-columns: 1fr;
}
}
`;
doc.head.appendChild(style);
}
const containerId = "__codex_microbrain_dashboard__";
let container = doc.getElementById(containerId);
if (!container) {
container = doc.createElement("div");
container.id = containerId;
host.appendChild(container);
}
container.dataset.type = type;
const legend = preset.trendSeries
.map(
(item) => `
${item.label}
`
)
.join("");
const segments = preset.segments
.map(
(item) => `
${item.label}
${item.value}
`
)
.join("");
const metrics = preset.metrics
.map(
(item) => `
${item.label}
${item.value}
${item.delta}
`
)
.join("");
const rows = preset.rankingRows
.map(
(row, index) => `
| ${index + 1} |
${row[0]} |
${row[1]} |
${row[2]} |
`
)
.join("");
const alerts = preset.alerts
.map(
(item) => `
${item.title}
${item.level}
${item.detail}
`
)
.join("");
container.innerHTML = `
${preset.eyebrow}
${preset.headline}
${preset.summary}
镜像重建 · ${preset.headline} · 近 30 天静态样本
${metrics}
趋势概览
${legend}
${buildTrendSvg(preset.trendSeries, preset.trendLabels)}
${preset.alertsTitle}
${alerts}
`;
}
function ensureCloudReportStyle(doc) {
if (doc.getElementById("__codex_cloud_report_style__")) {
return;
}
const style = doc.createElement("style");
style.id = "__codex_cloud_report_style__";
style.textContent = `
.waitMain {
display: none !important;
}
.codex-cloud-report {
margin: 0 2% 18px;
padding: 18px 20px 20px;
border-radius: 18px;
background: linear-gradient(180deg, #ffffff 0%, #f7faff 100%);
border: 1px solid rgba(17, 37, 63, 0.06);
box-shadow: 0 18px 42px rgba(17, 37, 63, 0.08);
}
.codex-cloud-report-head {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 20px;
margin-bottom: 16px;
}
.codex-cloud-report-eyebrow {
display: inline-flex;
align-items: center;
padding: 4px 10px;
margin-bottom: 8px;
border-radius: 999px;
background: rgba(17,37,63,0.06);
color: #6d7d97;
font-size: 12px;
}
.codex-cloud-report-head h4 {
margin: 0 0 4px;
color: #152742;
font-size: 24px;
}
.codex-cloud-report-head p {
margin: 0;
color: #6d7d97;
font-size: 13px;
}
.codex-cloud-report-badge {
padding: 9px 12px;
border-radius: 14px;
color: #496385;
font-size: 12px;
background: rgba(255,255,255,0.9);
border: 1px solid rgba(17,37,63,0.08);
}
.codex-cloud-report-cards {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 12px;
margin-bottom: 16px;
}
.codex-cloud-report-card {
padding: 14px 16px;
border-radius: 16px;
background: rgba(255,255,255,0.92);
border: 1px solid rgba(17,37,63,0.05);
}
.codex-cloud-report-card span {
display: block;
color: #7d8ca5;
font-size: 12px;
}
.codex-cloud-report-card strong {
display: block;
margin: 8px 0 6px;
color: #152742;
font-size: 28px;
line-height: 1.05;
}
.codex-cloud-report-card small {
color: #4f6a94;
font-size: 12px;
}
.codex-cloud-report-table {
overflow: auto;
border-radius: 14px;
border: 1px solid rgba(17,37,63,0.06);
background: #fff;
}
.codex-cloud-report-table table {
width: 100%;
min-width: 1180px;
border-collapse: collapse;
}
.codex-cloud-report-table th,
.codex-cloud-report-table td {
padding: 12px 10px;
border-bottom: 1px solid rgba(17,37,63,0.06);
text-align: center;
color: #3f5477;
font-size: 13px;
white-space: nowrap;
}
.codex-cloud-report-table th {
position: sticky;
top: 0;
z-index: 1;
background: #f9fbff;
color: #7d8ca5;
font-size: 12px;
font-weight: 600;
}
.codex-cloud-report-table td:first-child,
.codex-cloud-report-table th:first-child {
position: sticky;
left: 0;
z-index: 1;
background: #fff;
}
.codex-cloud-report-table th:first-child {
background: #f9fbff;
}
.codex-cloud-report-table td.project {
text-align: left;
color: #152742;
font-weight: 600;
}
.codex-cloud-report-rate {
color: #067647;
font-weight: 600;
}
@media (max-width: 1080px) {
.codex-cloud-report-cards {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
`;
doc.head.appendChild(style);
}
function createCloudReportSection(doc, type) {
const preset = CLOUD_REPORT_PRESETS[type];
if (!preset) {
return null;
}
ensureCloudReportStyle(doc);
const section = doc.createElement("section");
section.className = "codex-cloud-report";
section.id = `__codex_cloud_report_${type}__`;
const cards = preset.cards
.map(
(item) => `
${item.label}
${item.value}
${item.detail}
`
)
.join("");
const headers = preset.headers.map((header) => `${header} | `).join("");
const rows = preset.rows
.map((row) => {
const cells = row
.map((value, index) => {
const className =
index === 0 ? "project" : /%$/.test(value) ? "codex-cloud-report-rate" : "";
return `${value} | `;
})
.join("");
return `${cells}
`;
})
.join("");
section.innerHTML = `
${preset.eyebrow}
${preset.title || (type === "propertyFeeReport" ? "物业费收缴明细表" : type === "parkingLotReport" ? "车场列表" : type === "planTaskReport" ? "计划工单执行总览" : "经营报表")}
基于镜像静态样本重建报表数据,用于替代原始页面中的空值或缺失列表。
镜像重建 · 静态样本数据
${cards}
`;
return section;
}
function renderCloudDataReport(doc, type) {
const preset = CLOUD_REPORT_PRESETS[type];
if (!preset) {
return;
}
const host = doc.querySelector(".contentStys") || doc.querySelector(".app-container") || doc.querySelector(".app-main");
if (!host) {
return;
}
host.querySelectorAll(".el-table, .el-pagination").forEach((node) => {
node.style.display = "none";
});
const planTitle = host.querySelector(".planLst");
if (planTitle) {
planTitle.style.marginBottom = "12px";
}
const existing = doc.getElementById(`__codex_cloud_report_${type}__`);
if (existing) {
existing.remove();
}
const section = createCloudReportSection(doc, type);
if (!section) {
return;
}
if (planTitle && planTitle.parentNode) {
planTitle.parentNode.insertBefore(section, planTitle.nextSibling);
return;
}
host.appendChild(section);
}
function ensureStaticPageStyle(doc) {
if (doc.getElementById("__codex_static_page_style__")) {
return;
}
const style = doc.createElement("style");
style.id = "__codex_static_page_style__";
style.textContent = `
.codex-static-page {
margin: 20px;
padding: 18px 20px 20px;
border-radius: 18px;
background: linear-gradient(180deg, #ffffff 0%, #f8fbff 100%);
border: 1px solid rgba(17,37,63,0.06);
box-shadow: 0 18px 42px rgba(17,37,63,0.08);
}
.codex-static-page-head {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 20px;
margin-bottom: 16px;
}
.codex-static-page-eyebrow {
display: inline-flex;
align-items: center;
padding: 4px 10px;
margin-bottom: 8px;
border-radius: 999px;
background: rgba(17,37,63,0.06);
color: #6d7d97;
font-size: 12px;
}
.codex-static-page-head h4 {
margin: 0 0 4px;
color: #152742;
font-size: 24px;
}
.codex-static-page-head p {
margin: 0;
color: #6d7d97;
font-size: 13px;
}
.codex-static-page-badge {
padding: 9px 12px;
border-radius: 14px;
color: #496385;
font-size: 12px;
background: rgba(255,255,255,0.9);
border: 1px solid rgba(17,37,63,0.08);
}
.codex-static-page-cards {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 12px;
margin-bottom: 16px;
}
.codex-static-page-card {
padding: 14px 16px;
border-radius: 16px;
background: rgba(255,255,255,0.92);
border: 1px solid rgba(17,37,63,0.05);
}
.codex-static-page-card span {
display: block;
color: #7d8ca5;
font-size: 12px;
}
.codex-static-page-card strong {
display: block;
margin: 8px 0 6px;
color: #152742;
font-size: 28px;
line-height: 1.05;
}
.codex-static-page-card small {
color: #4f6a94;
font-size: 12px;
}
.codex-static-page-table {
overflow: auto;
border-radius: 14px;
border: 1px solid rgba(17,37,63,0.06);
background: #fff;
}
.codex-static-page-table table {
width: 100%;
min-width: 920px;
border-collapse: collapse;
}
.codex-static-page-table th,
.codex-static-page-table td {
padding: 12px 10px;
border-bottom: 1px solid rgba(17,37,63,0.06);
text-align: center;
color: #3f5477;
font-size: 13px;
white-space: nowrap;
}
.codex-static-page-table th {
background: #f9fbff;
color: #7d8ca5;
font-size: 12px;
font-weight: 600;
}
.codex-static-page-table td:first-child,
.codex-static-page-table th:first-child {
text-align: left;
}
@media (max-width: 1080px) {
.codex-static-page-cards {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
`;
doc.head.appendChild(style);
}
function renderStaticManagementPage(doc, type) {
const preset = STATIC_PAGE_PRESETS[type];
if (!preset) {
return;
}
ensureStaticPageStyle(doc);
doc.querySelectorAll(".waitMain").forEach((node) => {
node.style.display = "none";
});
const host =
doc.querySelector(".app-main > div") ||
doc.querySelector(".app-main > section") ||
doc.querySelector(".app-main") ||
doc.body;
if (!host) {
return;
}
const existing = doc.getElementById(`__codex_static_page_${type}__`);
if (existing) {
existing.remove();
}
const section = doc.createElement("section");
section.id = `__codex_static_page_${type}__`;
section.className = "codex-static-page";
const cards = preset.cards
.map(
(item) => `
${item.label}
${item.value}
${item.detail}
`
)
.join("");
const headers = preset.headers.map((header) => `${header} | `).join("");
const rows = preset.rows
.map((row) => `${row.map((value) => `| ${value} | `).join("")}
`)
.join("");
section.innerHTML = `
${preset.eyebrow}
${preset.title}
${preset.summary}
镜像重建 · 静态样本数据
${cards}
`;
host.appendChild(section);
}
function ensureEtmsEditableStyle(doc) {
if (doc.getElementById("__codex_etms_editable_style__")) {
return;
}
const style = doc.createElement("style");
style.id = "__codex_etms_editable_style__";
style.textContent = `
.codex-editable-shell {
position: relative;
}
.codex-editable-toolbar {
position: sticky;
top: 12px;
z-index: 20;
display: flex;
justify-content: flex-end;
gap: 8px;
margin: 0 0 12px;
}
.codex-editable-toolbar button {
border: 1px solid rgba(17,37,63,0.08);
border-radius: 999px;
padding: 6px 12px;
background: rgba(255,255,255,0.92);
color: #35507a;
font-size: 12px;
cursor: pointer;
}
.codex-editable-toolbar button.codex-primary {
background: #2d76ff;
border-color: transparent;
color: #fff;
}
.codex-editable-toolbar button.codex-danger {
color: #d14343;
}
.codex-editable-toolbar button:disabled {
opacity: 0.48;
cursor: not-allowed;
}
.codex-editable-body[contenteditable="true"] {
outline: 2px dashed rgba(45,118,255,0.35);
outline-offset: 8px;
}
.codex-editable-body[contenteditable="true"] a,
.codex-editable-body[contenteditable="true"] button {
pointer-events: none;
}
.codex-editable-hint {
margin-right: auto;
align-self: center;
color: #6d7d97;
font-size: 12px;
}
`;
doc.head.appendChild(style);
}
function createEtmsEditableKey(doc, section, index) {
const pathname = doc.defaultView?.location?.pathname || "unknown";
const sectionId = section.id || section.dataset.type || section.className || `section-${index}`;
return `__codex_etms_edit__${pathname}::${sectionId}`;
}
function wrapEtmsEditableBody(section) {
let body = section.querySelector(":scope > .codex-editable-body");
if (body) {
return body;
}
body = section.ownerDocument.createElement("div");
body.className = "codex-editable-body";
[...section.childNodes].forEach((node) => {
body.appendChild(node);
});
section.appendChild(body);
return body;
}
function setEtmsEditableState(doc, section, editing) {
const body = section.querySelector(":scope > .codex-editable-body");
const toolbar = section.querySelector(":scope > .codex-editable-toolbar");
if (!body || !toolbar) {
return;
}
body.contentEditable = editing ? "true" : "false";
body.spellcheck = false;
section.dataset.codexEditing = editing ? "1" : "0";
doc.body.dataset.codexMirrorEditing = editing ? "1" : "0";
toolbar.querySelector("[data-action='edit']").disabled = editing;
toolbar.querySelector("[data-action='save']").disabled = !editing;
}
function bindEtmsEditableSection(doc, section, index) {
ensureEtmsEditableStyle(doc);
section.classList.add("codex-editable-shell");
const body = wrapEtmsEditableBody(section);
const storageKey = createEtmsEditableKey(doc, section, index);
const win = doc.defaultView;
const saved = win?.localStorage.getItem(storageKey);
if (!section.dataset.codexDefaultHtml) {
section.dataset.codexDefaultHtml = body.innerHTML;
}
if (saved && body.innerHTML !== saved && section.dataset.codexEditing !== "1") {
body.innerHTML = saved;
}
let toolbar = section.querySelector(":scope > .codex-editable-toolbar");
if (!toolbar) {
toolbar = doc.createElement("div");
toolbar.className = "codex-editable-toolbar";
toolbar.innerHTML = `
本地编辑
`;
section.insertBefore(toolbar, body);
toolbar.addEventListener("click", (event) => {
const button = event.target.closest("button[data-action]");
if (!button) {
return;
}
const action = button.dataset.action;
if (action === "edit") {
setEtmsEditableState(doc, section, true);
body.focus();
return;
}
if (action === "save") {
win?.localStorage.setItem(storageKey, body.innerHTML);
setEtmsEditableState(doc, section, false);
return;
}
if (action === "reset") {
win?.localStorage.removeItem(storageKey);
body.innerHTML = section.dataset.codexDefaultHtml || body.innerHTML;
setEtmsEditableState(doc, section, false);
}
});
}
setEtmsEditableState(doc, section, false);
}
function installEtmsEditableSections(doc) {
const sections = [
...doc.querySelectorAll("#__codex_microbrain_dashboard__, [id^='__codex_cloud_report_'], [id^='__codex_static_page_'], #__codex_finance_summary__")
];
const seen = new Set();
sections.forEach((section, index) => {
if (!section || seen.has(section)) {
return;
}
seen.add(section);
bindEtmsEditableSection(doc, section, index);
});
}
function ensureEtmsListEditStyle(doc) {
if (doc.getElementById("__codex_etms_list_edit_style__")) {
return;
}
const style = doc.createElement("style");
style.id = "__codex_etms_list_edit_style__";
style.textContent = `
.codex-listedit-mask {
position: fixed;
inset: 0;
z-index: 99999;
background: rgba(8, 15, 28, 0.42);
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
}
.codex-listedit-modal {
width: min(760px, 100%);
max-height: min(760px, calc(100vh - 48px));
overflow: auto;
border-radius: 18px;
background: #fff;
box-shadow: 0 24px 54px rgba(17, 37, 63, 0.18);
padding: 20px 22px;
}
.codex-listedit-modal h4 {
margin: 0 0 16px;
color: #152742;
font-size: 20px;
}
.codex-listedit-summary {
margin: 0 0 16px;
color: #6d7d97;
font-size: 12px;
line-height: 1.7;
}
.codex-listedit-form {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}
.codex-listedit-form label {
display: flex;
flex-direction: column;
gap: 6px;
color: #6d7d97;
font-size: 12px;
}
.codex-listedit-form label.full {
grid-column: 1 / -1;
}
.codex-listedit-form input,
.codex-listedit-form textarea {
border: 1px solid rgba(17, 37, 63, 0.12);
border-radius: 10px;
padding: 10px 12px;
color: #152742;
font-size: 13px;
background: #fff;
}
.codex-listedit-form textarea {
min-height: 96px;
resize: vertical;
}
.codex-listedit-actions {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 18px;
}
.codex-listedit-actions button {
border: 1px solid rgba(17, 37, 63, 0.08);
border-radius: 999px;
padding: 6px 12px;
background: #fff;
color: #35507a;
font-size: 12px;
cursor: pointer;
}
.codex-listedit-actions button.codex-primary {
background: #2d76ff;
border-color: transparent;
color: #fff;
}
.codex-listedit-actions button.codex-danger {
color: #d14343;
}
.codex-listedit-fallback-panel {
margin: 16px 0;
padding: 14px 16px;
border-radius: 14px;
border: 1px solid rgba(17, 37, 63, 0.06);
background: linear-gradient(180deg, #ffffff 0%, #f8fbff 100%);
box-shadow: 0 12px 28px rgba(17, 37, 63, 0.08);
}
.codex-listedit-fallback-panel h5 {
margin: 0 0 10px;
color: #152742;
font-size: 15px;
}
.codex-listedit-fallback-panel p {
margin: 0 0 12px;
color: #6d7d97;
font-size: 12px;
line-height: 1.7;
}
.codex-listedit-fallback-list {
display: grid;
gap: 8px;
}
.codex-listedit-fallback-item {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 10px 12px;
border-radius: 10px;
background: rgba(247, 250, 255, 0.92);
border: 1px solid rgba(17, 37, 63, 0.06);
}
.codex-listedit-fallback-item span {
flex: 1;
color: #35507a;
font-size: 12px;
line-height: 1.6;
}
`;
doc.head.appendChild(style);
}
function createEtmsListEditStorageKey(doc) {
const pathname = doc.defaultView?.location?.pathname || "unknown";
return `__codex_etms_list_edit__${pathname}`;
}
function readEtmsListEditState(doc) {
try {
return JSON.parse(doc.defaultView?.localStorage.getItem(createEtmsListEditStorageKey(doc)) || "{}");
} catch (_error) {
return {};
}
}
function writeEtmsListEditState(doc, state) {
try {
doc.defaultView?.localStorage.setItem(createEtmsListEditStorageKey(doc), JSON.stringify(state));
} catch (_error) {
// ignore
}
}
function getEtmsVisibleText(node) {
return (node?.textContent || "").replace(/\s+/g, " ").trim();
}
function isEtmsElementVisible(node) {
if (!node) {
return false;
}
const style = node.ownerDocument?.defaultView?.getComputedStyle(node);
const rect = node.getBoundingClientRect?.();
if (!style || !rect) {
return false;
}
return style.display !== "none" && style.visibility !== "hidden" && rect.width > 0 && rect.height > 0;
}
function getEtmsListEditTableKey(doc, table) {
const tableRoot = table.closest(".el-table");
if (tableRoot) {
const roots = [...doc.querySelectorAll(".el-table")];
return `table-root-${roots.indexOf(tableRoot)}`;
}
const tables = [...doc.querySelectorAll("table")];
return `table-${tables.indexOf(table)}`;
}
function isEtmsActionOnlyText(text) {
return /^(编辑|删除|查看|复制角色|复制|下载|导出|导入|开具发票|手动开收据|下载收据|生成票据|催费|拆分|禁用|启用)(\s+(编辑|删除|查看|复制角色|复制|下载|导出|导入|开具发票|手动开收据|下载收据|生成票据|催费|拆分|禁用|启用))*$/.test(text);
}
function countEtmsVisibleCells(row) {
return [...row.querySelectorAll(":scope > td")].filter((cell) => isEtmsElementVisible(cell)).length;
}
function resolveEtmsPrimaryRow(row) {
const tableRoot = row?.closest(".el-table");
const rowIndex = [...(row?.parentElement?.children || [])].indexOf(row);
if (!tableRoot || rowIndex < 0) {
return row;
}
const candidates = [];
[...tableRoot.querySelectorAll("tbody")].forEach((tbody) => {
const candidate = tbody.children[rowIndex];
if (candidate && !candidates.includes(candidate)) {
candidates.push(candidate);
}
});
candidates.sort((left, right) => countEtmsVisibleCells(right) - countEtmsVisibleCells(left));
return candidates[0] || row;
}
function extractEtmsListEditHeaders(table, cellCount) {
const headers = [...table.querySelectorAll("thead th")]
.map((cell) => getEtmsVisibleText(cell))
.filter(Boolean);
if (!headers.length) {
return Array.from({ length: cellCount }, (_value, index) => `字段${index + 1}`);
}
return headers;
}
function extractEtmsListEditContext(doc, row) {
const table = row?.closest("table");
if (!table) {
return null;
}
const rows = [...(row.parentElement?.children || [])];
const rowIndex = rows.indexOf(row);
const cells = [...row.querySelectorAll(":scope > td")];
const headers = extractEtmsListEditHeaders(table, cells.length);
const fields = [];
cells.forEach((cell, index) => {
const header = headers[index] || `字段${index + 1}`;
const value = getEtmsVisibleText(cell);
if (!value || /操作/.test(header) || isEtmsActionOnlyText(value)) {
return;
}
fields.push({ header, value });
});
if (!fields.length) {
return null;
}
return {
tableKey: getEtmsListEditTableKey(doc, table),
rowKey: `row-${rowIndex}`,
fields
};
}
function resolveEtmsListEditContext(doc, trigger) {
const sourceRow = trigger?.closest("tr");
if (!sourceRow) {
return null;
}
const direct = extractEtmsListEditContext(doc, sourceRow);
if (direct) {
return {
row: sourceRow,
context: direct
};
}
const rowIndex = [...(sourceRow.parentElement?.children || [])].indexOf(sourceRow);
const tableRoot = sourceRow.closest(".el-table");
if (!tableRoot || rowIndex < 0) {
return null;
}
const candidateSelectors = [
".el-table__body-wrapper tbody tr",
".el-table__fixed-body-wrapper tbody tr",
".el-table__fixed-right .el-table__fixed-body-wrapper tbody tr"
];
for (const selector of candidateSelectors) {
const rows = [...tableRoot.querySelectorAll(selector)];
const row = rows[rowIndex];
if (!row || row === sourceRow) {
continue;
}
const context = extractEtmsListEditContext(doc, row);
if (context) {
return {
row,
context
};
}
}
return null;
}
function setEtmsListEditCellValue(cell, value) {
const target =
cell.querySelector(":scope > .cell") ||
(cell.children.length === 1 ? cell.children[0] : cell);
if (!target) {
return;
}
target.textContent = value;
}
function applyEtmsListEditValues(row, fields) {
const table = row?.closest("table");
if (!table) {
return;
}
const cells = [...row.querySelectorAll(":scope > td")];
const headers = extractEtmsListEditHeaders(table, cells.length);
let fieldIndex = 0;
cells.forEach((cell, index) => {
const header = headers[index] || `字段${index + 1}`;
const value = getEtmsVisibleText(cell);
if (!value || /操作/.test(header) || isEtmsActionOnlyText(value)) {
return;
}
const nextField = fields[fieldIndex];
if (!nextField) {
return;
}
setEtmsListEditCellValue(cell, nextField.value);
fieldIndex += 1;
});
}
function applyEtmsListEditStateToTable(doc, tableKey, rowKey, fields) {
const rowIndex = Number(String(rowKey || "").replace("row-", ""));
if (Number.isNaN(rowIndex)) {
return;
}
if (String(tableKey).startsWith("table-root-")) {
const rootIndex = Number(String(tableKey).replace("table-root-", ""));
const tableRoot = [...doc.querySelectorAll(".el-table")][rootIndex];
if (!tableRoot) {
return;
}
const seen = new Set();
[
".el-table__body-wrapper tbody tr",
".el-table__fixed-body-wrapper tbody tr",
".el-table__fixed-right .el-table__fixed-body-wrapper tbody tr"
].forEach((selector) => {
const row = [...tableRoot.querySelectorAll(selector)][rowIndex];
if (!row || seen.has(row)) {
return;
}
seen.add(row);
applyEtmsListEditValues(row, fields);
});
return;
}
const tableIndex = Number(String(tableKey || "").replace("table-", ""));
const table = [...doc.querySelectorAll("table")][tableIndex];
const row = table ? [...table.querySelectorAll("tbody tr")][rowIndex] : null;
if (row) {
applyEtmsListEditValues(row, fields);
}
}
function hydrateEtmsListEditRows(doc) {
const state = readEtmsListEditState(doc);
Object.entries(state).forEach(([tableKey, tableState]) => {
Object.entries(tableState || {}).forEach(([rowKey, rowState]) => {
if (rowState?.fields) {
applyEtmsListEditStateToTable(doc, tableKey, rowKey, rowState.fields);
}
});
});
}
function normalizeEtmsListEditTriggers(doc) {
[...doc.querySelectorAll("button.el-button, .textBtn, a, .el-button, .el-dropdown-menu__item")].forEach((node) => {
const text = getEtmsVisibleText(node);
if (!/编辑/.test(text) || !node.closest("tr")) {
return;
}
if ("disabled" in node) {
node.disabled = false;
}
node.removeAttribute?.("disabled");
node.classList?.remove("is-disabled");
node.closest(".is-disabled")?.classList.remove("is-disabled");
node.style.cursor = "pointer";
node.style.opacity = "1";
});
}
function injectEtmsInlineEditButtons(doc) {
[...doc.querySelectorAll("tbody tr")].forEach((row) => {
if (row.closest("[id^='__codex_'], .codex-budget-panel, .codex-editable-shell")) {
return;
}
const actionNodes = [...row.querySelectorAll("button, .textBtn, a, .el-button, .el-dropdown-menu__item")];
const hasVisibleEdit = actionNodes.some((node) => /编辑/.test(getEtmsVisibleText(node)) && isEtmsElementVisible(node));
if (hasVisibleEdit) {
return;
}
const hasHiddenEdit = actionNodes.some((node) => /编辑/.test(getEtmsVisibleText(node)));
if (!hasHiddenEdit) {
return;
}
const hostRow = resolveEtmsPrimaryRow(row);
const cells = [...hostRow.querySelectorAll(":scope > td")];
const hostCell =
cells.find((cell) => {
const text = getEtmsVisibleText(cell);
return isEtmsElementVisible(cell) && text && !isEtmsActionOnlyText(text) && text !== "#";
}) || cells[0];
if (!hostCell) {
return;
}
const host = hostCell.querySelector(":scope > .cell") || hostCell;
if (host.querySelector(":scope > .codex-inline-edit-trigger")) {
return;
}
const button = doc.createElement("button");
button.type = "button";
button.className = "el-button el-button--text el-button--mini codex-inline-edit-trigger";
button.textContent = "编辑";
button.style.marginLeft = "8px";
host.appendChild(button);
});
}
function collectEtmsHiddenEditEntries(doc) {
const entries = [];
const seen = new Set();
const hasVisibleEdit = [...doc.querySelectorAll("button, .textBtn, a, .el-button, .el-dropdown-menu__item")].some(
(node) => /编辑/.test(getEtmsVisibleText(node)) && isEtmsElementVisible(node)
);
if (hasVisibleEdit) {
return entries;
}
[...doc.querySelectorAll("tbody tr")].forEach((row) => {
if (row.closest("[id^='__codex_'], .codex-budget-panel, .codex-editable-shell")) {
return;
}
const actionNodes = [...row.querySelectorAll("button, .textBtn, a, .el-button, .el-dropdown-menu__item")];
const hasHiddenEdit = actionNodes.some((node) => /编辑/.test(getEtmsVisibleText(node)));
if (!hasHiddenEdit) {
return;
}
const primaryRow = resolveEtmsPrimaryRow(row);
const context = extractEtmsListEditContext(doc, primaryRow);
if (!context) {
return;
}
const key = `${context.tableKey}::${context.rowKey}`;
if (seen.has(key)) {
return;
}
seen.add(key);
entries.push({
row: primaryRow,
context,
summary: context.fields
.slice(0, 3)
.map((field) => `${field.header}:${field.value}`)
.join(" / ")
});
});
return entries;
}
function renderEtmsHiddenEditPanel(doc) {
const entries = collectEtmsHiddenEditEntries(doc);
const existing = doc.getElementById("__codex_etms_hidden_edit_panel__");
if (!entries.length) {
existing?.remove();
return;
}
const panel = existing || doc.createElement("section");
panel.id = "__codex_etms_hidden_edit_panel__";
panel.className = "codex-listedit-fallback-panel";
panel.innerHTML = `
本地编辑入口
当前页面默认视图没有直接露出原生“编辑”按钮,以下入口由镜像补出,点击后会打开本地列表编辑弹窗。
${entries
.slice(0, 12)
.map(
(entry, index) => `
${entry.summary}
`
)
.join("")}
`;
if (!existing) {
const host = doc.querySelector(".app-main > div") || doc.querySelector(".app-main") || doc.body;
host.insertBefore(panel, host.firstChild);
}
panel.querySelectorAll("[data-hidden-edit-index]").forEach((button) => {
button.addEventListener("click", () => {
const entry = entries[Number(button.getAttribute("data-hidden-edit-index"))];
if (!entry) {
return;
}
openEtmsListEditModal(doc, resolveEtmsPrimaryRow(entry.row), entry.context);
});
});
}
function closeEtmsListEditModal(doc) {
doc.getElementById("__codex_etms_list_edit_mask__")?.remove();
}
function openEtmsListEditModal(doc, row, context) {
ensureEtmsListEditStyle(doc);
closeEtmsListEditModal(doc);
const mask = doc.createElement("div");
mask.id = "__codex_etms_list_edit_mask__";
mask.className = "codex-listedit-mask";
const fieldsHtml = context.fields
.map(
(field, index) => `
`
)
.join("");
mask.innerHTML = `
本地编辑列表行
当前编辑的是镜像中的列表行内容。保存后会写入浏览器本地存储,并在当前页面刷新后继续生效。
${fieldsHtml}
`;
mask.addEventListener("click", (event) => {
if (event.target === mask) {
closeEtmsListEditModal(doc);
}
});
doc.body.appendChild(mask);
mask.querySelector("[data-action='close']")?.addEventListener("click", () => closeEtmsListEditModal(doc));
mask.querySelector("[data-action='save']")?.addEventListener("click", () => {
const nextFields = context.fields.map((field, index) => ({
header: field.header,
value: mask.querySelector(`[data-field-index='${index}']`)?.value.trim() || ""
}));
const state = readEtmsListEditState(doc);
state[context.tableKey] = state[context.tableKey] || {};
state[context.tableKey][context.rowKey] = { fields: nextFields };
writeEtmsListEditState(doc, state);
applyEtmsListEditStateToTable(doc, context.tableKey, context.rowKey, nextFields);
closeEtmsListEditModal(doc);
});
}
function installEtmsGenericListEditors(doc) {
ensureEtmsListEditStyle(doc);
hydrateEtmsListEditRows(doc);
normalizeEtmsListEditTriggers(doc);
injectEtmsInlineEditButtons(doc);
renderEtmsHiddenEditPanel(doc);
if (doc.body.dataset.codexListEditorsInstalled === "1") {
return;
}
doc.addEventListener(
"click",
(event) => {
const target = event.target.closest("button, .textBtn, a, .el-button");
if (!target) {
return;
}
if (target.closest("[id^='__codex_'], .codex-budget-panel, .codex-editable-toolbar")) {
return;
}
const label = getEtmsVisibleText(target);
if (!/编辑/.test(label)) {
return;
}
const resolved = resolveEtmsListEditContext(doc, target);
if (!resolved) {
return;
}
event.preventDefault();
event.stopPropagation();
openEtmsListEditModal(doc, resolved.row, resolved.context);
},
true
);
doc.body.dataset.codexListEditorsInstalled = "1";
}
function applyGlobalFrameSkin(iframe) {
try {
const doc = iframe && iframe.contentDocument;
if (!doc || !doc.head) {
return;
}
if (!doc.getElementById("__codex_runtime_frame_skin__")) {
const style = doc.createElement("style");
style.id = "__codex_runtime_frame_skin__";
style.textContent = `
.sidebar-container,
.fixed-header,
.tags-view-container,
.layout-tags-view-container,
.navbar,
.app-breadcrumb,
.el-breadcrumb,
.breadcrumb-container,
.tabList,
.right-menu,
.currentProject,
.AiBox,
.feedback-dialog,
.feedback-btn,
.hamburger-container,
.right-menu-item .international,
.right-menu-item .avatar-container {
display: none !important;
}
.main-container,
.main-container.hasTagsView,
.app-main,
.app-main > section,
.main-container .app-main {
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
}
.el-scrollbar__wrap,
.scrollbar-wrapper {
margin-right: 0 !important;
margin-bottom: 0 !important;
}
body,
html {
background: #f5f7fa !important;
overflow: auto !important;
}
.app-main > section,
.app-main > .app-container,
.app-main .app-container,
.main-container .app-main > section {
padding-top: 0 !important;
}
.el-table__empty-block,
.el-table__empty-text {
display: none !important;
}
`;
doc.head.appendChild(style);
}
const tables = [...doc.querySelectorAll("table")];
const hasDataTable = tables.some((table) => table.querySelectorAll("tbody tr").length > 0);
if (hasDataTable) {
tables.forEach((table) => {
const wrapper = table.closest(".el-table");
const rows = table.querySelectorAll("tbody tr").length;
if (rows > 0) {
if (wrapper) {
wrapper.style.setProperty("display", "block", "important");
}
return;
}
if (wrapper) {
wrapper.style.display = "none";
}
});
}
const src = iframe.getAttribute("src") || "";
const editingActive = doc.body?.dataset.codexMirrorEditing === "1";
if (!editingActive) {
if (src.includes("/companyMetadata/companyInfo/")) {
hydrateCompanyInfoFrame(doc);
}
if (src.includes("/companyMetadata/institution/")) {
if (!doc.getElementById("__codex_institution_expand__")) {
const style = doc.createElement("style");
style.id = "__codex_institution_expand__";
style.textContent = `
tr.el-table__row--level-1,
tr.el-table__row--level-2,
tr.el-table__row--level-3 {
display: table-row !important;
}
`;
doc.head.appendChild(style);
}
doc.querySelectorAll("tr.el-table__row--level-1, tr.el-table__row--level-2, tr.el-table__row--level-3").forEach((tr) => {
tr.style.setProperty("display", "table-row", "important");
});
}
if (src.includes("/companyMetadata/financeData/")) {
if (!doc.getElementById("__codex_finance_summary__")) {
const summary = doc.createElement("div");
summary.id = "__codex_finance_summary__";
summary.innerHTML = `
主营业务收入
¥205,600.00
营业利润
¥49,900.00
净利润
¥40,200.00
`;
const style = doc.createElement("style");
style.id = "__codex_finance_summary_style__";
style.textContent = `
#__codex_finance_summary__ {
display: grid;
grid-template-columns: repeat(3, minmax(180px, 1fr));
gap: 16px;
margin: 0 0 18px;
}
.codex-finance-summary-card {
padding: 18px 20px;
border-radius: 16px;
background: linear-gradient(135deg, #f8fbff, #eef5ff);
border: 1px solid rgba(45, 118, 255, 0.08);
box-shadow: 0 10px 24px rgba(31, 55, 88, 0.06);
}
.codex-finance-summary-card .label {
display: block;
margin-bottom: 8px;
color: #6b7a90;
font-size: 13px;
}
.codex-finance-summary-card strong {
color: #1f2d3d;
font-size: 24px;
font-weight: 700;
}
`;
doc.head.appendChild(style);
const host = doc.querySelector(".app-main > section") || doc.querySelector(".main-container .app-main") || doc.body;
host.insertBefore(summary, host.firstChild);
}
const visibleTables = [...doc.querySelectorAll("table")].filter((table) => {
const wrapper = table.closest(".el-table") || table;
return getComputedStyle(wrapper).display !== "none";
});
const valueTable = visibleTables.find((table) => table.querySelectorAll("tbody tr").length >= 3 && /¥0\.00/.test(table.innerText));
if (valueTable) {
const matrix = [
["¥128,000.00", "¥136,500.00", "¥142,300.00", "¥155,800.00", "¥163,200.00", "¥171,900.00", "¥176,500.00", "¥181,200.00", "¥188,300.00", "¥192,400.00", "¥198,800.00", "¥205,600.00"],
["¥28,600.00", "¥31,200.00", "¥33,900.00", "¥37,500.00", "¥39,200.00", "¥41,100.00", "¥42,300.00", "¥43,900.00", "¥45,500.00", "¥46,800.00", "¥48,200.00", "¥49,900.00"],
["¥21,800.00", "¥24,100.00", "¥26,300.00", "¥29,000.00", "¥30,600.00", "¥31,900.00", "¥33,100.00", "¥34,500.00", "¥35,800.00", "¥37,000.00", "¥38,600.00", "¥40,200.00"]
];
const rows = [...valueTable.querySelectorAll("tbody tr")].slice(0, 3);
rows.forEach((tr, rowIdx) => {
const cells = [...tr.querySelectorAll("td")];
matrix[rowIdx].forEach((value, valueIdx) => {
const cell = cells[valueIdx + 1];
const valueNode = cell && (cell.querySelector(".cell div") || cell.querySelector(".cell") || cell);
if (valueNode) {
valueNode.textContent = value;
}
});
});
}
}
if (src.includes("/r2cockpit/microbrain/finance/")) {
renderMicrobrainDashboard(doc, "finance");
}
if (src.includes("/r2cockpit/microbrain/equipment/")) {
renderMicrobrainDashboard(doc, "equipment");
}
if (src.includes("/r2cockpit/microbrain/parkingLot/")) {
renderMicrobrainDashboard(doc, "parkingLot");
}
if (src.includes("/supplierManage/supplierMicrobrain/")) {
renderMicrobrainDashboard(doc, "supplierMicrobrain");
}
if (src.includes("/r2cockpit/cloudData/propertyFeeReport/")) {
renderCloudDataReport(doc, "propertyFeeReport");
}
if (src.includes("/r2cockpit/cloudData/parkingLotReport/")) {
renderCloudDataReport(doc, "parkingLotReport");
}
if (src.includes("/r2cockpit/cloudData/planTaskReport/")) {
renderCloudDataReport(doc, "planTaskReport");
}
if (src.includes("/r2cockpit/cloudData/workOrderReport/")) {
renderCloudDataReport(doc, "workOrderReport");
}
if (src.includes("/r2cockpit/cloudData/dataReport/")) {
renderCloudDataReport(doc, "dataReport");
}
if (src.includes("/r2cockpit/cloudData/consumeReport/")) {
renderCloudDataReport(doc, "consumeReport");
}
if (src.includes("/r2cockpit/cloudData/jobGridReport/")) {
renderCloudDataReport(doc, "jobGridReport");
}
if (src.includes("/r2cockpit/cloudData/contractPlanReport/")) {
renderCloudDataReport(doc, "contractPlanReport");
}
if (src.includes("/r2cockpit/cloudData/contractGuaranteeReport/")) {
renderCloudDataReport(doc, "contractGuaranteeReport");
}
if (src.includes("/r2cockpit/cloudData/detailedContractGuaranteeReport/")) {
renderCloudDataReport(doc, "detailedContractGuaranteeReport");
}
if (src.includes("/r2cockpit/cloudData/officialAccount/")) {
renderCloudDataReport(doc, "officialAccount");
}
if (src.includes("/r2cockpit/cloudData/collectionTracking/")) {
renderCloudDataReport(doc, "collectionTracking");
}
if (src.includes("/r2cockpit/cloudData/collectionRate/")) {
renderCloudDataReport(doc, "collectionRate");
}
if (src.includes("/r2cockpit/cloudData/visitWorkReport/")) {
renderCloudDataReport(doc, "visitWorkReport");
}
if (src.includes("/personnelMerits/qualification/")) {
renderStaticManagementPage(doc, "qualification");
}
if (src.includes("/personnelMerits/employeeQuitReport/")) {
renderStaticManagementPage(doc, "employeeQuitReport");
}
if (src.includes("/systemManage/operationLog/")) {
renderStaticManagementPage(doc, "operationLog");
}
if (src.includes("/satisfaction/questionBank/")) {
renderStaticManagementPage(doc, "questionBank");
}
if (src.includes("/satisfaction/report/")) {
renderStaticManagementPage(doc, "report");
}
if (src.includes("/satisfaction/tracking/")) {
renderStaticManagementPage(doc, "tracking");
}
if (src.includes("/personnelMerits/assessment/")) {
renderStaticManagementPage(doc, "assessment");
}
}
installEtmsGenericListEditors(doc);
installEtmsEditableSections(doc);
const bodyHeight = doc.body ? doc.body.scrollHeight : 0;
const htmlHeight = doc.documentElement ? doc.documentElement.scrollHeight : 0;
const height = Math.max(bodyHeight, htmlHeight, window.innerHeight - 108, 720);
iframe.style.setProperty("height", `${height}px`, "important");
} catch (_error) {
// ignore
}
}
function installFrameSkinObserver() {
setInterval(() => {
document.querySelectorAll("iframe").forEach((iframe) => applyGlobalFrameSkin(iframe));
}, 800);
}
function appendStyles() {
STYLE_HREFS.forEach((href) => {
const finalHref = VERSION ? `${href}${href.includes("?") ? "&" : "?"}v=${VERSION}` : href;
if (document.querySelector(`link[href="${finalHref}"]`)) {
return;
}
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = finalHref;
document.head.appendChild(link);
});
}
function injectOuterRuntimeSkin() {
if (document.getElementById("__codex_runtime_outer_skin__")) {
return;
}
const style = document.createElement("style");
style.id = "__codex_runtime_outer_skin__";
style.textContent = `
.AiBox,
.feedback-dialog,
.feedback-btn,
.v-modal {
display: none !important;
}
.app-main,
.app-main > section,
.main-container,
.main-container.hasTagsView {
background: #f3f6fb !important;
}
.fixed-header {
position: sticky !important;
top: 0;
z-index: 10;
box-shadow: 0 4px 18px rgba(17, 37, 63, 0.06);
}
.navbar {
height: 60px !important;
padding: 0 16px !important;
background: rgba(255,255,255,0.94) !important;
backdrop-filter: blur(8px);
}
.breadcrumb-container {
font-size: 13px !important;
}
.right-menu {
gap: 10px;
}
.right-menu .el-select,
.right-menu .currentProject {
max-width: 320px;
}
.tags-view-container {
min-height: 38px !important;
padding: 6px 12px !important;
background: rgba(255,255,255,0.92) !important;
border-bottom: 1px solid rgba(17,37,63,0.06) !important;
}
.tags-view-wrapper .el-scrollbar__view {
display: flex;
align-items: center;
gap: 8px;
}
.tags-view-item {
display: inline-flex !important;
align-items: center;
gap: 6px;
height: 28px;
margin: 0 !important;
padding: 0 12px;
border-radius: 4px 4px 0 0;
border: 1px solid rgba(17, 37, 63, 0.12);
background: #fff;
color: #66758f;
font-size: 13px;
line-height: 28px;
white-space: nowrap;
cursor: default;
}
.tags-view-item.active {
border-color: rgba(45, 118, 255, 0.18);
background: #3a7be0;
color: #fff;
}
.tags-view-item.codex-synthetic-tag {
text-decoration: none;
cursor: pointer;
}
.tags-view-item .el-icon-close {
display: inline-flex !important;
align-items: center;
justify-content: center;
font-size: 12px;
opacity: 0.72;
}
.tags-view-item:first-child .el-icon-close {
display: none !important;
}
.codex-runtime-frame-host {
padding: 14px 16px 20px;
background: #f3f6fb;
}
.codex-runtime-frame {
display: block;
width: 100%;
min-height: 720px;
border: 0;
border-radius: 18px;
background: #fff;
box-shadow: 0 14px 40px rgba(17, 37, 63, 0.08);
}
.codex-runtime-summary {
display: grid;
grid-template-columns: repeat(3, minmax(180px, 1fr));
gap: 14px;
margin: 0 0 14px;
}
.codex-runtime-summary-card {
padding: 16px 18px;
border-radius: 16px;
background: linear-gradient(135deg, #f8fbff, #eef5ff);
border: 1px solid rgba(45, 118, 255, 0.08);
box-shadow: 0 10px 24px rgba(31, 55, 88, 0.06);
}
.codex-runtime-summary-card .label {
display: block;
margin-bottom: 8px;
color: #6b7a90;
font-size: 13px;
}
.codex-runtime-summary-card strong {
color: #1f2d3d;
font-size: 24px;
font-weight: 700;
}
`;
document.head.appendChild(style);
}
function appendScript(src) {
return new Promise((resolve, reject) => {
const script = document.createElement("script");
script.src = VERSION ? `${src}${src.includes("?") ? "&" : "?"}v=${VERSION}` : src;
script.onload = resolve;
script.onerror = reject;
document.body.appendChild(script);
});
}
async function loadJson(url) {
const finalUrl = VERSION ? `${url}${url.includes("?") ? "&" : "?"}v=${VERSION}` : url;
const response = await fetch(finalUrl, { cache: "no-store" });
if (!response.ok) {
throw new Error(`加载失败: ${url}`);
}
return response.json();
}
async function loadRouteMap() {
routeMap = await loadJson("./route-map.json");
}
async function seedStorage() {
storageSeed = await loadJson("./storage-seed.json");
Object.entries(storageSeed).forEach(([key, value]) => {
localStorage.setItem(key, value);
});
if (!localStorage.getItem("userInfo") && storageSeed.userInfo) {
localStorage.setItem("userInfo", storageSeed.userInfo);
}
if (!localStorage.getItem("companyInfo") && storageSeed.companyInfo) {
localStorage.setItem("companyInfo", storageSeed.companyInfo);
}
}
async function seedSession() {
const payload = await loadJson("./session-seed.json");
Object.entries(payload).forEach(([key, value]) => {
sessionStorage.setItem(key, value);
});
}
async function seedCookies() {
const payload = await loadJson("./cookie-seed.json");
Object.entries(payload).forEach(([key, value]) => {
document.cookie = `${key}=${value}; path=/; SameSite=Lax`;
});
}
async function ensureServiceWorker() {
if (!("serviceWorker" in navigator)) {
return;
}
await navigator.serviceWorker.register("./sw.js", { scope: "./" });
await navigator.serviceWorker.ready;
if (!navigator.serviceWorker.controller && !sessionStorage.getItem("mirror-runtime-sw-reloaded")) {
if (location.hash) {
sessionStorage.setItem("mirror-runtime-target-hash", location.hash);
}
sessionStorage.setItem("mirror-runtime-sw-reloaded", "1");
location.reload();
throw new Error("等待 Service Worker 接管当前页面");
}
sessionStorage.removeItem("mirror-runtime-sw-reloaded");
}
function buildDefaultHash() {
try {
const companyInfo = JSON.parse(storageSeed.companyInfo || "{}");
const phone = storageSeed.fromPhone || "";
const roleId = storageSeed.roleId || "";
const memberId = storageSeed.memberId || "";
const companyName = encodeURIComponent(companyInfo.fullName || "");
const companyId = companyInfo.osId || companyInfo.id || "";
const logo = encodeURIComponent(companyInfo.logo || "");
return `#/dashboard?phone=${phone}&companyName=${companyName}&companyId=${companyId}&logo=${logo}&roleId=${roleId}&memberId=${memberId}`;
} catch (_error) {
return "#/dashboard";
}
}
function pathFromHash(hash) {
if (!hash) {
return "/dashboard";
}
const value = hash.startsWith("#") ? hash.slice(1) : hash;
const pathOnly = value.split("?")[0];
return pathOnly || "/dashboard";
}
async function waitForVueRoot() {
for (let i = 0; i < 40; i += 1) {
const app = document.querySelector("#app");
const vm = app && app.__vue__;
const router = vm && vm.$router;
if (vm && router) {
return { vm, router };
}
await new Promise((resolve) => setTimeout(resolve, 250));
}
throw new Error("等待 Vue 根实例超时");
}
async function patchRuntimeRoutes() {
const { router } = await waitForVueRoot();
const rootRoute = (router.options.routes || []).find((item) => item.path === "/");
if (!rootRoute || !rootRoute.component) {
return null;
}
const existing = new Set((router.options.routes || []).map((item) => item.path));
const frameComponent = {
name: "EtmsMirrorFrame",
computed: {
frameSrc() {
const config = routeMap[this.$route.path] || { src: "/hc-etms.sqygj.cn/404/" };
return config.src || "/hc-etms.sqygj.cn/404/";
},
financeSummary() {
if (this.$route.path !== "/financeData") {
return null;
}
return [
{ label: "主营业务收入", value: "¥205,600.00" },
{ label: "营业利润", value: "¥49,900.00" },
{ label: "净利润", value: "¥40,200.00" }
];
}
},
mounted() {
this.$nextTick(() => applyGlobalFrameSkin(this.$refs.frame));
},
updated() {
this.$nextTick(() => applyGlobalFrameSkin(this.$refs.frame));
},
methods: {
onFrameLoad(event) {
applyGlobalFrameSkin(event.target);
}
},
render(h) {
const children = [];
if (this.financeSummary) {
children.push(
h(
"div",
{ class: "codex-runtime-summary" },
this.financeSummary.map((item) =>
h("div", { class: "codex-runtime-summary-card" }, [
h("span", { class: "label" }, item.label),
h("strong", item.value)
])
)
)
);
}
children.push(
h("iframe", {
ref: "frame",
class: "codex-runtime-frame",
attrs: {
src: this.frameSrc,
frameborder: "0"
},
on: {
load: this.onFrameLoad
},
style: {
height: "calc(100vh - 108px)"
}
})
);
return h("div", { class: "codex-runtime-frame-host" }, children);
}
};
const children = Object.keys(routeMap)
.filter((path) => path !== "/dashboard")
.filter((path) => !existing.has(path))
.map((path) => ({
path: path.replace(/^\//, ""),
name: `etms-mirror-${path.replace(/[^\w]/g, "-")}`,
meta: { title: (routeMap[path] && routeMap[path].title) || path.split("/").pop() || path },
component: frameComponent
}));
if (children.length) {
router.addRoutes([
{
path: "/",
component: rootRoute.component,
children
}
]);
}
const currentPath = pathFromHash(INITIAL_HASH || location.hash);
if (currentPath !== "/dashboard" && routeMap[currentPath]) {
router.replace({ path: currentPath });
}
return router;
}
function ensureHashRoute() {
const rememberedHash = sessionStorage.getItem("mirror-runtime-target-hash");
if (rememberedHash) {
if (location.hash !== rememberedHash) {
location.hash = rememberedHash;
}
sessionStorage.removeItem("mirror-runtime-target-hash");
return;
}
if (!location.hash || location.hash === "#" || location.hash === "#/") {
location.hash = buildDefaultHash();
}
}
function hideLoading() {
const loading = document.getElementById("mirror-loading");
if (loading) {
loading.style.display = "none";
}
}
function replaceTextNodeContent(root, replacements) {
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
let node = walker.nextNode();
while (node) {
const text = node.nodeValue || "";
let updated = text;
replacements.forEach(([from, to]) => {
updated = updated.replace(from, to);
});
if (updated !== text) {
node.nodeValue = updated;
}
node = walker.nextNode();
}
}
function patchDashboardSummary() {
const board = JSON.parse(storageSeed.boardInfo || "{}");
const replacements = [
[/服务项目总数:0 个/g, `服务项目总数:${board.projectCount || 94} 个`],
[/服务项目总户数:0 户/g, `服务项目总户数:${board.houseCount || 4686} 户`],
[/服务项目建筑面积:0 ㎡/g, `服务项目建筑面积:${board.floorageCount || 2888556.18} ㎡`],
[/商品即将到期项目\s*0/g, "商品即将到期项目\n3"],
[/企业剩余短信\s*0/g, "企业剩余短信\n11042"],
[/合同即将到期\s*0/g, "合同即将到期\n1"],
[/资质证书即将到期\s*0/g, "资质证书即将到期\n0"]
];
replaceTextNodeContent(document.body, replacements);
}
function scheduleDashboardPatch() {
let tries = 0;
const timer = setInterval(() => {
tries += 1;
patchDashboardSummary();
if (tries >= 8) {
clearInterval(timer);
}
}, 800);
}
function updateDocumentTitle(path) {
const config = routeMap[path];
if (config && config.title) {
document.title = `${config.title} - 企业服务平台`;
}
}
function getPresetTags(path) {
const shared = ["首页", "人事档案", "审批模板", "分公司管理", "财务数据"];
const cockpitShared = ["首页", "财务看板", "设备看板", "车场看板"];
const presets = {
"/personnelMerits/personnelFiles": shared,
"/companyMetadata/branchOfficeManage": shared,
"/companyMetadata/financeData": shared,
"/personnelFiles": shared,
"/branchOfficeManage": shared,
"/financeData": shared,
"/r2cockpit/microbrain/finance": cockpitShared,
"/r2cockpit/microbrain/equipment": cockpitShared,
"/r2cockpit/microbrain/parkingLot": cockpitShared,
"/finance": cockpitShared,
"/equipment": cockpitShared,
"/parkingLot": cockpitShared,
"/r2cockpit/cloudData/propertyFeeReport": ["首页", "物业费报表", "车场报表", "计划工单报表"],
"/r2cockpit/cloudData/parkingLotReport": ["首页", "物业费报表", "车场报表", "计划工单报表"],
"/r2cockpit/cloudData/planTaskReport": ["首页", "物业费报表", "车场报表", "计划工单报表"],
"/r2cockpit/cloudData/workOrderReport": ["首页", "计划工单报表", "非计划工单报表", "工单耗时统计"],
"/r2cockpit/cloudData/dataReport": ["首页", "计划工单报表", "非计划工单报表", "工单耗时统计"],
"/r2cockpit/cloudData/consumeReport": ["首页", "耗能报表", "作业网格台账报表", "合同计划执行报表"],
"/r2cockpit/cloudData/jobGridReport": ["首页", "耗能报表", "作业网格台账报表", "合同计划执行报表"],
"/r2cockpit/cloudData/contractPlanReport": ["首页", "耗能报表", "作业网格台账报表", "合同计划执行报表"],
"/r2cockpit/cloudData/contractGuaranteeReport": ["首页", "合同保障报表", "合同保障明细报表", "合同计划执行报表"],
"/r2cockpit/cloudData/detailedContractGuaranteeReport": ["首页", "合同保障报表", "合同保障明细报表", "合同计划执行报表"],
"/r2cockpit/cloudData/officialAccount": ["首页", "公众号拉新报表", "催收跟踪报表", "企业收费项报表", "拜访工作报表"],
"/r2cockpit/cloudData/collectionTracking": ["首页", "公众号拉新报表", "催收跟踪报表", "企业收费项报表", "拜访工作报表"],
"/r2cockpit/cloudData/collectionRate": ["首页", "公众号拉新报表", "催收跟踪报表", "企业收费项报表", "拜访工作报表"],
"/r2cockpit/cloudData/visitWorkReport": ["首页", "公众号拉新报表", "催收跟踪报表", "企业收费项报表", "拜访工作报表"],
"/personnelMerits/qualification": ["首页", "资质匹配", "员工离任报告", "人事档案"],
"/personnelMerits/employeeQuitReport": ["首页", "资质匹配", "员工离任报告", "人事档案"],
"/systemManage/operationLog": ["首页", "人事设置", "角色权限管理", "操作日志"],
"/satisfaction/questionBank": ["首页", "调查题库", "调查问卷", "调查报告", "整改跟踪"],
"/satisfaction/questionnaire": ["首页", "调查题库", "调查问卷", "调查报告", "整改跟踪"],
"/satisfaction/report": ["首页", "调查题库", "调查问卷", "调查报告", "整改跟踪"],
"/satisfaction/tracking": ["首页", "调查题库", "调查问卷", "调查报告", "整改跟踪"],
"/personnelMerits/assessment": ["首页", "人才测评", "资质匹配", "员工离任报告"],
"/supplierManage/supplierMicrobrain": ["首页", "供应商库", "合同管理", "供应商微脑"],
"/assessment": ["首页", "人才测评", "资质匹配", "员工离任报告"],
"/qualification": ["首页", "资质匹配", "员工离任报告", "人事档案"],
"/employeeQuitReport": ["首页", "资质匹配", "员工离任报告", "人事档案"],
"/operationLog": ["首页", "人事设置", "角色权限管理", "操作日志"],
"/questionBank": ["首页", "调查题库", "调查问卷", "调查报告", "整改跟踪"],
"/questionnaire": ["首页", "调查题库", "调查问卷", "调查报告", "整改跟踪"],
"/report": ["首页", "调查题库", "调查问卷", "调查报告", "整改跟踪"],
"/tracking": ["首页", "调查题库", "调查问卷", "调查报告", "整改跟踪"],
"/supplierMicrobrain": ["首页", "供应商库", "合同管理", "供应商微脑"]
};
return presets[path] || null;
}
function getTagRoute(title) {
const routeMapByTitle = {
"首页": "/dashboard",
"人事档案": "/personnelMerits/personnelFiles",
"审批模板": "/companyMetadata/approveMan",
"分公司管理": "/companyMetadata/branchOfficeManage",
"财务数据": "/companyMetadata/financeData",
"财务看板": "/finance",
"设备看板": "/equipment",
"车场看板": "/parkingLot",
"物业费报表": "/r2cockpit/cloudData/propertyFeeReport",
"车场报表": "/r2cockpit/cloudData/parkingLotReport",
"计划工单报表": "/r2cockpit/cloudData/planTaskReport",
"非计划工单报表": "/r2cockpit/cloudData/workOrderReport",
"工单耗时统计": "/r2cockpit/cloudData/dataReport",
"耗能报表": "/r2cockpit/cloudData/consumeReport",
"作业网格台账报表": "/r2cockpit/cloudData/jobGridReport",
"合同计划执行报表": "/r2cockpit/cloudData/contractPlanReport",
"合同保障报表": "/r2cockpit/cloudData/contractGuaranteeReport",
"合同保障明细报表": "/r2cockpit/cloudData/detailedContractGuaranteeReport",
"公众号拉新报表": "/r2cockpit/cloudData/officialAccount",
"催收跟踪报表": "/r2cockpit/cloudData/collectionTracking",
"企业收费项报表": "/r2cockpit/cloudData/collectionRate",
"拜访工作报表": "/r2cockpit/cloudData/visitWorkReport",
"资质匹配": "/personnelMerits/qualification",
"员工离任报告": "/personnelMerits/employeeQuitReport",
"人事设置": "/systemManage/personnelSetting",
"操作日志": "/systemManage/operationLog",
"调查题库": "/satisfaction/questionBank",
"调查问卷": "/satisfaction/questionnaire",
"调查报告": "/satisfaction/report",
"整改跟踪": "/satisfaction/tracking",
"人才测评": "/personnelMerits/assessment",
"供应商库": "/supplierManage/supplierStock",
"合同管理": "/supplierManage/contractManage",
"供应商微脑": "/supplierManage/supplierMicrobrain"
};
return routeMapByTitle[title] || "/dashboard";
}
function getTagLabel(node) {
const cloned = node.cloneNode(true);
cloned.querySelectorAll(".el-icon-close").forEach((icon) => icon.remove());
return (cloned.textContent || "").trim();
}
function createSyntheticTag(title, path, active) {
const anchor = document.createElement("a");
anchor.href = `#${path}`;
anchor.className = `tags-view-item codex-synthetic-tag${active ? " active" : ""}`;
anchor.appendChild(document.createTextNode(title));
if (title !== "首页") {
const close = document.createElement("span");
close.className = "el-icon-close";
anchor.appendChild(close);
}
return anchor;
}
function hydrateTagsView(path) {
const view = document.querySelector(".tags-view-container .el-scrollbar__view");
if (!view) {
return;
}
const preset = getPresetTags(path);
view.querySelectorAll(".codex-synthetic-tag").forEach((node) => node.remove());
if (!preset) {
return;
}
const existingNodes = [...view.querySelectorAll(".tags-view-item:not(.codex-synthetic-tag)")];
const existingMap = new Map(existingNodes.map((node) => [getTagLabel(node), node]));
const activeTitle =
(routeMap[path] && routeMap[path].title) ||
getTagLabel(view.querySelector(".tags-view-item.active") || document.createElement("span"));
preset.forEach((title) => {
let node = existingMap.get(title);
if (!node) {
node = createSyntheticTag(title, getTagRoute(title), title === activeTitle);
}
if (title === activeTitle) {
node.classList.add("active");
} else {
node.classList.remove("active");
}
view.appendChild(node);
});
}
function scheduleTagsViewHydration(path) {
let tries = 0;
const timer = setInterval(() => {
tries += 1;
hydrateTagsView(path);
if (tries >= 8) {
clearInterval(timer);
}
}, 300);
}
function installRouteBridge(router) {
if (!router || window.__ETMS_RUNTIME_BRIDGE_INSTALLED__) {
return;
}
window.__ETMS_RUNTIME_BRIDGE_INSTALLED__ = true;
document.addEventListener(
"click",
(event) => {
const anchor = event.target && event.target.closest ? event.target.closest("a[href]") : null;
if (!anchor) {
return;
}
const href = anchor.getAttribute("href") || "";
if (!href.startsWith("#/")) {
return;
}
event.preventDefault();
const raw = href.slice(1);
const path = raw.split("?")[0] || "/dashboard";
if (path === "/goToProject") {
window.location.href = "/__mirror/runtime/hc-pos-dashboard/#/dashboard";
return;
}
if (routeMap[path]) {
router.replace({ path });
updateDocumentTitle(path);
} else {
router.replace({ path: "/404" });
}
},
true
);
router.afterEach((to) => {
updateDocumentTitle(to.path);
scheduleTagsViewHydration(to.path);
});
}
try {
await seedStorage();
await seedSession();
await seedCookies();
await loadRouteMap();
await ensureServiceWorker();
ensureHashRoute();
appendStyles();
injectOuterRuntimeSkin();
for (const src of SCRIPT_SRCS) {
await appendScript(src);
}
const router = await patchRuntimeRoutes();
installRouteBridge(router);
const initialPath = pathFromHash(location.hash);
updateDocumentTitle(initialPath);
hideLoading();
scheduleDashboardPatch();
scheduleTagsViewHydration(initialPath);
installFrameSkinObserver();
} catch (error) {
const loading = document.getElementById("mirror-loading");
if (loading) {
const detail = document.createElement("small");
detail.textContent = String(error && error.message ? error.message : error);
loading.appendChild(detail);
}
}
})();