const nav = require("../../data/links.json"); function countLinks(cat) { let n = 0; const groups = cat.groups || []; for (let i = 0; i < groups.length; i++) { n += (groups[i].links || []).length; } return n; } function withCounts(categories) { return (categories || []).map((c) => Object.assign({}, c, { linkCount: countLinks(c) }) ); } Page({ data: { brand: nav.brand || "游民导航", tagline: nav.tagline || "", footer: nav.footer || "", brandIcon: nav.brandIcon || "/icons/_brand.webp", categories: withCounts(nav.categories), activeId: (nav.categories && nav.categories[0] && nav.categories[0].id) || "", activeTitle: (nav.categories && nav.categories[0] && nav.categories[0].title) || "", theme: "light", drawerOpen: false, showTop: false, toast: "", statusBarHeight: 20, navBarHeight: 44, sheetOpen: false, sheetLink: null, }, _jumping: false, _sectionTops: [], _toastTimer: null, onLoad() { const sys = wx.getWindowInfo ? wx.getWindowInfo() : wx.getSystemInfoSync(); const statusBarHeight = sys.statusBarHeight || 20; const menu = wx.getMenuButtonBoundingClientRect ? wx.getMenuButtonBoundingClientRect() : null; let navBarHeight = 44; if (menu && menu.height) { navBarHeight = (menu.top - statusBarHeight) * 2 + menu.height; } const app = getApp(); const theme = (app && app.globalData && app.globalData.theme) || "light"; this.setData({ statusBarHeight, navBarHeight, theme, }); this._applyTheme(theme); }, onReady() { wx.nextTick(() => this._measureSections()); }, onShow() { this._applyTheme(this.data.theme); }, onPageScroll(e) { const scrollTop = e.scrollTop || 0; const showTop = scrollTop > 480; if (showTop !== this.data.showTop) { this.setData({ showTop }); } if (this._jumping || !this._sectionTops.length) return; const marker = scrollTop + this.data.statusBarHeight + this.data.navBarHeight + 24; let current = this._sectionTops[0].id; for (let i = 0; i < this._sectionTops.length; i++) { if (this._sectionTops[i].top <= marker) current = this._sectionTops[i].id; else break; } if (current !== this.data.activeId) { const cat = this.data.categories.find((c) => c.id === current); this.setData({ activeId: current, activeTitle: (cat && cat.title) || "", }); } }, _measureSections() { const query = wx.createSelectorQuery(); query.selectAll(".cat-panel").boundingClientRect(); query.selectViewport().scrollOffset(); query.exec((res) => { const rects = (res && res[0]) || []; const scroll = (res && res[1]) || { scrollTop: 0 }; this._sectionTops = rects.map((r) => ({ id: (r.id || "").replace(/^cat-/, ""), top: (r.top || 0) + (scroll.scrollTop || 0), })); }); }, _applyTheme(theme) { const dark = theme === "dark"; wx.setNavigationBarColor({ frontColor: dark ? "#ffffff" : "#000000", backgroundColor: dark ? "#0a0f14" : "#e9eef4", animation: { duration: 200, timingFunc: "easeIn" }, }); wx.setBackgroundColor({ backgroundColor: dark ? "#0a0f14" : "#e9eef4", backgroundColorTop: dark ? "#0a0f14" : "#e9eef4", backgroundColorBottom: dark ? "#0a0f14" : "#e9eef4", }); }, openDrawer() { this.setData({ drawerOpen: true }); }, closeDrawer() { this.setData({ drawerOpen: false }); }, noop() {}, toggleTheme() { const theme = this.data.theme === "dark" ? "light" : "dark"; this.setData({ theme }); try { wx.setStorageSync("navmini-theme", theme); } catch (e) { /* ignore */ } const app = getApp(); if (app && app.globalData) app.globalData.theme = theme; this._applyTheme(theme); }, onSelectCategory(e) { const id = e.currentTarget.dataset.id; if (!id) return; const cat = this.data.categories.find((c) => c.id === id); this.setData({ drawerOpen: false, activeId: id, activeTitle: (cat && cat.title) || "", }); this._jumping = true; wx.pageScrollTo({ selector: `#cat-${id}`, duration: 320, offsetTop: -(this.data.statusBarHeight + this.data.navBarHeight + 8), complete: () => { setTimeout(() => { this._jumping = false; this._measureSections(); }, 360); }, }); }, onTapLink(e) { const { id, catid, groupid } = e.currentTarget.dataset; let link = null; const cat = this.data.categories.find((c) => c.id === catid); if (cat) { const group = (cat.groups || []).find((g) => g.id === groupid); if (group) link = (group.links || []).find((l) => l.id === id); } if (!link || !link.href) { this._showToast("无效链接"); return; } this.setData({ sheetOpen: true, sheetLink: link }); }, closeSheet() { this.setData({ sheetOpen: false, sheetLink: null }); }, copySheetUrl() { const link = this.data.sheetLink; if (!link || !link.href) return; wx.setClipboardData({ data: link.href, success: () => { this._showToast("已复制,请到浏览器打开"); }, fail: () => { this._showToast("复制失败"); }, }); }, backTop() { wx.pageScrollTo({ scrollTop: 0, duration: 300 }); }, _showToast(msg) { if (this._toastTimer) clearTimeout(this._toastTimer); this.setData({ toast: msg }); this._toastTimer = setTimeout(() => { this.setData({ toast: "" }); this._toastTimer = null; }, 1800); }, });