const { getDayInfo, getAlmanacInfo, getMonthCalendar, getLegalHoliday, isWorkday, getUpcomingFestivals, getNextBuddhistFestival } = require('../../utils/core/index.js'); const { SOLAR_TERM_TIMES } = require('../../utils/core/data.js'); function pad(n) { return String(n).padStart(2, '0'); } function fmt(y, m, d) { return `${y}-${pad(m)}-${pad(d)}`; } const MONTH_SPAN = 2; // 当前月前后各2个月,共5个月 Page({ data: { statusBarHeight: 20, navBarHeight: 44, viewMode: 'day', dayInfo: {}, almanac: {}, legalHoliday: null, workday: true, termTime: '', isFirstOrFifteen: false, nextBuddhist: null, showBuddhist: false, highlightLunar: true, upcoming: [], // 月历 swiper monthList: [], // [{key, year, month, weeks}] monthIndex: 2, // 当前居中 currentYear: 0, currentMonth: 0, weekHeaders: ['日', '一', '二', '三', '四', '五', '六'], // 全屏弹窗 zoomVisible: false, zoomTitle: '', zoomType: '', // yiji | detail | fest zoomData: null }, onLoad() { const sys = wx.getWindowInfo ? wx.getWindowInfo() : wx.getSystemInfoSync(); const menu = wx.getMenuButtonBoundingClientRect ? wx.getMenuButtonBoundingClientRect() : null; const statusBarHeight = sys.statusBarHeight || 20; let navBarHeight = 44; if (menu && menu.top) navBarHeight = (menu.top - statusBarHeight) * 2 + menu.height; this.setData({ statusBarHeight, navBarHeight }); this.loadSettings(); this.loadDay(new Date()); this.loadUpcoming(); }, onShow() { this.loadSettings(); // 设置可能变化,刷新 if (this.data.dayInfo.solarYear) this.refreshDerived(); }, loadSettings() { const s = wx.getStorageSync('lunar-settings') || {}; this.setData({ showBuddhist: s.showBuddhist === true, highlightLunar: s.highlightLunar !== false }); }, onPullDownRefresh() { if (this.data.viewMode === 'day') { this.loadDay(new Date()); this.loadUpcoming(); } else { this.buildMonthList(this.data.currentYear, this.data.currentMonth); } wx.stopPullDownRefresh(); }, /** 加载某日的老黄历 */ loadDay(date) { const y = date.getFullYear(); const m = date.getMonth() + 1; const d = date.getDate(); const dayInfo = getDayInfo(y, m, d); const almanac = getAlmanacInfo(y, m, d); this.setData({ dayInfo, almanac, currentYear: y, currentMonth: m }); this.refreshDerived(); this.loadUpcoming(); }, /** 计算派生数据(节假日/工作日/佛历/初一十五) */ refreshDerived() { const { dayInfo, showBuddhist, highlightLunar } = this.data; const { solarYear: y, solarMonth: m, solarDay: d } = dayInfo; const legalHoliday = getLegalHoliday(y, m, d); const workday = isWorkday(y, m, d); const termTime = dayInfo.solarTerm ? (SOLAR_TERM_TIMES[dayInfo.solarTerm] || '') : ''; const isFirstOrFifteen = highlightLunar && (dayInfo.lunarDay === 1 || dayInfo.lunarDay === 15); const nextBuddhist = showBuddhist ? getNextBuddhistFestival(y, m, d) : null; this.setData({ legalHoliday, workday, termTime, isFirstOrFifteen, nextBuddhist }); }, loadUpcoming() { const { dayInfo } = this.data; const { solarYear: y, solarMonth: m, solarDay: d } = dayInfo; this.setData({ upcoming: getUpcomingFestivals(5, y, m, d) }); }, prevDay() { this.shiftDay(-1); }, nextDay() { this.shiftDay(1); }, shiftDay(delta) { const { dayInfo } = this.data; const date = new Date(dayInfo.solarYear, dayInfo.solarMonth - 1, dayInfo.solarDay + delta); this.loadDay(date); }, backToday() { this.loadDay(new Date()); this.loadUpcoming(); }, /** 切换 日/月 视图 */ toggleView() { const mode = this.data.viewMode === 'day' ? 'month' : 'day'; this.setData({ viewMode: mode }); if (mode === 'month') { const { dayInfo } = this.data; this.buildMonthList(dayInfo.solarYear, dayInfo.solarMonth); } }, /** 构建5个月的数据,居中显示 */ buildMonthList(year, month) { const monthList = []; for (let i = -MONTH_SPAN; i <= MONTH_SPAN; i++) { let y = year, m = month + i; while (m < 1) { m += 12; y--; } while (m > 12) { m -= 12; y++; } const weeks = getMonthCalendar(y, m); monthList.push({ key: `${y}-${m}`, year: y, month: m, weeks }); } this.setData({ monthList, monthIndex: MONTH_SPAN, currentYear: year, currentMonth: month }); }, /** swiper 切换 */ onMonthSwiperChange(e) { const index = e.detail.current; const { monthList } = this.data; const cur = monthList[index]; this.setData({ monthIndex: index, currentYear: cur.year, currentMonth: cur.month }); // 边缘时向对应方向补一个月,保持可无限滚动 if (index === 0) { this.prependMonth(); } else if (index === monthList.length - 1) { this.appendMonth(); } }, prependMonth() { const { monthList } = this.data; const first = monthList[0]; let y = first.year, m = first.month - 1; if (m < 1) { m = 12; y--; } const weeks = getMonthCalendar(y, m); monthList.unshift({ key: `${y}-${m}`, year: y, month: m, weeks }); if (monthList.length > 7) monthList.pop(); this.setData({ monthList, monthIndex: this.data.monthIndex + 1 }); }, appendMonth() { const { monthList } = this.data; const last = monthList[monthList.length - 1]; let y = last.year, m = last.month + 1; if (m > 12) { m = 1; y++; } const weeks = getMonthCalendar(y, m); monthList.push({ key: `${y}-${m}`, year: y, month: m, weeks }); if (monthList.length > 7) monthList.shift(); this.setData({ monthList, monthIndex: this.data.monthIndex - 1 }); }, /** 月历点选某天 → 切回日视图 */ selectDay(e) { const date = e.currentTarget.dataset.date; const [y, m, d] = date.split('-').map(Number); this.loadDay(new Date(y, m - 1, d)); this.setData({ viewMode: 'day' }); }, goDetail() { const { dayInfo } = this.data; wx.navigateTo({ url: `/pages/day-detail/day-detail?date=${fmt(dayInfo.solarYear, dayInfo.solarMonth, dayInfo.solarDay)}` }); }, /** 跳转到某节日的老黄历 */ goFestival(e) { const date = e.currentTarget.dataset.date; const [y, m, d] = date.split('-').map(Number); this.loadDay(new Date(y, m - 1, d)); this.setData({ viewMode: 'day' }); wx.pageScrollTo && wx.pageScrollTo({ scrollTop: 0, duration: 0 }); }, /** ===== 全屏放大弹窗 ===== */ openZoom(e) { const type = e.currentTarget.dataset.type; const { dayInfo, almanac, legalHoliday, termTime } = this.data; let zoomTitle = ''; let zoomData = null; if (type === 'yiji') { zoomTitle = `${dayInfo.solarMonth}月${dayInfo.solarDay}日 宜忌`; zoomData = { recommends: almanac.recommends, avoids: almanac.avoids }; } else if (type === 'detail') { zoomTitle = `${dayInfo.solarMonth}月${dayInfo.solarDay}日 黄历详情`; zoomData = { lunar: `${dayInfo.lunarMonthName}${dayInfo.lunarDayName}`, ganzhi: `${dayInfo.lunarYearGanzhi}年 ${dayInfo.lunarMonthGanzhi}月 ${dayInfo.lunarDayGanzhi}日`, duty: almanac.duty, twelveStar: `${almanac.twelveStar.name}(${almanac.twelveStar.ecliptic})`, twentyEightStar: almanac.twentyEightStar.name, sixStar: almanac.sixStar, clash: `冲${almanac.clash} 煞${almanac.evilDirection}`, pengZu: almanac.pengZu, legalHoliday, termTime: dayInfo.solarTerm ? `${dayInfo.solarTerm} ${termTime}` : '' }; } else if (type === 'fest') { zoomTitle = '近期节日'; zoomData = { upcoming: this.data.upcoming }; } this.setData({ zoomVisible: true, zoomTitle, zoomType: type, zoomData }); }, closeZoom() { this.setData({ zoomVisible: false }); }, navTo(e) { wx.navigateTo({ url: e.currentTarget.dataset.url }); }, noop() {} });