SunMaster · 2026 Edition

Every catalogue.
One click away.

Twenty-five product catalogues covering solar street lighting, PV modules, energy storage, flood lights and specialist applications. Open any catalogue and read it online — no download required.

25 Catalogues
7 Product lines
474 Pages in total
25 catalogues

All catalogues

Street Light 19 pages

Solar Street Light — Project Type

Government & municipal engineering series, designed for tender specifications.

Street Light 15 pages

Solar Street Light — Economical

Cost-effective all-in-one series for volume residential and rural projects.

Street Light 32 pages

All-in-One Solar LED Street Light

Integrated design with MPPT controller, LiFePO4 battery and LED module.

Street Light 46 pages

Solar Garden Lamp

Courtyard and landscape lighting with bollard, post-top and wall types.

Street Light 8 pages

Solar Street Light — Steel Housing

Heavy-duty steel housing series for high-humidity and coastal installations.

Street Light 20 pages

Split Solar Street Light with Camera

Half-split configuration with integrated 4G CCTV and monitoring platform.

Smart & IoT 20 pages

Smart Solar Street Light Solution

Smart public facilities overall solution with remote dimming and fault alerts.

Smart & IoT 4 pages

IoT Monitoring System

4G cloud platform for real-time monitoring of solar lighting assets.

Poles 8 pages

Vertical Solar Lighting

Vertical pole-integrated solar lighting for highways and urban corridors.

Poles 8 pages

Solar Post Light — Octagon Series

Octagonal solar post light with full-day charging and motion sensing.

Poles 4 pages

Solar Pole Light

Complete solar pole solutions with round and square pole options.

Panels 30 pages

Solar Panel

Monocrystalline and polycrystalline modules for on-grid and off-grid use.

Panels 12 pages

Flexible Solar Panel

Lightweight bendable modules for curved roofs, RVs and boats.

Panels 7 pages

Transparent Glass-Glass Module

Bifacial transparent modules for greenhouses, carports and facades.

Panels 7 pages

Foldable Solar Panel

Portable folding panels with high-frequency MPPT for outdoor power.

Storage 62 pages

Battery Energy Storage System

Rack, stacked and wall-mounted LiFePO4 systems with BMS protection.

Storage 30 pages

Solar Micro-Inverter Solution

Micro-inverter and balcony solar system for plug-and-play PV.

Storage 2 pages

Portable Solar Generator

All-in-one portable power station with high-frequency MPPT solar charger.

Storage 4 pages

Solar Balcony System

Balcony-mounted PV kit for residential self-consumption.

Flood Light 15 pages

Solar Flood Light

High-lumen solar flood lights for security, yards and industrial areas.

Applications 5 pages

Smart Solar Bench

Solar-powered smart bench with WiFi, USB charging and air monitoring.

Applications 19 pages

Solar Water Pump

Solar PV water pumping systems for agriculture and rural supply.

Applications 10 pages

Solar Air Conditioner

Hybrid solar air conditioners with grid and PV dual input.

Applications 72 pages

Solar Traffic Light & Road Stud

Solar traffic signals, warning lights, road studs and toll station series.

Applications 15 pages

Solar & Wind Hybrid Street Light

Wind-solar complementary street lighting for coastal and windy regions.

Need a spec sheet or a project quotation?

Tell us the model, quantity and destination — our engineering team replies with datasheets, certifications and FOB pricing within one working day.

