tabBar(5个,全部带图标): - 老黄历(首页) / 许愿 / 八字 / 百科(新) / 我的(原设置) - 移除日历tab,月历并入首页左上角切换 - 移除运势tab,改从'我的'页进入 首页重构: - custom 导航栏,标题'老黄历' - 老式万年历大日历卡片:大日期+农历+干支+宜忌 - 左右箭头切换日期,'回到今天' - 左上角'月历/日历'切换按钮,月历视图复用原日历网格 - 月历点选日期自动切回日视图 新增百科页: - 二十四节气/农历节日/公历节日/干支生肖/黄历术语 分类 - 搜索 + 展开详情 我的页(原设置): - 新增功能入口:每日运势/占卜/二十四节气/月历视图
@@ -9,12 +9,13 @@
|
||||
"pages/solar-terms/solar-terms",
|
||||
"pages/settings/settings",
|
||||
"pages/wish-tree/wish-tree",
|
||||
"pages/wish-detail/wish-detail"
|
||||
"pages/wish-detail/wish-detail",
|
||||
"pages/wiki/wiki"
|
||||
],
|
||||
"window": {
|
||||
"backgroundTextStyle": "light",
|
||||
"navigationBarBackgroundColor": "#C41E3A",
|
||||
"navigationBarTitleText": "万年历",
|
||||
"navigationBarTitleText": "老黄历",
|
||||
"navigationBarTextStyle": "white",
|
||||
"backgroundColor": "#FFFBF5"
|
||||
},
|
||||
@@ -26,15 +27,15 @@
|
||||
"list": [
|
||||
{
|
||||
"pagePath": "pages/home/home",
|
||||
"text": "首页",
|
||||
"text": "老黄历",
|
||||
"iconPath": "images/home.png",
|
||||
"selectedIconPath": "images/home-active.png"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/calendar/calendar",
|
||||
"text": "日历",
|
||||
"iconPath": "images/calendar.png",
|
||||
"selectedIconPath": "images/calendar-active.png"
|
||||
"pagePath": "pages/wish-tree/wish-tree",
|
||||
"text": "许愿",
|
||||
"iconPath": "images/wish.png",
|
||||
"selectedIconPath": "images/wish-active.png"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/bazi/bazi",
|
||||
@@ -43,16 +44,16 @@
|
||||
"selectedIconPath": "images/bazi-active.png"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/fortune/fortune",
|
||||
"text": "运势",
|
||||
"iconPath": "images/fortune.png",
|
||||
"selectedIconPath": "images/fortune-active.png"
|
||||
"pagePath": "pages/wiki/wiki",
|
||||
"text": "百科",
|
||||
"iconPath": "images/wiki.png",
|
||||
"selectedIconPath": "images/wiki-active.png"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/wish-tree/wish-tree",
|
||||
"text": "许愿",
|
||||
"iconPath": "images/wish.png",
|
||||
"selectedIconPath": "images/wish-active.png"
|
||||
"pagePath": "pages/settings/settings",
|
||||
"text": "我的",
|
||||
"iconPath": "images/me.png",
|
||||
"selectedIconPath": "images/me-active.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
|
Before Width: | Height: | Size: 67 B After Width: | Height: | Size: 602 B |
|
Before Width: | Height: | Size: 67 B After Width: | Height: | Size: 604 B |
|
Before Width: | Height: | Size: 67 B After Width: | Height: | Size: 446 B |
|
Before Width: | Height: | Size: 67 B After Width: | Height: | Size: 448 B |
|
After Width: | Height: | Size: 436 B |
|
After Width: | Height: | Size: 437 B |
|
After Width: | Height: | Size: 386 B |
|
After Width: | Height: | Size: 388 B |
|
Before Width: | Height: | Size: 67 B After Width: | Height: | Size: 499 B |
|
Before Width: | Height: | Size: 67 B After Width: | Height: | Size: 500 B |
@@ -1,28 +1,116 @@
|
||||
const { getTodayInfo, getAlmanacInfo } = require('../../utils/core/index.js');
|
||||
const { getDayInfo, getAlmanacInfo, getMonthCalendar } = require('../../utils/core/index.js');
|
||||
|
||||
function pad(n) { return String(n).padStart(2, '0'); }
|
||||
function fmt(y, m, d) { return `${y}-${pad(m)}-${pad(d)}`; }
|
||||
|
||||
Page({
|
||||
data: {
|
||||
statusBarHeight: 20,
|
||||
navBarHeight: 44,
|
||||
viewMode: 'day', // day | month
|
||||
dayInfo: {},
|
||||
almanac: {}
|
||||
almanac: {},
|
||||
// 月历
|
||||
year: 0,
|
||||
month: 0,
|
||||
weekHeaders: ['日', '一', '二', '三', '四', '五', '六'],
|
||||
calendarDays: [],
|
||||
selectedDay: null
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.loadData();
|
||||
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.loadDay(new Date());
|
||||
},
|
||||
|
||||
onPullDownRefresh() {
|
||||
this.loadData();
|
||||
if (this.data.viewMode === 'day') {
|
||||
this.loadDay(new Date());
|
||||
} else {
|
||||
this.loadCalendar();
|
||||
}
|
||||
wx.stopPullDownRefresh();
|
||||
},
|
||||
|
||||
loadData() {
|
||||
const dayInfo = getTodayInfo();
|
||||
const almanac = getAlmanacInfo(dayInfo.solarYear, dayInfo.solarMonth, dayInfo.solarDay);
|
||||
this.setData({ dayInfo, almanac });
|
||||
/** 加载某日的老黄历 */
|
||||
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, year: y, month: m });
|
||||
},
|
||||
|
||||
/** 前一天 / 后一天 */
|
||||
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());
|
||||
},
|
||||
|
||||
/** 切换 日视图/月历视图 */
|
||||
toggleView() {
|
||||
const mode = this.data.viewMode === 'day' ? 'month' : 'day';
|
||||
this.setData({ viewMode: mode });
|
||||
if (mode === 'month') {
|
||||
const { dayInfo } = this.data;
|
||||
this.setData({ year: dayInfo.solarYear, month: dayInfo.solarMonth }, () => this.loadCalendar());
|
||||
}
|
||||
},
|
||||
|
||||
/** 月历 */
|
||||
loadCalendar() {
|
||||
const { year, month } = this.data;
|
||||
const weeks = getMonthCalendar(year, month);
|
||||
const calendarDays = [];
|
||||
weeks.forEach(w => w.forEach(d => calendarDays.push(d)));
|
||||
this.setData({ calendarDays });
|
||||
},
|
||||
|
||||
prevMonth() {
|
||||
let { year, month } = this.data;
|
||||
month--;
|
||||
if (month < 1) { month = 12; year--; }
|
||||
this.setData({ year, month }, () => this.loadCalendar());
|
||||
},
|
||||
|
||||
nextMonth() {
|
||||
let { year, month } = this.data;
|
||||
month++;
|
||||
if (month > 12) { month = 1; year++; }
|
||||
this.setData({ year, month }, () => this.loadCalendar());
|
||||
},
|
||||
|
||||
/** 月历中选中某天 → 切回日视图 */
|
||||
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)}` });
|
||||
},
|
||||
|
||||
navTo(e) {
|
||||
const url = e.currentTarget.dataset.url;
|
||||
wx.navigateTo({ url });
|
||||
wx.navigateTo({ url: e.currentTarget.dataset.url });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"navigationBarTitleText": "万年历",
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": true,
|
||||
"backgroundTextStyle": "dark"
|
||||
}
|
||||
|
||||
@@ -1,54 +1,69 @@
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="custom-nav" style="padding-top: {{statusBarHeight}}px;">
|
||||
<view class="nav-inner" style="height: {{navBarHeight}}px;">
|
||||
<view class="nav-toggle" bindtap="toggleView">
|
||||
<text class="nav-toggle-text">{{viewMode === 'day' ? '月历' : '日历'}}</text>
|
||||
</view>
|
||||
<text class="nav-title font-chinese">老黄历</text>
|
||||
<view class="nav-right"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 日视图:老黄历 -->
|
||||
<scroll-view class="page-body" scroll-y wx:if="{{viewMode === 'day'}}" style="padding-top: {{statusBarHeight + navBarHeight}}px;">
|
||||
<view class="container">
|
||||
<!-- 顶部日期卡片 -->
|
||||
<view class="card date-card">
|
||||
<view class="flex justify-between items-center">
|
||||
<view>
|
||||
<text class="text-3xl font-bold">{{dayInfo.solarDay}}</text>
|
||||
<text class="text-lg text-muted ml-2">{{dayInfo.solarMonth}}月{{dayInfo.solarYear}}年</text>
|
||||
<!-- 大日历卡片 -->
|
||||
<view class="almanac-card">
|
||||
<!-- 顶部:公历 -->
|
||||
<view class="almanac-head">
|
||||
<view class="almanac-head-left">
|
||||
<text class="almanac-year">{{dayInfo.solarYear}}年{{dayInfo.solarMonth}}月</text>
|
||||
<text class="almanac-week">{{dayInfo.weekDay}} · {{dayInfo.constellation}}</text>
|
||||
</view>
|
||||
<view class="text-right">
|
||||
<text class="text-base">{{dayInfo.weekDay}}</text>
|
||||
<text class="text-sm text-muted block">{{dayInfo.constellation}}</text>
|
||||
<view class="almanac-head-right" wx:if="{{dayInfo.isToday}}">
|
||||
<text class="today-tag">今日</text>
|
||||
</view>
|
||||
<image class="settings-entry" src="/images/settings.png" mode="aspectFit" bindtap="navTo" data-url="/pages/settings/settings"></image>
|
||||
</view>
|
||||
<view class="mt-2 flex items-center gap-2">
|
||||
|
||||
<!-- 大日期 -->
|
||||
<view class="almanac-day-row">
|
||||
<view class="day-arrow" bindtap="prevDay">‹</view>
|
||||
<view class="almanac-day-num font-chinese">{{dayInfo.solarDay}}</view>
|
||||
<view class="day-arrow" bindtap="nextDay">›</view>
|
||||
</view>
|
||||
|
||||
<!-- 农历 -->
|
||||
<view class="almanac-lunar">
|
||||
<text class="almanac-lunar-main font-chinese">{{dayInfo.lunarMonthName}}{{dayInfo.lunarDayName}}</text>
|
||||
<text class="almanac-lunar-sub">{{dayInfo.lunarYearGanzhi}}年 {{dayInfo.lunarMonthGanzhi}}月 {{dayInfo.lunarDayGanzhi}}日 · 属{{dayInfo.zodiac}}</text>
|
||||
</view>
|
||||
|
||||
<!-- 节日/节气 -->
|
||||
<view class="almanac-fest" wx:if="{{dayInfo.lunarFestival || dayInfo.solarFestival || dayInfo.solarTerm}}">
|
||||
<text class="badge badge-festival" wx:if="{{dayInfo.lunarFestival}}">{{dayInfo.lunarFestival}}</text>
|
||||
<text class="badge badge-festival" wx:if="{{dayInfo.solarFestival}}">{{dayInfo.solarFestival}}</text>
|
||||
<text class="badge badge-outline" wx:if="{{dayInfo.solarTerm}}">{{dayInfo.solarTerm}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 农历信息 -->
|
||||
<view class="card">
|
||||
<view class="flex justify-between items-center">
|
||||
<view>
|
||||
<text class="text-2xl font-bold font-chinese">{{dayInfo.lunarMonthName}}{{dayInfo.lunarDayName}}</text>
|
||||
<text class="text-sm text-muted block mt-1">{{dayInfo.lunarYearGanzhi}}年 {{dayInfo.lunarMonthGanzhi}}月 {{dayInfo.lunarDayGanzhi}}日</text>
|
||||
</view>
|
||||
<view class="text-right">
|
||||
<text class="text-lg font-medium">{{dayInfo.zodiac}}年</text>
|
||||
<text class="text-sm text-muted block">{{dayInfo.moonPhase}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 宜忌 -->
|
||||
<view class="card">
|
||||
<view class="flex gap-2 mb-2">
|
||||
<view class="flex-1">
|
||||
<text class="text-lucky font-bold text-lg">宜</text>
|
||||
<view class="flex flex-wrap gap-1 mt-1">
|
||||
<text class="badge badge-lucky" wx:for="{{almanac.recommends}}" wx:key="*this">{{item}}</text>
|
||||
<view class="yiji-row">
|
||||
<view class="yiji-col">
|
||||
<view class="yiji-title yi">宜</view>
|
||||
<view class="yiji-items">
|
||||
<text class="yiji-item yi" wx:for="{{almanac.recommends}}" wx:key="*this">{{item}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-1">
|
||||
<text class="text-unlucky font-bold text-lg">忌</text>
|
||||
<view class="flex flex-wrap gap-1 mt-1">
|
||||
<text class="badge badge-unlucky" wx:for="{{almanac.avoids}}" wx:key="*this">{{item}}</text>
|
||||
<view class="yiji-divider"></view>
|
||||
<view class="yiji-col">
|
||||
<view class="yiji-title ji">忌</view>
|
||||
<view class="yiji-items">
|
||||
<text class="yiji-item ji" wx:for="{{almanac.avoids}}" wx:key="*this">{{item}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 回今天 -->
|
||||
<view class="back-today" wx:if="{{!dayInfo.isToday}}" bindtap="backToday">回到今天</view>
|
||||
</view>
|
||||
|
||||
<!-- 黄历详情 -->
|
||||
@@ -70,26 +85,50 @@
|
||||
<text class="text-xs text-muted">六曜</text>
|
||||
<text class="text-base font-medium block">{{almanac.sixStar}}</text>
|
||||
</view>
|
||||
<view class="p-2 bg-page rounded">
|
||||
<text class="text-xs text-muted">冲煞</text>
|
||||
<text class="text-base font-medium block">冲{{almanac.clash}} 煞{{almanac.evilDirection}}</text>
|
||||
</view>
|
||||
<view class="p-2 bg-page rounded">
|
||||
<text class="text-xs text-muted">彭祖百忌</text>
|
||||
<text class="text-base font-medium block">{{almanac.pengZu}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn-primary mt-2 detail-btn" bindtap="goDetail">查看详情</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 月历视图 -->
|
||||
<scroll-view class="page-body" scroll-y wx:if="{{viewMode === 'month'}}" style="padding-top: {{statusBarHeight + navBarHeight}}px;">
|
||||
<view class="container">
|
||||
<!-- 年月切换 -->
|
||||
<view class="card flex justify-between items-center">
|
||||
<view class="btn-ghost" bindtap="prevMonth">‹</view>
|
||||
<view class="text-xl font-bold">{{year}}年{{month}}月</view>
|
||||
<view class="btn-ghost" bindtap="nextMonth">›</view>
|
||||
</view>
|
||||
|
||||
<!-- 快捷入口 -->
|
||||
<view class="grid grid-cols-4 gap-2 mt-2">
|
||||
<view class="quick-entry" bindtap="navTo" data-url="/pages/calendar/calendar">
|
||||
<image src="/images/calendar.png" class="quick-icon" mode="aspectFit"/>
|
||||
<text class="text-sm">日历</text>
|
||||
<!-- 星期头 -->
|
||||
<view class="grid grid-cols-7 gap-1 mb-1">
|
||||
<view class="text-center text-sm text-muted" wx:for="{{weekHeaders}}" wx:key="*this">{{item}}</view>
|
||||
</view>
|
||||
<view class="quick-entry" bindtap="navTo" data-url="/pages/bazi/bazi">
|
||||
<image src="/images/bazi.png" class="quick-icon" mode="aspectFit"/>
|
||||
<text class="text-sm">八字</text>
|
||||
</view>
|
||||
<view class="quick-entry" bindtap="navTo" data-url="/pages/fortune/fortune">
|
||||
<image src="/images/fortune.png" class="quick-icon" mode="aspectFit"/>
|
||||
<text class="text-sm">运势</text>
|
||||
</view>
|
||||
<view class="quick-entry" bindtap="navTo" data-url="/pages/divination/divination">
|
||||
<image src="/images/divination.png" class="quick-icon" mode="aspectFit"/>
|
||||
<text class="text-sm">占卜</text>
|
||||
|
||||
<!-- 日历网格 -->
|
||||
<view class="grid grid-cols-7 gap-1">
|
||||
<view
|
||||
class="day-cell {{item.isToday ? 'today' : ''}} {{item.solarMonth !== month ? 'other-month' : ''}}"
|
||||
wx:for="{{calendarDays}}"
|
||||
wx:key="solarDate"
|
||||
bindtap="selectDay"
|
||||
data-date="{{item.solarDate}}"
|
||||
>
|
||||
<text class="day-number">{{item.solarDay}}</text>
|
||||
<text class="day-lunar {{item.lunarFestival || item.solarFestival ? 'festival' : ''}}">
|
||||
{{item.lunarFestival || item.solarFestival || item.lunarDayName}}
|
||||
</text>
|
||||
<view class="day-dot" wx:if="{{item.isTermDay}}"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
@@ -1,38 +1,267 @@
|
||||
/* 自定义导航栏 */
|
||||
.custom-nav {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #C41E3A;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.nav-inner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 24rpx;
|
||||
}
|
||||
|
||||
.nav-toggle {
|
||||
min-width: 96rpx;
|
||||
height: 56rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.5);
|
||||
border-radius: 999rpx;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.nav-toggle-text {
|
||||
color: #FFFFFF;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
color: #FFFFFF;
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
letter-spacing: 4rpx;
|
||||
}
|
||||
|
||||
.nav-right {
|
||||
min-width: 96rpx;
|
||||
}
|
||||
|
||||
/* 页面主体 */
|
||||
.page-body {
|
||||
box-sizing: border-box;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.date-card {
|
||||
background: linear-gradient(135deg, #C41E3A 0%, #8B1A2B 100%);
|
||||
/* ===== 老黄历大日历卡片 ===== */
|
||||
.almanac-card {
|
||||
background: linear-gradient(160deg, #FFFFFF 0%, #FFF8EF 100%);
|
||||
border: 1rpx solid #E8D5C4;
|
||||
border-radius: 24rpx;
|
||||
padding: 32rpx 24rpx;
|
||||
margin-bottom: 16rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.almanac-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.almanac-year {
|
||||
font-size: 30rpx;
|
||||
color: #6B5E53;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.almanac-week {
|
||||
font-size: 24rpx;
|
||||
color: #9E8E7E;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.today-tag {
|
||||
background: #C41E3A;
|
||||
color: #FFFFFF;
|
||||
border: none;
|
||||
font-size: 20rpx;
|
||||
padding: 4rpx 20rpx;
|
||||
border-radius: 999rpx;
|
||||
}
|
||||
|
||||
.date-card .text-muted {
|
||||
color: rgba(255,255,255,0.7);
|
||||
/* 大日期 */
|
||||
.almanac-day-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 16rpx 0 8rpx;
|
||||
}
|
||||
|
||||
.quick-entry {
|
||||
.almanac-day-num {
|
||||
font-size: 160rpx;
|
||||
font-weight: 700;
|
||||
color: #C41E3A;
|
||||
line-height: 1.1;
|
||||
min-width: 320rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.day-arrow {
|
||||
font-size: 64rpx;
|
||||
color: #C9B8A6;
|
||||
padding: 0 32rpx;
|
||||
}
|
||||
|
||||
/* 农历 */
|
||||
.almanac-lunar {
|
||||
text-align: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.almanac-lunar-main {
|
||||
font-size: 44rpx;
|
||||
font-weight: 600;
|
||||
color: #1A1A1A;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.almanac-lunar-sub {
|
||||
font-size: 24rpx;
|
||||
color: #9E8E7E;
|
||||
display: block;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
/* 节日 */
|
||||
.almanac-fest {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
/* 宜忌 */
|
||||
.yiji-row {
|
||||
display: flex;
|
||||
border-top: 1rpx solid #F0E6DA;
|
||||
padding-top: 24rpx;
|
||||
}
|
||||
|
||||
.yiji-col {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.yiji-divider {
|
||||
width: 1rpx;
|
||||
background: #F0E6DA;
|
||||
margin: 0 16rpx;
|
||||
}
|
||||
|
||||
.yiji-title {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 30rpx;
|
||||
font-weight: 700;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.yiji-title.yi {
|
||||
background: #C41E3A;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.yiji-title.ji {
|
||||
background: #546E7A;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.yiji-items {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8rpx;
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
.yiji-item {
|
||||
font-size: 24rpx;
|
||||
padding: 4rpx 14rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.yiji-item.yi {
|
||||
background: #FEF2F2;
|
||||
color: #C41E3A;
|
||||
}
|
||||
|
||||
.yiji-item.ji {
|
||||
background: #F1F5F9;
|
||||
color: #546E7A;
|
||||
}
|
||||
|
||||
/* 回到今天 */
|
||||
.back-today {
|
||||
text-align: center;
|
||||
margin-top: 20rpx;
|
||||
color: #C41E3A;
|
||||
font-size: 26rpx;
|
||||
padding: 12rpx;
|
||||
}
|
||||
|
||||
.detail-btn {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ===== 月历 ===== */
|
||||
.day-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 24rpx;
|
||||
padding: 12rpx 4rpx;
|
||||
background: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
border: 1rpx solid #E8D5C4;
|
||||
border-radius: 12rpx;
|
||||
min-height: 100rpx;
|
||||
}
|
||||
|
||||
.quick-icon {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
margin-bottom: 8rpx;
|
||||
.day-cell.today {
|
||||
background: #C41E3A;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.settings-entry {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
margin-left: 16rpx;
|
||||
opacity: 0.6;
|
||||
.day-cell.today .day-lunar {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.day-cell.other-month {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.day-number {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.day-lunar {
|
||||
font-size: 20rpx;
|
||||
color: #9E8E7E;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
|
||||
.day-lunar.festival {
|
||||
color: #C41E3A;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.day-dot {
|
||||
width: 8rpx;
|
||||
height: 8rpx;
|
||||
border-radius: 50%;
|
||||
background: #C41E3A;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
|
||||
@@ -58,6 +58,10 @@ Page({
|
||||
wx.showToast({ title: '已删除', icon: 'success' });
|
||||
},
|
||||
|
||||
navTo(e) {
|
||||
wx.navigateTo({ url: e.currentTarget.dataset.url });
|
||||
},
|
||||
|
||||
login() {
|
||||
wx.getUserProfile({
|
||||
desc: '用于完善用户资料',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"navigationBarTitleText": "设置",
|
||||
"navigationBarTitleText": "我的",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
|
||||
@@ -57,12 +57,33 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 功能入口 -->
|
||||
<view class="card">
|
||||
<view class="section-title">功能</view>
|
||||
<view class="menu-item" bindtap="navTo" data-url="/pages/fortune/fortune">
|
||||
<text class="menu-label">每日运势</text>
|
||||
<text class="menu-arrow">›</text>
|
||||
</view>
|
||||
<view class="menu-item" bindtap="navTo" data-url="/pages/divination/divination">
|
||||
<text class="menu-label">占卜</text>
|
||||
<text class="menu-arrow">›</text>
|
||||
</view>
|
||||
<view class="menu-item" bindtap="navTo" data-url="/pages/solar-terms/solar-terms">
|
||||
<text class="menu-label">二十四节气</text>
|
||||
<text class="menu-arrow">›</text>
|
||||
</view>
|
||||
<view class="menu-item" bindtap="navTo" data-url="/pages/calendar/calendar">
|
||||
<text class="menu-label">月历视图</text>
|
||||
<text class="menu-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 关于 -->
|
||||
<view class="card">
|
||||
<view class="section-title">关于</view>
|
||||
<view class="text-sm text-muted">
|
||||
<text>万年历小程序 v1.0.0</text>
|
||||
<text class="block mt-1">提供农历、黄历、八字、运势、占卜等功能</text>
|
||||
<text>老黄历小程序 v1.0.1</text>
|
||||
<text class="block mt-1">提供农历、黄历、八字、许愿等功能</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -45,3 +45,24 @@
|
||||
.bookmark-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24rpx 0;
|
||||
border-bottom: 1rpx solid #E8D5C4;
|
||||
}
|
||||
|
||||
.menu-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.menu-label {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.menu-arrow {
|
||||
color: #C9B8A6;
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
const { SOLAR_TERMS, LUNAR_FESTIVALS, SOLAR_FESTIVALS, HEAVEN_STEMS, EARTH_BRANCHES, ZODIACS } = require('../../utils/core/data.js');
|
||||
|
||||
const CATEGORIES = [
|
||||
{ key: 'all', name: '全部' },
|
||||
{ key: 'term', name: '二十四节气' },
|
||||
{ key: 'lunarFest', name: '农历节日' },
|
||||
{ key: 'solarFest', name: '公历节日' },
|
||||
{ key: 'ganzhi', name: '干支生肖' },
|
||||
{ key: 'termExplain', name: '黄历术语' }
|
||||
];
|
||||
|
||||
const TERM_BRIEFS = {
|
||||
'立春': '春季开始,万物复苏', '雨水': '降雨增多,气温回升', '惊蛰': '春雷惊醒蛰伏动物',
|
||||
'春分': '昼夜平分,春季过半', '清明': '天气晴朗,草木繁茂', '谷雨': '雨生百谷,播种时节',
|
||||
'立夏': '夏季开始,万物生长', '小满': '麦类籽粒开始饱满', '芒种': '有芒作物成熟,忙于播种',
|
||||
'夏至': '白昼最长,盛夏来临', '小暑': '天气开始炎热', '大暑': '一年中最热的时期',
|
||||
'立秋': '秋季开始,暑去凉来', '处暑': '暑气结束,秋意渐浓', '白露': '天气转凉,出现露水',
|
||||
'秋分': '昼夜平分,秋季过半', '寒露': '露水更凉,秋意更浓', '霜降': '开始降霜,天气渐冷',
|
||||
'立冬': '冬季开始,万物收藏', '小雪': '开始降雪,气温下降', '大雪': '降雪增多,天气更冷',
|
||||
'冬至': '白昼最短,数九开始', '小寒': '天气寒冷,但未到极点', '大寒': '一年中最冷的时期'
|
||||
};
|
||||
|
||||
const TERM_EXPLAINS = [
|
||||
{ title: '干支纪年', brief: '天干地支组合纪年法', content: '天干有十:甲乙丙丁戊己庚辛壬癸;地支有十二:子丑寅卯辰巳午未申酉戌亥。两者按顺序两两组合,形成六十甲子循环,用于纪年、纪月、纪日、纪时。' },
|
||||
{ title: '建除十二神', brief: '建、除、满、平、定、执、破、危、成、收、开、闭', content: '建除十二神又称十二值日,是古代择日的重要依据。以月建起建,按地支顺序排列。建日宜出行,除日宜疗病,满日宜嫁娶,平日宜修造,定日宜祈福,执日宜祭祀,破日宜破屋,危日宜安床,成日宜开市,收日宜纳财,开日宜开光,闭日宜安葬。' },
|
||||
{ title: '黄道吉日', brief: '青龙、明堂、金匮、天德、玉堂、司命为黄道', content: '黄道黑道是古代择日术语。黄道日(青龙、明堂、金匮、天德、玉堂、司命值日)诸事皆宜;黑道日(天刑、朱雀、白虎、天牢、玄武、勾陈值日)宜避凶就吉。' },
|
||||
{ title: '二十八宿', brief: '古代天文学家将黄道附近的星宿分为二十八组', content: '二十八宿分东方青龙(角亢氐房心尾箕)、北方玄武(斗牛女虚危室壁)、西方白虎(奎娄胃昴毕觜参)、南方朱雀(井鬼柳星张翼轸)四象,每象七宿。古人用二十八宿来判断日子的吉凶。' },
|
||||
{ title: '六曜', brief: '先胜、友引、先负、佛灭、大安、赤口', content: '六曜起源于中国,后传入日本并广泛流行。大安日诸事皆吉;先胜日上午吉;友引日早晚吉;先负日上午凶;佛灭日大凶;赤口日午凶。以农历月日之和除以六取余数确定。' },
|
||||
{ title: '彭祖百忌', brief: '每日天干地支对应的禁忌事项', content: '彭祖百忌是古代择日学的重要内容,根据每日的天干地支组合给出相应的禁忌。如"甲不开仓财物耗散,子不问卜自惹祸殃"等,共六十条对应六十甲子。' },
|
||||
{ title: '冲煞', brief: '日支与某生肖相冲,该生肖之人需谨慎', content: '冲煞指日支与某地支相冲(如子午相冲、丑未相冲等),对应的生肖之人在当日需谨慎行事。煞方指当日凶煞所在的方位,不宜在该方位动土或远行。' },
|
||||
{ title: '纳音五行', brief: '六十甲子与五行的配合', content: '纳音是将六十甲子与五行相配,每两组干支合为一种纳音,共三十种。如甲子乙丑海中金、丙寅丁卯炉中火等,用于命理分析。' },
|
||||
{ title: '月相', brief: '朔、上弦、望、下弦的月相变化', content: '农历初一为朔(新月),初七初八为上弦月,十五为望(满月),廿二廿三为下弦月。月相变化影响潮汐,也被古人用于判断吉凶。' },
|
||||
{ title: '胎神方位', brief: '孕妇需避开的方位', content: '胎神是传统民俗中保护胎儿的神灵,每日所在方位不同。孕妇不宜在胎神方位动土、钉钉或搬动重物,以免惊动胎神。' }
|
||||
];
|
||||
|
||||
function buildEntries() {
|
||||
const entries = [];
|
||||
|
||||
// 二十四节气
|
||||
SOLAR_TERMS.forEach(name => {
|
||||
entries.push({
|
||||
cat: 'term', catName: '节气', title: name,
|
||||
brief: TERM_BRIEFS[name] || '二十四节气之一',
|
||||
content: TERM_BRIEFS[name] || '二十四节气之一,是古人根据太阳在黄道上的位置划分的时令节点。',
|
||||
open: false
|
||||
});
|
||||
});
|
||||
|
||||
// 农历节日
|
||||
const seenLunar = new Set();
|
||||
Object.entries(LUNAR_FESTIVALS).forEach(([key, name]) => {
|
||||
if (seenLunar.has(name)) return;
|
||||
seenLunar.add(name);
|
||||
const [m, d] = key.split('-');
|
||||
entries.push({
|
||||
cat: 'lunarFest', catName: '农历节日', title: name,
|
||||
brief: `农历${m}月${d}日`,
|
||||
content: `${name},农历${m}月${d}日,是中国传统农历节日。`,
|
||||
open: false
|
||||
});
|
||||
});
|
||||
|
||||
// 公历节日
|
||||
const seenSolar = new Set();
|
||||
Object.entries(SOLAR_FESTIVALS).forEach(([key, name]) => {
|
||||
if (seenSolar.has(name)) return;
|
||||
seenSolar.add(name);
|
||||
const [m, d] = key.split('-');
|
||||
entries.push({
|
||||
cat: 'solarFest', catName: '公历节日', title: name,
|
||||
brief: `公历${m}月${d}日`,
|
||||
content: `${name},公历${m}月${d}日。`,
|
||||
open: false
|
||||
});
|
||||
});
|
||||
|
||||
// 干支生肖
|
||||
HEAVEN_STEMS.forEach((s, i) => {
|
||||
entries.push({
|
||||
cat: 'ganzhi', catName: '天干', title: s,
|
||||
brief: `十天干之第${i + 1}位`,
|
||||
content: `${s}为十天干之第${i + 1}位,五行属${['木','木','火','火','土','土','金','金','水','水'][i]},属${i % 2 === 0 ? '阳' : '阴'}。`,
|
||||
open: false
|
||||
});
|
||||
});
|
||||
EARTH_BRANCHES.forEach((b, i) => {
|
||||
entries.push({
|
||||
cat: 'ganzhi', catName: '地支', title: `${b}(${ZODIACS[i]})`,
|
||||
brief: `十二地支之第${i + 1}位,生肖属${ZODIACS[i]}`,
|
||||
content: `${b}为十二地支之第${i + 1}位,生肖属${ZODIACS[i]},五行属${['水','土','木','木','土','火','火','土','金','金','土','水'][i]}。`,
|
||||
open: false
|
||||
});
|
||||
});
|
||||
|
||||
// 黄历术语
|
||||
TERM_EXPLAINS.forEach(t => {
|
||||
entries.push({ cat: 'termExplain', catName: '术语', ...t, open: false });
|
||||
});
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
categories: CATEGORIES,
|
||||
activeCat: 'all',
|
||||
keyword: '',
|
||||
entries: [],
|
||||
filteredEntries: []
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
const entries = buildEntries();
|
||||
this.setData({ entries, filteredEntries: entries });
|
||||
},
|
||||
|
||||
switchCat(e) {
|
||||
this.setData({ activeCat: e.currentTarget.dataset.key }, () => this.filter());
|
||||
},
|
||||
|
||||
onSearch(e) {
|
||||
this.setData({ keyword: e.detail.value.trim() }, () => this.filter());
|
||||
},
|
||||
|
||||
filter() {
|
||||
const { entries, activeCat, keyword } = this.data;
|
||||
let list = entries;
|
||||
if (activeCat !== 'all') list = list.filter(t => t.cat === activeCat);
|
||||
if (keyword) list = list.filter(t => t.title.includes(keyword) || t.brief.includes(keyword) || t.content.includes(keyword));
|
||||
this.setData({ filteredEntries: list });
|
||||
},
|
||||
|
||||
toggleEntry(e) {
|
||||
const index = e.currentTarget.dataset.index;
|
||||
const key = `filteredEntries[${index}].open`;
|
||||
this.setData({ [key]: !this.data.filteredEntries[index].open });
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"navigationBarTitleText": "百科",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<view class="container">
|
||||
<!-- 搜索 -->
|
||||
<view class="search-bar">
|
||||
<input class="search-input" placeholder="搜索节气、节日、术语..." value="{{keyword}}" bindinput="onSearch" confirm-type="search"/>
|
||||
</view>
|
||||
|
||||
<!-- 分类 -->
|
||||
<scroll-view class="cat-scroll" scroll-x enhanced show-scrollbar="{{false}}">
|
||||
<view class="cat-list">
|
||||
<view
|
||||
class="cat-item {{activeCat === item.key ? 'active' : ''}}"
|
||||
wx:for="{{categories}}"
|
||||
wx:key="key"
|
||||
bindtap="switchCat"
|
||||
data-key="{{item.key}}"
|
||||
>{{item.name}}</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 条目列表 -->
|
||||
<view class="entry-list">
|
||||
<view class="card entry-card" wx:for="{{filteredEntries}}" wx:key="title" bindtap="toggleEntry" data-index="{{index}}">
|
||||
<view class="flex justify-between items-center">
|
||||
<text class="text-lg font-bold font-chinese">{{item.title}}</text>
|
||||
<text class="badge badge-outline">{{item.catName}}</text>
|
||||
</view>
|
||||
<view class="text-sm text-muted mt-1" wx:if="{{!item.open}}">{{item.brief}}</view>
|
||||
<view class="entry-detail mt-2" wx:if="{{item.open}}">
|
||||
<text class="text-base">{{item.content}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="text-center text-muted empty-tip" wx:if="{{filteredEntries.length === 0}}">
|
||||
<text>没有找到相关条目</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -0,0 +1,56 @@
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
background: #FFFFFF;
|
||||
border: 1rpx solid #E8D5C4;
|
||||
border-radius: 999rpx;
|
||||
padding: 16rpx 32rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.cat-scroll {
|
||||
white-space: nowrap;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.cat-list {
|
||||
display: inline-flex;
|
||||
gap: 16rpx;
|
||||
padding: 4rpx 0;
|
||||
}
|
||||
|
||||
.cat-item {
|
||||
display: inline-flex;
|
||||
padding: 12rpx 28rpx;
|
||||
border-radius: 999rpx;
|
||||
font-size: 26rpx;
|
||||
background: #FFFFFF;
|
||||
border: 1rpx solid #E8D5C4;
|
||||
color: #6B5E53;
|
||||
}
|
||||
|
||||
.cat-item.active {
|
||||
background: #C41E3A;
|
||||
border-color: #C41E3A;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.entry-card {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.entry-detail {
|
||||
border-top: 1rpx solid #F0E6DA;
|
||||
padding-top: 16rpx;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
padding: 80rpx 0;
|
||||
}
|
||||