feat: 祈福小助手万年历小程序第一期

This commit is contained in:
gouki
2026-08-06 08:47:09 +00:00
commit a3e6aa9c01
136 changed files with 16597 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
const { birthInfoToBazi, analyzeElementBalance } = require('../../utils/core/index.js');
Page({
data: {
gender: 'male',
birthDate: '1990-01-01',
birthTime: '12:00',
ziSect: 'lateZiNextDay',
bazi: null,
pillars: [],
elements: [],
elementAnalysis: {}
},
onLoad() {
// 尝试从本地存储恢复
const saved = wx.getStorageSync('lunar-bazi-input');
if (saved) {
this.setData(saved);
}
},
setGender(e) {
this.setData({ gender: e.currentTarget.dataset.g });
},
setZiSect(e) {
this.setData({ ziSect: e.currentTarget.dataset.s });
},
onDateChange(e) {
this.setData({ birthDate: e.detail.value });
},
onTimeChange(e) {
this.setData({ birthTime: e.detail.value });
},
calculate() {
const { gender, birthDate, birthTime, ziSect } = this.data;
const [year, month, day] = birthDate.split('-').map(Number);
const [hour, minute] = birthTime.split(':').map(Number);
const bazi = birthInfoToBazi({ year, month, day, hour, minute, gender, ziSect });
const elementAnalysis = analyzeElementBalance(bazi.eightChar);
const pillars = [
{ label: '年柱', ...bazi.eightChar.yearPillar },
{ label: '月柱', ...bazi.eightChar.monthPillar },
{ label: '日柱', ...bazi.eightChar.dayPillar },
{ label: '时柱', ...bazi.eightChar.hourPillar }
];
const total = elementAnalysis.total || 1;
const elements = [
{ name: '木', count: elementAnalysis.wood, percent: Math.round(elementAnalysis.wood / total * 100) },
{ name: '火', count: elementAnalysis.fire, percent: Math.round(elementAnalysis.fire / total * 100) },
{ name: '土', count: elementAnalysis.earth, percent: Math.round(elementAnalysis.earth / total * 100) },
{ name: '金', count: elementAnalysis.metal, percent: Math.round(elementAnalysis.metal / total * 100) },
{ name: '水', count: elementAnalysis.water, percent: Math.round(elementAnalysis.water / total * 100) }
];
this.setData({ bazi, pillars, elements, elementAnalysis });
// 保存输入
wx.setStorageSync('lunar-bazi-input', { gender, birthDate, birthTime, ziSect });
// 保存八字供运势页使用
wx.setStorageSync('lunar-user-bazi', bazi);
},
reset() {
this.setData({ bazi: null });
},
goFortune() {
wx.switchTab({ url: '/pages/fortune/fortune' });
}
});
+4
View File
@@ -0,0 +1,4 @@
{
"navigationBarTitleText": "八字排盘",
"enablePullDownRefresh": false
}
+104
View File
@@ -0,0 +1,104 @@
<view class="container">
<!-- 输入表单 -->
<view class="card" wx:if="{{!bazi}}">
<view class="section-title">输入出生信息</view>
<view class="form-item">
<text class="form-label">性别</text>
<view class="flex gap-2">
<view class="btn-outline {{gender === 'male' ? 'active' : ''}}" bindtap="setGender" data-g="male">男</view>
<view class="btn-outline {{gender === 'female' ? 'active' : ''}}" bindtap="setGender" data-g="female">女</view>
</view>
</view>
<view class="form-item">
<text class="form-label">出生日期</text>
<picker mode="date" value="{{birthDate}}" bindchange="onDateChange">
<view class="picker-input">{{birthDate}}</view>
</picker>
</view>
<view class="form-item">
<text class="form-label">出生时间</text>
<picker mode="time" value="{{birthTime}}" bindchange="onTimeChange">
<view class="picker-input">{{birthTime}}</view>
</picker>
</view>
<view class="form-item">
<text class="form-label">子时流派</text>
<view class="flex gap-2">
<view class="btn-outline {{ziSect === 'lateZiNextDay' ? 'active' : ''}}" bindtap="setZiSect" data-s="lateZiNextDay">晚子时日柱算次日</view>
<view class="btn-outline {{ziSect === 'lateZiSameDay' ? 'active' : ''}}" bindtap="setZiSect" data-s="lateZiSameDay">晚子时日柱算当日</view>
</view>
</view>
<view class="btn-primary mt-2" bindtap="calculate">排盘</view>
</view>
<!-- 八字结果 -->
<block wx:if="{{bazi}}">
<!-- 四柱 -->
<view class="card">
<view class="section-title">四柱八字</view>
<view class="grid grid-cols-4 gap-2">
<view class="pillar" wx:for="{{pillars}}" wx:key="label">
<text class="pillar-label">{{item.label}}</text>
<text class="pillar-ganzhi">{{item.ganzhi}}</text>
<text class="pillar-ten">{{item.tenStar || '日主'}}</text>
</view>
</view>
</view>
<!-- 五行分析 -->
<view class="card">
<view class="section-title">五行分析</view>
<view class="element-bar">
<view class="element-item" wx:for="{{elements}}" wx:key="name">
<text class="element-name">{{item.name}}</text>
<view class="element-track">
<view class="element-fill" style="width: {{item.percent}}%"></view>
</view>
<text class="element-count">{{item.count}}</text>
</view>
</view>
<view class="mt-2 text-sm text-muted">
日主:{{bazi.eightChar.dayMaster}} | dominant: {{elementAnalysis.dominant}} | weakest: {{elementAnalysis.weakest}}
</view>
</view>
<!-- 大运 -->
<view class="card">
<view class="section-title">大运</view>
<scroll-view scroll-x class="scroll-x">
<view class="flex gap-2">
<view class="fortune-item" wx:for="{{bazi.decadeFortunes}}" wx:key="index">
<text class="text-sm text-muted">{{item.startAge}}-{{item.endAge}}岁</text>
<text class="text-base font-medium">{{item.ganzhi}}</text>
<text class="text-xs text-muted">{{item.startYear}}-{{item.endYear}}</text>
</view>
</view>
</scroll-view>
</view>
<!-- 流年 -->
<view class="card">
<view class="section-title">流年</view>
<scroll-view scroll-x class="scroll-x">
<view class="flex gap-2">
<view class="fortune-item" wx:for="{{bazi.annualFortunes}}" wx:key="year">
<text class="text-sm text-muted">{{item.age}}岁</text>
<text class="text-base font-medium">{{item.ganzhi}}</text>
<text class="text-xs text-muted">{{item.year}}</text>
</view>
</view>
</scroll-view>
</view>
<!-- 操作 -->
<view class="flex gap-2 mt-2">
<view class="btn-outline flex-1 text-center" bindtap="reset">重新排盘</view>
<view class="btn-primary flex-1 text-center" bindtap="goFortune">看运势</view>
</view>
</block>
</view>
+107
View File
@@ -0,0 +1,107 @@
.container {
padding: 20rpx;
}
.section-title {
font-size: 28rpx;
font-weight: 600;
margin-bottom: 16rpx;
color: #C41E3A;
}
.form-item {
margin-bottom: 24rpx;
}
.form-label {
font-size: 24rpx;
color: #6B5E53;
margin-bottom: 8rpx;
display: block;
}
.picker-input {
padding: 20rpx;
background: #FFFBF5;
border-radius: 12rpx;
border: 1rpx solid #E8D5C4;
}
.btn-outline.active {
background: #C41E3A;
color: #FFFFFF;
border-color: #C41E3A;
}
.pillar {
display: flex;
flex-direction: column;
align-items: center;
padding: 20rpx;
background: #FFFBF5;
border-radius: 12rpx;
}
.pillar-label {
font-size: 20rpx;
color: #9E8E7E;
}
.pillar-ganzhi {
font-size: 36rpx;
font-weight: 700;
color: #C41E3A;
margin: 8rpx 0;
}
.pillar-ten {
font-size: 20rpx;
color: #6B5E53;
}
.element-bar {
display: flex;
flex-direction: column;
gap: 12rpx;
}
.element-item {
display: flex;
align-items: center;
gap: 12rpx;
}
.element-name {
width: 60rpx;
font-size: 24rpx;
}
.element-track {
flex: 1;
height: 16rpx;
background: #E8D5C4;
border-radius: 8rpx;
overflow: hidden;
}
.element-fill {
height: 100%;
background: #C41E3A;
border-radius: 8rpx;
}
.element-count {
width: 60rpx;
text-align: right;
font-size: 24rpx;
}
.fortune-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 16rpx 24rpx;
background: #FFFBF5;
border-radius: 12rpx;
min-width: 160rpx;
}
+86
View File
@@ -0,0 +1,86 @@
const { getMonthCalendar } = require('../../utils/core/index.js');
Page({
data: {
year: new Date().getFullYear(),
month: new Date().getMonth() + 1,
weekHeaders: ['日', '一', '二', '三', '四', '五', '六'],
calendarDays: [],
selectedDay: null,
showMonthPicker: false,
years: [],
months: [1,2,3,4,5,6,7,8,9,10,11,12],
pickerValue: [0, 0]
},
onLoad() {
const years = [];
for (let y = 1900; y <= 2100; y++) years.push(y);
this.setData({ years });
this.loadCalendar();
},
loadCalendar() {
const { year, month } = this.data;
const weeks = getMonthCalendar(year, month);
const calendarDays = [];
weeks.forEach(week => {
week.forEach(day => calendarDays.push(day));
});
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());
},
showPicker() {
const { year, month } = this.data;
this.setData({
showMonthPicker: true,
pickerValue: [year - 1900, month - 1]
});
},
hidePicker() {
this.setData({ showMonthPicker: false });
},
pickerChange(e) {
this.setData({ pickerValue: e.detail.value });
},
confirmPicker() {
const { pickerValue, years, months } = this.data;
this.setData({
year: years[pickerValue[0]],
month: months[pickerValue[1]],
showMonthPicker: false
}, () => this.loadCalendar());
},
selectDay(e) {
const date = e.currentTarget.dataset.date;
const day = this.data.calendarDays.find(d => d.solarDate === date);
this.setData({ selectedDay: day });
},
goDetail() {
const { selectedDay } = this.data;
if (selectedDay) {
wx.navigateTo({ url: `/pages/day-detail/day-detail?date=${selectedDay.solarDate}` });
}
},
noop() {}
});
+4
View File
@@ -0,0 +1,4 @@
{
"navigationBarTitleText": "日历",
"enablePullDownRefresh": false
}
+60
View File
@@ -0,0 +1,60 @@
<view class="container">
<!-- 年月选择器 -->
<view class="card flex justify-between items-center">
<view class="btn-ghost" bindtap="prevMonth"></view>
<view class="text-xl font-bold" bindtap="showPicker">{{year}}年{{month}}月</view>
<view class="btn-ghost" bindtap="nextMonth"></view>
</view>
<!-- 星期头 -->
<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="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 class="card mt-2" wx:if="{{selectedDay}}">
<view class="flex justify-between items-center">
<view>
<text class="text-lg font-bold">{{selectedDay.solarDate}}</text>
<text class="text-sm text-muted block">{{selectedDay.lunarMonthName}}{{selectedDay.lunarDayName}}</text>
</view>
<view class="btn-primary" bindtap="goDetail">详情</view>
</view>
</view>
</view>
<!-- 年月选择弹窗 -->
<view class="picker-mask {{showMonthPicker ? 'show' : ''}}" bindtap="hidePicker">
<view class="picker-panel" catchtap="noop">
<view class="picker-header">
<text bindtap="hidePicker">取消</text>
<text class="font-bold">选择年月</text>
<text bindtap="confirmPicker">确定</text>
</view>
<picker-view class="picker-view" value="{{pickerValue}}" bindchange="pickerChange">
<picker-view-column>
<view wx:for="{{years}}" wx:key="*this" class="picker-item">{{item}}年</view>
</picker-view-column>
<picker-view-column>
<view wx:for="{{months}}" wx:key="*this" class="picker-item">{{item}}月</view>
</picker-view-column>
</picker-view>
</view>
</view>
+92
View File
@@ -0,0 +1,92 @@
.container {
padding: 20rpx;
}
.day-cell {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 12rpx 4rpx;
background: #FFFFFF;
border-radius: 12rpx;
min-height: 100rpx;
}
.day-cell.today {
background: #C41E3A;
color: #FFFFFF;
}
.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;
}
.picker-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
z-index: 100;
display: none;
}
.picker-mask.show {
display: block;
}
.picker-panel {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: #FFFFFF;
border-radius: 24rpx 24rpx 0 0;
}
.picker-header {
display: flex;
justify-content: space-between;
padding: 24rpx;
border-bottom: 1rpx solid #E8D5C4;
}
.picker-view {
height: 400rpx;
}
.picker-item {
text-align: center;
line-height: 68rpx;
font-size: 32rpx;
}
+43
View File
@@ -0,0 +1,43 @@
const { getDayInfo, getAlmanacInfo } = require('../../utils/core/index.js');
Page({
data: {
date: '',
dayInfo: {},
almanac: {}
},
onLoad(options) {
const date = options.date || new Date().toISOString().split('T')[0];
this.setData({ date });
this.loadData(date);
},
loadData(dateStr) {
const [year, month, day] = dateStr.split('-').map(Number);
const dayInfo = getDayInfo(year, month, day);
const almanac = getAlmanacInfo(year, month, day);
this.setData({ dayInfo, almanac });
},
addBookmark() {
const bookmarks = wx.getStorageSync('lunar-bookmarks') || [];
const { dayInfo } = this.data;
const exists = bookmarks.some(b => b.date === dayInfo.solarDate);
if (!exists) {
bookmarks.push({
date: dayInfo.solarDate,
lunarDate: `${dayInfo.lunarMonthName}${dayInfo.lunarDayName}`,
note: ''
});
wx.setStorageSync('lunar-bookmarks', bookmarks);
wx.showToast({ title: '已收藏', icon: 'success' });
} else {
wx.showToast({ title: '已收藏过', icon: 'none' });
}
},
goBazi() {
wx.navigateTo({ url: '/pages/bazi/bazi' });
}
});
+4
View File
@@ -0,0 +1,4 @@
{
"navigationBarTitleText": "日详情",
"enablePullDownRefresh": false
}
+147
View File
@@ -0,0 +1,147 @@
<view class="container">
<!-- 日期头部 -->
<view class="card header-card">
<view class="text-center">
<text class="text-3xl font-bold">{{dayInfo.solarDay}}</text>
<text class="text-lg text-muted block">{{dayInfo.solarYear}}年{{dayInfo.solarMonth}}月 {{dayInfo.weekDay}}</text>
</view>
<view class="flex justify-center gap-2 mt-2">
<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="section-title">农历</view>
<view class="grid grid-cols-2 gap-2">
<view class="info-item">
<text class="text-xs text-muted">农历日期</text>
<text class="text-base font-medium">{{dayInfo.lunarYear}}年{{dayInfo.lunarMonthName}}{{dayInfo.lunarDayName}}</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">生肖</text>
<text class="text-base font-medium">{{dayInfo.zodiac}}</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">干支</text>
<text class="text-base font-medium">{{dayInfo.lunarYearGanzhi}}年 {{dayInfo.lunarMonthGanzhi}}月 {{dayInfo.lunarDayGanzhi}}日</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">月相</text>
<text class="text-base font-medium">{{dayInfo.moonPhase}}</text>
</view>
</view>
</view>
<!-- 宜忌 -->
<view class="card">
<view class="section-title">宜忌</view>
<view class="flex gap-2">
<view class="flex-1">
<text class="text-lucky font-bold">宜</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>
</view>
<view class="flex-1">
<text class="text-unlucky font-bold">忌</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>
</view>
</view>
</view>
<!-- 黄历详情 -->
<view class="card">
<view class="section-title">黄历</view>
<view class="grid grid-cols-2 gap-2">
<view class="info-item">
<text class="text-xs text-muted">值神</text>
<text class="text-base font-medium">{{almanac.duty}}{{almanac.dutyLuck === 'good' ? '吉' : almanac.dutyLuck === 'bad' ? '凶' : '平'}}</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">黄道黑道</text>
<text class="text-base font-medium">{{almanac.twelveStar.name}}{{almanac.twelveStar.ecliptic}}</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">二十八宿</text>
<text class="text-base font-medium">{{almanac.twentyEightStar.name}}</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">九星</text>
<text class="text-base font-medium">{{almanac.nineStar.name}}</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">六曜</text>
<text class="text-base font-medium">{{almanac.sixStar}}</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">小六壬</text>
<text class="text-base font-medium">{{almanac.minorRen.name}}</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">纳音</text>
<text class="text-base font-medium">{{almanac.nayin}}</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">胎神</text>
<text class="text-base font-medium">{{almanac.fetus.position}}</text>
</view>
</view>
</view>
<!-- 冲煞 -->
<view class="card">
<view class="section-title">冲煞</view>
<view class="grid grid-cols-2 gap-2">
<view class="info-item">
<text class="text-xs text-muted">冲</text>
<text class="text-base font-medium">{{almanac.clash}}</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">害</text>
<text class="text-base font-medium">{{almanac.harm}}</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">合</text>
<text class="text-base font-medium">{{almanac.combine}}</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">煞方</text>
<text class="text-base font-medium">{{almanac.evilDirection}}</text>
</view>
</view>
</view>
<!-- 彭祖百忌 -->
<view class="card">
<view class="section-title">彭祖百忌</view>
<text class="text-base">{{almanac.pengZu}}</text>
</view>
<!-- 时辰黄历 -->
<view class="card">
<view class="section-title">时辰黄历</view>
<view class="hour-list">
<view class="hour-item" wx:for="{{almanac.hourDetails}}" wx:key="name">
<view class="flex justify-between items-center">
<text class="font-medium">{{item.name}}{{item.range}}</text>
<text class="text-sm text-muted">{{item.ganzhi}}</text>
</view>
<view class="flex gap-2 mt-1">
<text class="text-xs text-muted">值神:{{item.twelveStar}}</text>
<text class="text-xs text-muted">九星:{{item.nineStar}}</text>
</view>
</view>
</view>
</view>
<!-- 操作按钮 -->
<view class="flex gap-2 mt-2">
<view class="btn-outline flex-1 text-center" bindtap="addBookmark">收藏</view>
<view class="btn-primary flex-1 text-center" bindtap="goBazi">排八字</view>
</view>
</view>
+41
View File
@@ -0,0 +1,41 @@
.container {
padding: 20rpx;
}
.header-card {
background: linear-gradient(135deg, #C41E3A 0%, #8B1A2B 100%);
color: #FFFFFF;
border: none;
padding: 40rpx 24rpx;
}
.header-card .text-muted {
color: rgba(255,255,255,0.7);
}
.section-title {
font-size: 28rpx;
font-weight: 600;
margin-bottom: 16rpx;
color: #C41E3A;
}
.info-item {
padding: 16rpx;
background: #FFFBF5;
border-radius: 12rpx;
}
.hour-list {
max-height: 600rpx;
overflow-y: auto;
}
.hour-item {
padding: 16rpx;
border-bottom: 1rpx solid #E8D5C4;
}
.hour-item:last-child {
border-bottom: none;
}
+64
View File
@@ -0,0 +1,64 @@
const { calculatePlumBlossom, calculateBoneWeight, HEAVEN_STEMS, EARTH_BRANCHES, LUNAR_MONTH_NAMES, LUNAR_DAY_NAMES, HOUR_NAMES } = require('../../utils/core/index.js');
Page({
data: {
plumDate: new Date().toISOString().split('T')[0],
plumTime: '12:00',
plumResult: null,
yearGanzhiList: [],
monthList: LUNAR_MONTH_NAMES,
dayList: LUNAR_DAY_NAMES,
hourList: HOUR_NAMES,
boneYearIndex: 0,
boneMonthIndex: 0,
boneDayIndex: 0,
boneHourIndex: 0,
boneResult: null
},
onLoad() {
const yearGanzhiList = [];
for (let i = 0; i < 60; i++) {
yearGanzhiList.push(HEAVEN_STEMS[i % 10] + EARTH_BRANCHES[i % 12]);
}
this.setData({ yearGanzhiList });
},
onPlumDateChange(e) {
this.setData({ plumDate: e.detail.value });
},
onPlumTimeChange(e) {
this.setData({ plumTime: e.detail.value });
},
calcPlum() {
const { plumDate, plumTime } = this.data;
const [year, month, day] = plumDate.split('-').map(Number);
const [hour] = plumTime.split(':').map(Number);
const result = calculatePlumBlossom(year, month, day, hour);
this.setData({ plumResult: result });
},
onBoneYearChange(e) {
this.setData({ boneYearIndex: e.detail.value });
},
onBoneMonthChange(e) {
this.setData({ boneMonthIndex: e.detail.value });
},
onBoneDayChange(e) {
this.setData({ boneDayIndex: e.detail.value });
},
onBoneHourChange(e) {
this.setData({ boneHourIndex: e.detail.value });
},
calcBone() {
const { boneYearIndex, boneMonthIndex, boneDayIndex, boneHourIndex } = this.data;
const result = calculateBoneWeight(boneYearIndex, boneMonthIndex + 1, boneDayIndex + 1, boneHourIndex);
this.setData({ boneResult: result });
}
});
+4
View File
@@ -0,0 +1,4 @@
{
"navigationBarTitleText": "占卜",
"enablePullDownRefresh": false
}
+110
View File
@@ -0,0 +1,110 @@
<view class="container">
<!-- 梅花易数 -->
<view class="card">
<view class="section-title">梅花易数</view>
<view class="form-item">
<text class="form-label">起卦时间</text>
<picker mode="date" value="{{plumDate}}" bindchange="onPlumDateChange">
<view class="picker-input">{{plumDate}}</view>
</picker>
</view>
<view class="form-item">
<text class="form-label">时辰</text>
<picker mode="time" value="{{plumTime}}" bindchange="onPlumTimeChange">
<view class="picker-input">{{plumTime}}</view>
</picker>
</view>
<view class="btn-primary" bindtap="calcPlum">起卦</view>
</view>
<!-- 梅花易数结果 -->
<view class="card" wx:if="{{plumResult}}">
<view class="section-title">卦象</view>
<view class="hexagram-display">
<view class="trigram-row">
<text class="trigram-symbol">{{plumResult.upperTrigram.symbol}}</text>
<text class="trigram-name">{{plumResult.upperTrigram.name}}{{plumResult.upperTrigram.element}}</text>
</view>
<view class="trigram-row">
<text class="trigram-symbol">{{plumResult.lowerTrigram.symbol}}</text>
<text class="trigram-name">{{plumResult.lowerTrigram.name}}{{plumResult.lowerTrigram.element}}</text>
</view>
</view>
<view class="mt-2">
<text class="text-lg font-bold">{{plumResult.originalHexagram.name}}</text>
<text class="text-sm text-muted block mt-1">第{{plumResult.changingLine}}爻动</text>
</view>
<view class="mt-2 p-2 bg-page rounded">
<text class="text-sm">{{plumResult.originalHexagram.judgment}}</text>
</view>
<view class="mt-2 p-2 bg-page rounded">
<text class="text-sm">{{plumResult.originalHexagram.image}}</text>
</view>
<view class="mt-2" wx:if="{{plumResult.transformedHexagram}}">
<text class="text-base font-medium">变卦:{{plumResult.transformedHexagram.name}}</text>
</view>
<view class="mt-2 text-sm text-muted">
体用关系:{{plumResult.relationship}}
</view>
</view>
<!-- 称骨算命 -->
<view class="card mt-2">
<view class="section-title">称骨算命</view>
<view class="form-item">
<text class="form-label">出生年份(干支)</text>
<picker mode="selector" range="{{yearGanzhiList}}" value="{{boneYearIndex}}" bindchange="onBoneYearChange">
<view class="picker-input">{{yearGanzhiList[boneYearIndex]}}</view>
</picker>
</view>
<view class="form-item">
<text class="form-label">农历月份</text>
<picker mode="selector" range="{{monthList}}" value="{{boneMonthIndex}}" bindchange="onBoneMonthChange">
<view class="picker-input">{{monthList[boneMonthIndex]}}</view>
</picker>
</view>
<view class="form-item">
<text class="form-label">农历日期</text>
<picker mode="selector" range="{{dayList}}" value="{{boneDayIndex}}" bindchange="onBoneDayChange">
<view class="picker-input">{{dayList[boneDayIndex]}}</view>
</picker>
</view>
<view class="form-item">
<text class="form-label">时辰</text>
<picker mode="selector" range="{{hourList}}" value="{{boneHourIndex}}" bindchange="onBoneHourChange">
<view class="picker-input">{{hourList[boneHourIndex]}}</view>
</picker>
</view>
<view class="btn-primary" bindtap="calcBone">算命</view>
</view>
<!-- 称骨结果 -->
<view class="card" wx:if="{{boneResult}}">
<view class="section-title">称骨结果</view>
<view class="text-center">
<text class="text-3xl font-bold">{{boneResult.totalLiang}}两{{boneResult.totalQian}}钱</text>
<text class="badge {{boneResult.fortune.includes('上') ? 'badge-lucky' : boneResult.fortune.includes('下') ? 'badge-unlucky' : 'badge-outline'}} ml-2">{{boneResult.fortune}}</text>
</view>
<view class="mt-2 p-3 bg-page rounded">
<text class="text-base">{{boneResult.interpretation}}</text>
</view>
<view class="grid grid-cols-4 gap-2 mt-2">
<view class="text-center">
<text class="text-xs text-muted">年</text>
<text class="text-base font-medium block">{{boneResult.yearWeight}}钱</text>
</view>
<view class="text-center">
<text class="text-xs text-muted">月</text>
<text class="text-base font-medium block">{{boneResult.monthWeight}}钱</text>
</view>
<view class="text-center">
<text class="text-xs text-muted">日</text>
<text class="text-base font-medium block">{{boneResult.dayWeight}}钱</text>
</view>
<view class="text-center">
<text class="text-xs text-muted">时</text>
<text class="text-base font-medium block">{{boneResult.hourWeight}}钱</text>
</view>
</view>
</view>
</view>
+52
View File
@@ -0,0 +1,52 @@
.container {
padding: 20rpx;
}
.section-title {
font-size: 28rpx;
font-weight: 600;
margin-bottom: 16rpx;
color: #C41E3A;
}
.form-item {
margin-bottom: 24rpx;
}
.form-label {
font-size: 24rpx;
color: #6B5E53;
margin-bottom: 8rpx;
display: block;
}
.picker-input {
padding: 20rpx;
background: #FFFBF5;
border-radius: 12rpx;
border: 1rpx solid #E8D5C4;
}
.hexagram-display {
display: flex;
flex-direction: column;
align-items: center;
padding: 24rpx;
background: #FFFBF5;
border-radius: 16rpx;
}
.trigram-row {
display: flex;
align-items: center;
gap: 16rpx;
margin: 8rpx 0;
}
.trigram-symbol {
font-size: 64rpx;
}
.trigram-name {
font-size: 28rpx;
}
+47
View File
@@ -0,0 +1,47 @@
const { calculateDailyFortune } = require('../../utils/core/index.js');
Page({
data: {
hasBazi: false,
fortune: null,
scoreLevelText: ''
},
onShow() {
this.loadFortune();
},
onPullDownRefresh() {
this.loadFortune();
wx.stopPullDownRefresh();
},
loadFortune() {
const bazi = wx.getStorageSync('lunar-user-bazi');
if (!bazi) {
this.setData({ hasBazi: false, fortune: null });
return;
}
const today = new Date();
const fortune = calculateDailyFortune(bazi.eightChar, today);
const levelMap = {
great: '大吉',
good: '吉',
fair: '平',
poor: '凶',
bad: '大凶'
};
this.setData({
hasBazi: true,
fortune,
scoreLevelText: levelMap[fortune.scoreLevel] || '平'
});
},
goBazi() {
wx.switchTab({ url: '/pages/bazi/bazi' });
}
});
+4
View File
@@ -0,0 +1,4 @@
{
"navigationBarTitleText": "每日运势",
"enablePullDownRefresh": true
}
+98
View File
@@ -0,0 +1,98 @@
<view class="container">
<!-- 无八字提示 -->
<view class="card text-center" wx:if="{{!hasBazi}}">
<text class="text-lg text-muted">请先排八字以查看每日运势</text>
<view class="btn-primary mt-2" bindtap="goBazi">去排八字</view>
</view>
<!-- 运势内容 -->
<block wx:if="{{hasBazi && fortune}}">
<!-- 总分卡片 -->
<view class="card score-card">
<view class="text-center">
<text class="score-value">{{fortune.overallScore}}</text>
<text class="score-level">{{scoreLevelText}}</text>
</view>
<view class="text-sm text-muted text-center mt-1">{{fortune.date}} {{fortune.lunarDate}}</view>
</view>
<!-- 幸运元素 -->
<view class="card">
<view class="section-title">幸运元素</view>
<view class="grid grid-cols-2 gap-2">
<view class="info-item">
<text class="text-xs text-muted">幸运色</text>
<text class="text-base font-medium">{{fortune.luckyMeta.colors.join('、')}}</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">幸运数字</text>
<text class="text-base font-medium">{{fortune.luckyMeta.numbers.join('、')}}</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">幸运方位</text>
<text class="text-base font-medium">{{fortune.luckyMeta.direction}}</text>
</view>
<view class="info-item">
<text class="text-xs text-muted">五行</text>
<text class="text-base font-medium">{{fortune.luckyMeta.element}}</text>
</view>
</view>
</view>
<!-- 四柱关系 -->
<view class="card">
<view class="section-title">四柱与今日关系</view>
<view class="relation-list">
<view class="relation-item" wx:for="{{fortune.pillarRelationships}}" wx:key="pillar">
<view class="flex justify-between items-center">
<text class="font-medium">{{item.pillarLabel}}</text>
<text class="text-sm {{item.score >= 0 ? 'text-lucky' : 'text-unlucky'}}">{{item.score > 0 ? '+' : ''}}{{item.score}}</text>
</view>
<view class="text-sm text-muted mt-1">
{{item.userGanzhi}} vs {{item.dayGanzhi}}
</view>
<view class="flex flex-wrap gap-1 mt-1">
<text class="badge badge-outline" wx:if="{{item.stemTenStar}}">{{item.stemTenStar}}</text>
<text class="badge badge-lucky" wx:if="{{item.stemCombine}}">天干合</text>
<text class="badge badge-unlucky" wx:if="{{item.stemOpposite}}">天干冲</text>
<text class="badge badge-lucky" wx:if="{{item.branchCombine}}">地支合</text>
<text class="badge badge-unlucky" wx:if="{{item.branchOpposite}}">地支冲</text>
</view>
</view>
</view>
</view>
<!-- 建议 -->
<view class="card">
<view class="section-title">今日建议</view>
<view class="suggestion-list">
<view class="suggestion-item" wx:for="{{fortune.suggestions}}" wx:key="*this">
<text class="text-base">{{item}}</text>
</view>
</view>
</view>
<!-- 分项得分 -->
<view class="card">
<view class="section-title">分项运势</view>
<view class="grid grid-cols-2 gap-2">
<view class="info-item text-center">
<text class="text-xs text-muted">爱情</text>
<text class="text-xl font-bold {{fortune.categoryScores.love >= 0 ? 'text-lucky' : 'text-unlucky'}}">{{fortune.categoryScores.love}}</text>
</view>
<view class="info-item text-center">
<text class="text-xs text-muted">事业</text>
<text class="text-xl font-bold {{fortune.categoryScores.career >= 0 ? 'text-lucky' : 'text-unlucky'}}">{{fortune.categoryScores.career}}</text>
</view>
<view class="info-item text-center">
<text class="text-xs text-muted">财运</text>
<text class="text-xl font-bold {{fortune.categoryScores.wealth >= 0 ? 'text-lucky' : 'text-unlucky'}}">{{fortune.categoryScores.wealth}}</text>
</view>
<view class="info-item text-center">
<text class="text-xs text-muted">健康</text>
<text class="text-xl font-bold {{fortune.categoryScores.health >= 0 ? 'text-lucky' : 'text-unlucky'}}">{{fortune.categoryScores.health}}</text>
</view>
</view>
</view>
</block>
</view>
+47
View File
@@ -0,0 +1,47 @@
.container {
padding: 20rpx;
}
.score-card {
background: linear-gradient(135deg, #C41E3A 0%, #8B1A2B 100%);
color: #FFFFFF;
border: none;
padding: 40rpx 24rpx;
}
.score-value {
font-size: 80rpx;
font-weight: 700;
}
.score-level {
font-size: 32rpx;
margin-left: 16rpx;
opacity: 0.9;
}
.section-title {
font-size: 28rpx;
font-weight: 600;
margin-bottom: 16rpx;
color: #C41E3A;
}
.info-item {
padding: 16rpx;
background: #FFFBF5;
border-radius: 12rpx;
}
.relation-item {
padding: 16rpx;
border-bottom: 1rpx solid #E8D5C4;
}
.relation-item:last-child {
border-bottom: none;
}
.suggestion-item {
padding: 12rpx 0;
}
+28
View File
@@ -0,0 +1,28 @@
const { getTodayInfo, getAlmanacInfo } = require('../../utils/core/index.js');
Page({
data: {
dayInfo: {},
almanac: {}
},
onLoad() {
this.loadData();
},
onPullDownRefresh() {
this.loadData();
wx.stopPullDownRefresh();
},
loadData() {
const dayInfo = getTodayInfo();
const almanac = getAlmanacInfo(dayInfo.solarYear, dayInfo.solarMonth, dayInfo.solarDay);
this.setData({ dayInfo, almanac });
},
navTo(e) {
const url = e.currentTarget.dataset.url;
wx.navigateTo({ url });
}
});
+5
View File
@@ -0,0 +1,5 @@
{
"navigationBarTitleText": "万年历",
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark"
}
+94
View File
@@ -0,0 +1,94 @@
<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>
<view class="text-right">
<text class="text-base">{{dayInfo.weekDay}}</text>
<text class="text-sm text-muted block">{{dayInfo.constellation}}</text>
</view>
</view>
<view class="mt-2 flex items-center gap-2">
<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>
</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>
</view>
</view>
</view>
<!-- 黄历详情 -->
<view class="card">
<view class="grid grid-cols-2 gap-2">
<view class="p-2 bg-page rounded">
<text class="text-xs text-muted">值神</text>
<text class="text-base font-medium block">{{almanac.duty}}</text>
</view>
<view class="p-2 bg-page rounded">
<text class="text-xs text-muted">黄道</text>
<text class="text-base font-medium block">{{almanac.twelveStar.name}}{{almanac.twelveStar.ecliptic}}</text>
</view>
<view class="p-2 bg-page rounded">
<text class="text-xs text-muted">二十八宿</text>
<text class="text-base font-medium block">{{almanac.twentyEightStar.name}}</text>
</view>
<view class="p-2 bg-page rounded">
<text class="text-xs text-muted">六曜</text>
<text class="text-base font-medium block">{{almanac.sixStar}}</text>
</view>
</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>
<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>
</view>
</view>
+31
View File
@@ -0,0 +1,31 @@
.container {
padding: 20rpx;
padding-bottom: 40rpx;
}
.date-card {
background: linear-gradient(135deg, #C41E3A 0%, #8B1A2B 100%);
color: #FFFFFF;
border: none;
}
.date-card .text-muted {
color: rgba(255,255,255,0.7);
}
.quick-entry {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 24rpx;
background: #FFFFFF;
border-radius: 16rpx;
border: 1rpx solid #E8D5C4;
}
.quick-icon {
width: 64rpx;
height: 64rpx;
margin-bottom: 8rpx;
}
+74
View File
@@ -0,0 +1,74 @@
Page({
data: {
userInfo: null,
weekStartDay: 0,
ziHourSect: 'lateZiNextDay',
solarTime: true,
bookmarks: []
},
onLoad() {
this.loadSettings();
this.loadBookmarks();
},
onShow() {
this.loadBookmarks();
},
loadSettings() {
const settings = wx.getStorageSync('lunar-settings') || {};
this.setData({
weekStartDay: settings.weekStartDay || 0,
ziHourSect: settings.ziHourSect || 'lateZiNextDay',
solarTime: settings.solarTime !== false
});
},
saveSettings() {
const { weekStartDay, ziHourSect, solarTime } = this.data;
wx.setStorageSync('lunar-settings', { weekStartDay, ziHourSect, solarTime });
},
loadBookmarks() {
const bookmarks = wx.getStorageSync('lunar-bookmarks') || [];
this.setData({ bookmarks });
},
setWeekStart(e) {
this.setData({ weekStartDay: Number(e.currentTarget.dataset.v) });
this.saveSettings();
},
setZiSect(e) {
this.setData({ ziHourSect: e.currentTarget.dataset.v });
this.saveSettings();
},
onSolarTimeChange(e) {
this.setData({ solarTime: e.detail.value });
this.saveSettings();
},
removeBookmark(e) {
const date = e.currentTarget.dataset.date;
let bookmarks = this.data.bookmarks.filter(b => b.date !== date);
wx.setStorageSync('lunar-bookmarks', bookmarks);
this.setData({ bookmarks });
wx.showToast({ title: '已删除', icon: 'success' });
},
login() {
wx.getUserProfile({
desc: '用于完善用户资料',
success: (res) => {
this.setData({ userInfo: res.userInfo });
wx.setStorageSync('lunar-user-info', res.userInfo);
wx.showToast({ title: '登录成功', icon: 'success' });
},
fail: () => {
wx.showToast({ title: '登录失败', icon: 'none' });
}
});
}
});
+4
View File
@@ -0,0 +1,4 @@
{
"navigationBarTitleText": "设置",
"enablePullDownRefresh": false
}
+68
View File
@@ -0,0 +1,68 @@
<view class="container">
<!-- 用户信息 -->
<view class="card">
<view class="section-title">用户信息</view>
<view class="flex items-center gap-2" wx:if="{{userInfo}}">
<image src="{{userInfo.avatarUrl}}" class="avatar" mode="aspectFill"/>
<view>
<text class="text-base font-medium">{{userInfo.nickName}}</text>
<text class="text-xs text-muted block">已登录</text>
</view>
</view>
<view class="btn-primary" wx:else bindtap="login">微信登录</view>
</view>
<!-- 偏好设置 -->
<view class="card">
<view class="section-title">偏好设置</view>
<view class="setting-item">
<text class="setting-label">周起始日</text>
<view class="flex gap-2">
<view class="btn-outline {{weekStartDay === 0 ? 'active' : ''}}" bindtap="setWeekStart" data-v="0">周日</view>
<view class="btn-outline {{weekStartDay === 1 ? 'active' : ''}}" bindtap="setWeekStart" data-v="1">周一</view>
</view>
</view>
<view class="setting-item">
<text class="setting-label">子时流派</text>
<view class="flex gap-2">
<view class="btn-outline {{ziHourSect === 'lateZiNextDay' ? 'active' : ''}}" bindtap="setZiSect" data-v="lateZiNextDay">晚子时算次日</view>
<view class="btn-outline {{ziHourSect === 'lateZiSameDay' ? 'active' : ''}}" bindtap="setZiSect" data-v="lateZiSameDay">晚子时算当日</view>
</view>
</view>
<view class="setting-item">
<text class="setting-label">真太阳时校正</text>
<switch checked="{{solarTime}}" bindchange="onSolarTimeChange" color="#C41E3A"/>
</view>
</view>
<!-- 收藏管理 -->
<view class="card">
<view class="section-title">我的收藏</view>
<view class="bookmark-list" wx:if="{{bookmarks.length > 0}}">
<view class="bookmark-item" wx:for="{{bookmarks}}" wx:key="date">
<view class="flex justify-between items-center">
<view>
<text class="text-base font-medium">{{item.date}}</text>
<text class="text-xs text-muted block">{{item.lunarDate}}</text>
</view>
<view class="btn-ghost text-unlucky" bindtap="removeBookmark" data-date="{{item.date}}">删除</view>
</view>
</view>
</view>
<view class="text-center text-muted" wx:else>
<text>暂无收藏</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>
</view>
</view>
</view>
+47
View File
@@ -0,0 +1,47 @@
.container {
padding: 20rpx;
}
.section-title {
font-size: 28rpx;
font-weight: 600;
margin-bottom: 16rpx;
color: #C41E3A;
}
.avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
}
.setting-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 0;
border-bottom: 1rpx solid #E8D5C4;
}
.setting-item:last-child {
border-bottom: none;
}
.setting-label {
font-size: 28rpx;
}
.btn-outline.active {
background: #C41E3A;
color: #FFFFFF;
border-color: #C41E3A;
}
.bookmark-item {
padding: 16rpx 0;
border-bottom: 1rpx solid #E8D5C4;
}
.bookmark-item:last-child {
border-bottom: none;
}
+36
View File
@@ -0,0 +1,36 @@
const { SOLAR_TERMS, SOLAR_TERM_DATES } = require('../../utils/core/index.js');
Page({
data: {
year: new Date().getFullYear(),
terms: []
},
onLoad() {
this.loadTerms();
},
loadTerms() {
const { year } = this.data;
const today = new Date();
const terms = [];
for (let m = 0; m < 12; m++) {
for (let t = 0; t < 2; t++) {
const termIndex = m * 2 + t;
const day = SOLAR_TERM_DATES[m][t];
const dateStr = `${year}-${String(m + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
const termDate = new Date(year, m, day);
terms.push({
name: SOLAR_TERMS[termIndex],
date: dateStr,
isPast: termDate < today
});
}
}
// 按日期排序
terms.sort((a, b) => new Date(a.date) - new Date(b.date));
this.setData({ terms });
}
});
+4
View File
@@ -0,0 +1,4 @@
{
"navigationBarTitleText": "二十四节气",
"enablePullDownRefresh": false
}
+16
View File
@@ -0,0 +1,16 @@
<view class="container">
<view class="card">
<view class="section-title">{{year}}年二十四节气</view>
<view class="term-list">
<view class="term-item" wx:for="{{terms}}" wx:key="name">
<view class="flex justify-between items-center">
<view>
<text class="text-base font-medium">{{item.name}}</text>
<text class="text-xs text-muted block">{{item.date}}</text>
</view>
<text class="badge {{item.isPast ? 'badge-outline' : 'badge-lucky'}}">{{item.isPast ? '已过' : '未来'}}</text>
</view>
</view>
</view>
</view>
</view>
+24
View File
@@ -0,0 +1,24 @@
.container {
padding: 20rpx;
}
.section-title {
font-size: 28rpx;
font-weight: 600;
margin-bottom: 16rpx;
color: #C41E3A;
}
.term-list {
display: flex;
flex-direction: column;
}
.term-item {
padding: 20rpx 0;
border-bottom: 1rpx solid #E8D5C4;
}
.term-item:last-child {
border-bottom: none;
}