"; } function buildChips() { var counts = {}; BOOKS.forEach(function (b) { counts[b.cat] = (counts[b.cat] || 0) + 1; }); var html = chipHtml("all", "All catalogues", BOOKS.length); CATS.forEach(function (c) { html += chipHtml(c.id, CAT_LABEL[c.id] || c.name, counts[c.id] || 0); }); chips.innerHTML = html; chips.querySelectorAll(".chip").forEach(function (el) { el.addEventListener("click", function () { state.cat = el.dataset.cat; chips.querySelectorAll(".chip").forEach(function (x) { x.classList.toggle("is-on", x.dataset.cat === state.cat); x.setAttribute("aria-selected", x.dataset.cat === state.cat ? "true" : "false"); }); render(); }); }); } /* ---------------- cards ---------------- */ function match(b) { if (state.cat !== "all" && b.cat !== state.cat) return false; if (!state.q) return true; var hay = (b.title + " " + b.desc + " " + (CAT_LABEL[b.cat] || "") + " " + b.id).toLowerCase(); return state.q.split(/\s+/).every(function (w) { return hay.indexOf(w) > -1; }); } function esc(s) { return String(s).replace(/[&<>"]/g, function (c) { return { "&": "&", "<": "<", ">": ">", '"': """ }[c]; }); } var ICON_COPY = ' '; var ICON_DL = ' '; var ICON_GO = ' '; function cardHtml(b, i) { var pr = (i === undefined || i < 4) ? ' fetchpriority="high"' : ' fetchpriority="low"'; var link = standaloneUrl(b.id); return '' + '
' + '
' + ' ' + (CAT_LABEL[b.cat] || "Catalogue") + "" + ' ' + b.pages + " pages" + '
' + ' ' + "
" + "
" + '
' + "

" + esc(b.title) + "

" + "

" + esc(b.desc) + "

" + '
' + ' Read online' + ICON_GO + "" + ' " + ' ' + ICON_DL + "" + "
" + "
" + "
"; } function render() { var list = BOOKS.filter(match); grid.innerHTML = list.map(function (b, i) { return cardHtml(b, i); }).join(""); /* 只有在客户「真的搜/筛过」且没结果时才提示,避免异常情况误报「没有匹配」 */ emptyBox.hidden = !(list.length === 0 && (state.q || state.cat !== "all")); countLabel.textContent = list.length + (list.length === 1 ? " catalogue" : " catalogues"); var cat = CATS.filter(function (c) { return c.id === state.cat; })[0]; secTitle.textContent = state.cat === "all" ? "All catalogues" : (cat ? cat.name.replace(/&/g, "&") : "Catalogues"); secDesc.textContent = state.cat === "all" ? "Click any catalogue to open its own page and read it online. Every catalogue is the original print PDF." : (cat ? cat.desc.replace(/&/g, "&") : ""); grid.querySelectorAll(".card").forEach(function (el) { el.addEventListener("click", function (e) { if (e.target.closest("a,button")) return; /* 按钮各自处理 */ location.href = el.dataset.link; }); el.addEventListener("keydown", function (e) { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); location.href = el.dataset.link; } }); }); grid.querySelectorAll(".btn-copy").forEach(function (btn) { btn.addEventListener("click", function (e) { e.stopPropagation(); copyLink(btn.dataset.link); }); }); } /* ---------------- 复制链接 ---------------- */ function toast(msg) { toastEl.textContent = msg; toastEl.hidden = false; toastEl.classList.add("is-on"); clearTimeout(toast._t); toast._t = setTimeout(function () { toastEl.classList.remove("is-on"); setTimeout(function () { toastEl.hidden = true; }, 300); }, 1900); } function copyLink(text) { function done() { toast("Link copied — paste it to your customer"); } if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(text).then(done, function () { legacyCopy(text, done); }); } else { legacyCopy(text, done); } } function legacyCopy(text, done) { var ta = document.createElement("textarea"); ta.value = text; ta.setAttribute("readonly", ""); ta.style.cssText = "position:fixed;top:-1000px;left:0;opacity:0"; document.body.appendChild(ta); ta.select(); var ok = false; try { ok = document.execCommand("copy"); } catch (e) {} document.body.removeChild(ta); if (ok) done(); else toast("Copy failed — the link is: " + text); } /* ========================================================================== 阅读器 ========================================================================== */ var cur = null; var abortCtl = null; var blobCache = {}; var blobOrder = []; var canFetch = !!(window.fetch && window.Blob && window.URL && URL.createObjectURL); function fmtMB(n) { if (!n) return "0 MB"; return (n / 1048576).toFixed(n > 10485760 ? 0 : 1) + " MB"; } function remember(id, url) { blobCache[id] = url; blobOrder.push(id); while (blobOrder.length > 3) { var old = blobOrder.shift(); if (old !== id && blobCache[old]) { try { URL.revokeObjectURL(blobCache[old]); } catch (e) {} delete blobCache[old]; } } } function showLoading(b) { frame.hidden = true; fallback.hidden = true; loading.hidden = false; plName.textContent = b.title; plBar.style.width = "0%"; plBar.parentNode.classList.remove("is-unknown"); plPct.textContent = "Connecting…"; } function setProgress(pct, got, total) { if (total) { plBar.style.width = Math.max(2, pct) + "%"; plPct.textContent = pct + "% · " + fmtMB(got) + " / " + fmtMB(total); } else { plBar.parentNode.classList.add("is-unknown"); plPct.textContent = fmtMB(got) + " downloaded"; } } function showFrame(blobUrl) { loading.hidden = true; fallback.hidden = true; frame.hidden = false; /* 不带 #view= 之类参数:参数偶发会让内置阅读器初始化失败 */ frame.src = blobUrl; } function fail(b, url, reason) { loading.hidden = true; frame.hidden = true; fallback.hidden = false; fbTitle.textContent = b.title; fbText.textContent = reason === "NOT_PDF" ? "The server returned something other than a PDF for this file. Open it directly or download it instead." : "This catalogue could not be loaded just now. Please try again, or open the PDF directly."; fbOpen.href = url; } /* 最后一道保险:自己下载失败时,退回浏览器直连(浏览器内置阅读器边下边看) */ function showDirect(b, url) { loading.hidden = true; fallback.hidden = true; frame.hidden = false; frame.src = url; } /* 体积分流阈值: ≤ 8MB → 整本下完再显示(一次成功,不会中途断) > 8MB → 直接交给浏览器边下边看,第一页秒出,用户立刻能读 体积在 data.js 里每本书的 "size" 字段(换文件后记得更新) */ var BIG_FILE = 8 * 1048576; /* 取整本 PDF(下载中断自动断点续传,最多 4 轮) */ function loadPdf(b, round) { round = round || 0; var url = pdfUrl(b); if (blobCache[b.id]) { showFrame(blobCache[b.id]); return; } if (!canFetch) { fail(b, url); return; } if (abortCtl) { try { abortCtl.abort(); } catch (e) {} } abortCtl = ("AbortController" in window) ? new AbortController() : null; showLoading(b); var chunks = []; var got = 0; var total = 0; function finish() { var out = new Uint8Array(got), off = 0; for (var i = 0; i < chunks.length; i++) { out.set(chunks[i], off); off += chunks[i].length; } /* 简单校验:PDF 头必须是 %PDF */ var head = String.fromCharCode(out[0], out[1], out[2], out[3]); if (head !== "%PDF") { fail(b, url, "NOT_PDF"); return; } var blobUrl = URL.createObjectURL(new Blob([out.buffer], { type: "application/pdf" })); remember(b.id, blobUrl); if (cur && cur.id === b.id) showFrame(blobUrl); } function attempt(from) { var headers = {}; if (from > 0) headers.Range = "bytes=" + from + "-"; return fetch(url, { credentials: "omit", cache: "no-store", headers: headers, signal: abortCtl ? abortCtl.signal : undefined }).then(function (res) { if (from > 0 && res.status !== 206) { /* 服务器不支持续传 → 从头再来 */ chunks = []; got = 0; from = 0; } if (!res.ok && res.status !== 206) throw new Error("HTTP " + res.status); var ct = (res.headers.get("content-type") || "").toLowerCase(); if (ct && ct.indexOf("pdf") === -1 && ct.indexOf("octet-stream") === -1) { throw new Error("NOT_PDF"); } var cr = res.headers.get("content-range"); if (cr) { var m = /\/(\d+)/.exec(cr); if (m) total = Number(m[1]) || total; } if (!total) total = Number(res.headers.get("content-length")) || 0; /* 保险:万一 data.js 里的体积过期了(有人换了更大的文件), 发现太大就立刻改成「边下边看」,不让客户干等整本下完 */ if (from === 0 && total > BIG_FILE) throw new Error("TOO_BIG"); if (!res.body || !res.body.getReader) { return res.arrayBuffer().then(function (buf) { chunks.push(new Uint8Array(buf)); got += buf.byteLength; setProgress(100, got, total || got); finish(); }); } var rs = res.body.getReader(); return (function pump() { return rs.read().then(function (r) { if (r.done) { finish(); return; } chunks.push(r.value); got += r.value.length; setProgress(total ? Math.min(99, Math.round(got / total * 100)) : 0, got, total); return pump(); }); })(); }); } attempt(0).catch(function (err) { if (err && err.name === "AbortError") return; var msg = (err && err.message) || ""; /* 实际文件比记录的大 → 立刻改用边下边看 */ if (msg === "TOO_BIG") { showDirect(b, url); return; } var isNetwork = (err instanceof TypeError) || /Failed to fetch|NetworkError|Load failed|network/i.test(msg); /* 网络类错误:先重试一次,仍不行就直接交给浏览器 */ if (isNetwork) { if (round < 1) { setTimeout(function () { loadPdf(b, round + 1); }, 500); } else { showDirect(b, url); } return; } /* 已经下到一部分 → 断点续传再试;完全没下到 → 换一轮重试 */ if (round < 2) { if (got > 0 && got < (total || Infinity)) { plPct.textContent = "Connection dropped — resuming…"; setTimeout(function () { attempt(got).catch(function (e2) { if (e2 && e2.name === "AbortError") return; loadPdf(b, round + 1); }); }, 400); } else { setTimeout(function () { loadPdf(b, round + 1); }, 600 * (round + 1)); } return; } /* 全都失败 → 退回浏览器直连,至少不让页面空着 */ if (window.console) console.warn("[catalogue] fetch failed, falling back to direct:", msg); showDirect(b, url); }); } /* 打开一本图册时先决定用哪种方式加载 */ function startLoad(b) { var url = pdfUrl(b); if (blobCache[b.id]) { showFrame(blobCache[b.id]); return; } if (!canFetch) { showDirect(b, url); return; } if (abortCtl) { try { abortCtl.abort(); } catch (e) {} abortCtl = null; } /* 大文件(或没有体积信息)→ 边下边看,第一页立刻出来,不用等 */ var size = Number(b.size) || 0; if (!size || size > BIG_FILE) { showDirect(b, url); return; } loading.hidden = false; frame.hidden = true; fallback.hidden = true; plName.textContent = b.title; plBar.style.width = "0%"; plBar.parentNode.classList.remove("is-unknown"); plPct.textContent = "Preparing…"; loadPdf(b); } /* ========================================================================== 阅读模式开关 --------------------------------------------------------------------------- ★ 为什么不用 class 切换(2026-11-09 踩过的坑)★ 领动云站把整个静态页塞进 #static-page-isolation-root #static-page-xxxx 容器, 并且**给所有 CSS 选择器加了这个前缀**:`html.is-reader .hero{display:none}` 会被改写成 `#root #container.is-reader .hero{display:none}`。 也就是说 .is-reader 必须挂在**它自己的容器**上才生效,挂在 上永远是死的 —— 结果就是加了参数也一直显示集合页。 所以这里改成:① 尝试识别平台容器并加类(让整套 CSS 也能起作用); ② 无论如何都用**内联 style** 强制生效(内联样式优先级最高,平台改不到)。 ========================================================================== */ var HIDE_IN_READER = [".hero", ".toolbar", ".lib", ".cta"]; function platformRoot() { /* 从自己的内容往上找平台包的那层容器(本地预览时找不到,返回 null) */ var e = document.querySelector(".hero") || document.querySelector(".lib"); while (e && e !== document.body && e !== document.documentElement) { if (e.id && /^static-page-/.test(e.id)) return e; e = e.parentElement; } return null; } function enterReaderMode() { document.documentElement.classList.add("is-reader"); var pr = platformRoot(); if (pr) pr.classList.add("is-reader"); HIDE_IN_READER.forEach(function (sel) { var el = document.querySelector(sel); if (el) el.style.setProperty("display", "none", "important"); }); if (!reader) return; reader.style.display = "flex"; reader.style.flexDirection = "column"; reader.style.position = "static"; reader.style.opacity = "1"; reader.style.pointerEvents = "auto"; reader.style.background = "#0A0F0B"; reader.style.minHeight = "0"; /* 平台顶部还有自己的导航条,100vh 会被截掉一截 → 按实际位置算高度 */ fitReader(); document.documentElement.style.background = "#0A0F0B"; if (document.body) { document.body.style.background = "#0A0F0B"; document.body.style.overflow = "hidden"; } try { window.scrollTo(0, 0); } catch (e) {} } function fitReader() { if (!reader) return; var top = reader.getBoundingClientRect().top; var h = Math.round(window.innerHeight - Math.max(0, top)); if (h < 420) h = 420; reader.style.height = h + "px"; reader.style.maxHeight = h + "px"; } function exitReaderMode() { document.documentElement.classList.remove("is-reader"); var pr = platformRoot(); if (pr) pr.classList.remove("is-reader"); HIDE_IN_READER.forEach(function (sel) { var el = document.querySelector(sel); if (el) el.style.removeProperty("display"); }); if (reader) { reader.style.display = "none"; reader.style.height = ""; reader.style.maxHeight = ""; } if (document.body) document.body.style.overflow = ""; } function openCatalogue(b) { cur = b; var url = pdfUrl(b); /* iOS Safari 不能内嵌 PDF,直接把客户送到 PDF(可翻页、可分享) */ if (/iPad|iPhone|iPod/.test(navigator.userAgent) || (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1)) { location.replace(url); return; } enterReaderMode(); reader.setAttribute("aria-hidden", "false"); rTitle.textContent = b.title; rMeta.textContent = b.pages + " pages · " + (CAT_LABEL[b.cat] || "Catalogue"); rOpenDl.href = url; plAlt.href = url; fbOpen.href = url; readerBack.href = PAGE_URL; document.title = b.title + " | SunMaster Solar"; /* 规范网址:把 #cat= 纠正成 ?cat=,方便复制 */ try { if (history.replaceState && location.search.indexOf("cat=") === -1) { history.replaceState(null, "", standaloneUrl(b.id)); } } catch (e) {} startLoad(b); } /* 工具栏 */ document.getElementById("readerCopy").addEventListener("click", function () { if (cur) copyLink(standaloneUrl(cur.id)); }); /* Reload = 强制走「整本下完再显示」这条路,绕开浏览器内置阅读器,保证一定能看到 */ document.getElementById("readerReload").addEventListener("click", function () { if (!cur) return; if (blobCache[cur.id]) { try { URL.revokeObjectURL(blobCache[cur.id]); } catch (e) {} delete blobCache[cur.id]; } loadPdf(cur); }); fbRetry.addEventListener("click", function () { if (cur) loadPdf(cur); }); window.addEventListener("pagehide", function () { blobOrder.forEach(function (id) { if (blobCache[id]) { try { URL.revokeObjectURL(blobCache[id]); } catch (e) {} } }); blobCache = {}; blobOrder = []; }); /* 窗口尺寸变了要重新贴合(平台顶部导航高度也会变) */ var rsT; window.addEventListener("resize", function () { if (!cur || !reader || reader.style.display !== "flex") return; clearTimeout(rsT); rsT = setTimeout(fitReader, 120); }); /* ---------------- search ---------------- */ var tId; searchInput.addEventListener("input", function () { clearTimeout(tId); tId = setTimeout(function () { state.q = searchInput.value.trim().toLowerCase(); searchClear.hidden = !state.q; render(); }, 140); }); searchClear.addEventListener("click", function () { searchInput.value = ""; state.q = ""; searchClear.hidden = true; render(); searchInput.focus(); }); /* ---------------- boot ---------------- */ var wantId = requestedId(); var wantBook = wantId ? bookById(wantId) : null; if (wantBook) { try { openCatalogue(wantBook); } catch (e) { /* 阅读页起不来 → 退回列表,绝不留白屏 */ if (window.console) console.warn("[catalogue] reader failed:", e); try { exitReaderMode(); } catch (e2) {} wantBook = null; } } if (!wantBook) { try { buildChips(); } catch (e) { if (window.console) console.warn("[catalogue] chips failed:", e); } try { render(); } catch (e) { if (window.console) console.warn("[catalogue] render failed:", e); } } })(); } catch (error) { console.error("[static-page] 内联脚本执行失败", error); }