Files
lunar-mini/mini/pages/home/home.js
T
gouki 692f291338
Publish Mini Program Dev Version / publish (push) Has been cancelled
feat(home): 日视图swiper轮播+老黄历方框合并+引入lunar-javascript真实宜忌
1. 日视图改为swiper轮播,左右滑动切换日期,箭头固定在最左最右
2. 大日期方框扩大到包含农历和干支
3. 生肖(马年)移到导航栏右侧
4. 星期移到工作日提示左侧
5. 引入lunar-javascript(6tail库),用真实宜忌(最多20+项)替换手写4-5项
6. 值神/黄道详情样式调整:label大、value小、加间隔
7. 去掉点击放大提示
2026-08-08 14:04:59 +00:00

296 lines
9.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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个月
const DAY_SPAN = 2; // 当前日前后各2天,共5天
Page({
data: {
statusBarHeight: 20,
navBarHeight: 44,
viewMode: 'day',
// 日视图 swiper
dayList: [], // [{key, dayInfo, almanac, legalHoliday, workday, termTime, isFirstOrFifteen, nextBuddhist, showBuddhist, upcoming}]
dayIndex: 2, // 当前居中
// 月历 swiper
monthList: [],
monthIndex: 2,
currentYear: 0,
currentMonth: 0,
weekHeaders: ['日', '一', '二', '三', '四', '五', '六'],
// 当前选中日期(用于月历联动)
dayInfo: {},
// 全屏弹窗
zoomVisible: false,
zoomTitle: '',
zoomType: '',
zoomData: null,
// 设置
showBuddhist: false,
highlightLunar: true
},
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.buildDayList(new Date());
},
onShow() {
this.loadSettings();
if (this.data.dayList.length > 0) this.refreshDayListSettings();
},
loadSettings() {
const s = wx.getStorageSync('lunar-settings') || {};
this.setData({
showBuddhist: s.showBuddhist === true,
highlightLunar: s.highlightLunar !== false
});
},
onPullDownRefresh() {
if (this.data.viewMode === 'day') {
this.buildDayList(new Date());
} else {
this.buildMonthList(this.data.currentYear, this.data.currentMonth);
}
wx.stopPullDownRefresh();
},
/** 构建某日的完整数据 */
buildDayData(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);
const legalHoliday = getLegalHoliday(y, m, d);
const workday = isWorkday(y, m, d);
const termTime = dayInfo.solarTerm ? (SOLAR_TERM_TIMES[dayInfo.solarTerm] || '') : '';
const isFirstOrFifteen = this.data.highlightLunar && (dayInfo.lunarDay === 1 || dayInfo.lunarDay === 15);
const nextBuddhist = this.data.showBuddhist ? getNextBuddhistFestival(y, m, d) : null;
const upcoming = getUpcomingFestivals(5, y, m, d);
return {
key: fmt(y, m, d),
dayInfo, almanac, legalHoliday, workday, termTime,
isFirstOrFifteen, nextBuddhist, upcoming,
showBuddhist: this.data.showBuddhist
};
},
/** 构建5天的数据,居中显示 */
buildDayList(centerDate) {
const dayList = [];
for (let i = -DAY_SPAN; i <= DAY_SPAN; i++) {
const date = new Date(centerDate.getFullYear(), centerDate.getMonth(), centerDate.getDate() + i);
dayList.push(this.buildDayData(date));
}
const center = dayList[DAY_SPAN];
this.setData({
dayList,
dayIndex: DAY_SPAN,
dayInfo: center.dayInfo,
currentYear: center.dayInfo.solarYear,
currentMonth: center.dayInfo.solarMonth
});
},
/** 设置变化后刷新 dayList */
refreshDayListSettings() {
const dayList = this.data.dayList.map(item => ({
...item,
showBuddhist: this.data.showBuddhist,
isFirstOrFifteen: this.data.highlightLunar && (item.dayInfo.lunarDay === 1 || item.dayInfo.lunarDay === 15),
nextBuddhist: this.data.showBuddhist ? getNextBuddhistFestival(item.dayInfo.solarYear, item.dayInfo.solarMonth, item.dayInfo.solarDay) : null
}));
this.setData({ dayList });
},
/** 日视图 swiper 切换 */
onDaySwiperChange(e) {
const index = e.detail.current;
const { dayList } = this.data;
const cur = dayList[index];
this.setData({
dayIndex: index,
dayInfo: cur.dayInfo,
currentYear: cur.dayInfo.solarYear,
currentMonth: cur.dayInfo.solarMonth
});
// 边缘时向对应方向补一天,保持可无限滑动
if (index === 0) {
this.prependDay();
} else if (index === dayList.length - 1) {
this.appendDay();
}
},
prependDay() {
const { dayList } = this.data;
const first = dayList[0];
const date = new Date(first.dayInfo.solarYear, first.dayInfo.solarMonth - 1, first.dayInfo.solarDay - 1);
dayList.unshift(this.buildDayData(date));
if (dayList.length > 7) dayList.pop();
this.setData({ dayList, dayIndex: this.data.dayIndex + 1 });
},
appendDay() {
const { dayList } = this.data;
const last = dayList[dayList.length - 1];
const date = new Date(last.dayInfo.solarYear, last.dayInfo.solarMonth - 1, last.dayInfo.solarDay + 1);
dayList.push(this.buildDayData(date));
if (dayList.length > 7) dayList.shift();
this.setData({ dayList, dayIndex: this.data.dayIndex - 1 });
},
prevDay() {
if (this.data.dayIndex > 0) {
this.setData({ dayIndex: this.data.dayIndex - 1 });
this.onDaySwiperChange({ detail: { current: this.data.dayIndex - 1 } });
}
},
nextDay() {
if (this.data.dayIndex < this.data.dayList.length - 1) {
this.setData({ dayIndex: this.data.dayIndex + 1 });
this.onDaySwiperChange({ detail: { current: this.data.dayIndex + 1 } });
}
},
backToday() {
this.buildDayList(new Date());
},
/** 切换 日/月 视图 */
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.buildDayList(new Date(y, m - 1, d));
this.setData({ viewMode: 'day' });
},
/** 跳转到某节日的老黄历 */
goFestival(e) {
const date = e.currentTarget.dataset.date;
const [y, m, d] = date.split('-').map(Number);
this.buildDayList(new Date(y, m - 1, d));
this.setData({ viewMode: 'day' });
},
/** ===== 全屏放大弹窗 ===== */
openZoom(e) {
const type = e.currentTarget.dataset.type;
const date = e.currentTarget.dataset.date;
const dayItem = this.data.dayList.find(item => item.key === date);
if (!dayItem) return;
const { dayInfo, almanac, legalHoliday, termTime } = dayItem;
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: dayItem.upcoming };
}
this.setData({ zoomVisible: true, zoomTitle, zoomType: type, zoomData });
},
closeZoom() {
this.setData({ zoomVisible: false });
},
navTo(e) {
wx.navigateTo({ url: e.currentTarget.dataset.url });
},
noop() {}
});