feat(bazi): 八字页重构——空态示例排盘+字段术语表+文化声明,生辰档案绑定
Publish Mini Program Dev Version / publish (push) Failing after 11s
Build and Publish Server / build (push) Successful in 2m55s

- 八字页:未绑定生辰时展示虚构示例排盘(1990-08-08 10:30男)与15条字段说明,
  附传统文化声明文案;已绑定时支持多档案切换,排盘增强(十神/藏干/纳音/五行配色/命盘概览)
- 个人中心:新增生辰管理卡片,每用户免费绑定3个出生年月;登录改为真实微信登录
- 服务端:新增 BirthProfile 模型与 /api/user/birth-profiles 增删查接口,AutoMigrate 建表
- 前端:新增 birth-profile.js 本地存储优先+登录后云端双向同步
- 修复:个人中心 tabBar 页面入口误用 navigateTo 改为 switchTab
This commit is contained in:
gouki
2026-08-09 23:21:58 +00:00
parent 013e7ab99a
commit 50975e0627
12 changed files with 1068 additions and 196 deletions
+130 -55
View File
@@ -1,75 +1,150 @@
const { birthInfoToBazi, analyzeElementBalance } = require('../../utils/core/index.js');
const birthProfile = require('../../utils/birth-profile.js');
// 空态演示用的示例生辰(虚构,仅作排盘样式展示)
const DEMO_BIRTH = { year: 1990, month: 8, day: 8, hour: 10, minute: 30, gender: 'male', ziSect: 'lateZiNextDay' };
// 五行 → 样式类名
const ELEMENT_CLASS = { '木': 'el-wood', '火': 'el-fire', '土': 'el-earth', '金': 'el-metal', '水': 'el-water' };
// 八字知识词条:逐字段详细说明
const GLOSSARY = [
{ term: '四柱八字', desc: '用天干地支记录出生年、月、日、时的方法,年、月、日、时各一对干支,合称"四柱",共八个字,故称"八字"。它源于古代干支纪时体系,是传统历法文化的一部分。' },
{ term: '天干地支', desc: '天干共十个(甲乙丙丁戊己庚辛壬癸),地支共十二个(子丑寅卯辰巳午未申酉戌亥),是古人用于纪年、纪月、纪日、纪时的符号系统,也是传统历法的基础。' },
{ term: '年柱', desc: '出生年份的干支。传统上以立春为界划分年份(立春前出生按上一年)。年柱在民俗说法中对应祖辈与少年时期。' },
{ term: '月柱', desc: '出生月份的干支。月份以节气划分(如立春至惊蛰为正月),并非公历或农历的自然月。民俗说法中对应父母与青年时期。' },
{ term: '日柱', desc: '出生当日的干支,按六十甲子循环纪日。日柱的天干代表本人(日主),是整个命盘分析的核心。' },
{ term: '时柱', desc: '出生时辰的干支。古人将一昼夜分为十二个时辰,每个时辰合今两小时(如子时为 23:00-01:00)。' },
{ term: '日主', desc: '日柱的天干,代表命主本人。日主的五行属性(木火土金水)是分析命盘五行强弱与十神关系的出发点。' },
{ term: '十神', desc: '以日主为参照,按五行生克关系对其他干支的十种称谓:比肩、劫财、食神、伤官、偏财、正财、七杀、正官、偏印、正印。它是古代的一种关系分类符号,用于描述干支之间的生克比和。' },
{ term: '五行', desc: '木、火、土、金、水五种基本元素,源于古代哲学,认为万物由五行构成并相生相克(木生火、火生土、土生金、金生水、水生木;木克土、土克水、水克火、火克金、金克木)。五行分析统计八字中各元素的数量与强弱。' },
{ term: '藏干', desc: '又称"人元",指每个地支内部按传统规则所含的一个至三个天干。例如寅中藏甲、丙、戊。排盘时作为辅助信息列出。' },
{ term: '纳音', desc: '将六十甲子两两配对归入五行所得的三十种称谓,如"甲子乙丑海中金"、"丙寅丁卯炉中火"。年命纳音(年柱纳音)在民俗中常被用来称呼人的"命",如"金命"、"火命"。' },
{ term: '空亡', desc: '六十甲子分为六旬,每旬十个干支配十二地支,余下两个地支无天干相配,称为该旬"空亡"。这是干支纪法本身的结构性概念,此处仅作历法知识展示。' },
{ term: '大运', desc: '传统上以月柱为基础、按十年一换的节奏推演出的干支序列,用来描述人生不同阶段的节律。属于传统民俗推演方法,供文化了解。' },
{ term: '流年', desc: '即每一年的干支(如 2026 年为丙午年)。传统做法将流年与本命干支对照,观察逐年的变化关系。' },
{ term: '子时流派', desc: '子时(23:00-01:00)横跨两天,晚子时(23:00-24:00)出生者的日柱按当天还是次日起算,历代流派说法不一。可在"我的-偏好设置"中选择。' }
];
/** 根据出生信息构建排盘展示数据 */
function buildChart({ year, month, day, hour, minute, gender, ziSect }) {
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 }
].map(p => ({
label: p.label,
ganzhi: p.ganzhi,
tenStar: p.tenStar || '日主',
heavenStem: p.heavenStem,
earthBranch: p.earthBranch,
stemClass: ELEMENT_CLASS[p.elementStem] || '',
branchClass: ELEMENT_CLASS[p.elementBranch] || '',
hideStems: (p.hideStems || []).map(h => h.stem + (h.tenStar ? `(${h.tenStar})` : '')).join(' '),
nayin: p.nayin
}));
const total = elementAnalysis.total || 1;
const elements = [
{ name: '木', count: elementAnalysis.wood, percent: Math.round(elementAnalysis.wood / total * 100), cls: 'el-wood' },
{ name: '火', count: elementAnalysis.fire, percent: Math.round(elementAnalysis.fire / total * 100), cls: 'el-fire' },
{ name: '土', count: elementAnalysis.earth, percent: Math.round(elementAnalysis.earth / total * 100), cls: 'el-earth' },
{ name: '金', count: elementAnalysis.metal, percent: Math.round(elementAnalysis.metal / total * 100), cls: 'el-metal' },
{ name: '水', count: elementAnalysis.water, percent: Math.round(elementAnalysis.water / total * 100), cls: 'el-water' }
];
return { bazi, pillars, elements, elementAnalysis };
}
Page({
data: {
gender: 'male',
birthDate: '1990-01-01',
birthTime: '12:00',
ziSect: 'lateZiNextDay',
isDemo: true,
profiles: [],
activeProfileId: '',
profile: null,
bazi: null,
pillars: [],
elements: [],
elementAnalysis: {}
elementAnalysis: {},
glossary: GLOSSARY,
showGlossary: false
},
onLoad() {
// 尝试从本地存储恢复
const saved = wx.getStorageSync('lunar-bazi-input');
if (saved) {
this.setData(saved);
onShow() {
this.refresh();
},
refresh() {
const render = () => {
const profiles = birthProfile.getProfiles();
if (profiles.length === 0) {
this.showDemo();
} else {
this.showProfile(profiles, birthProfile.getActiveProfile());
}
};
// 已登录时先同步云端档案,失败静默回退本地
if (birthProfile.isLoggedIn()) {
birthProfile.syncFromServer().then(render).catch(render);
} else {
render();
}
},
setGender(e) {
this.setData({ gender: e.currentTarget.dataset.g });
/** 空态:展示示例排盘 */
showDemo() {
const chart = buildChart(DEMO_BIRTH);
this.setData({
isDemo: true,
profiles: [],
activeProfileId: '',
profile: null,
showGlossary: true,
...chart
});
},
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 });
/** 已绑定:展示所选档案的排盘 */
showProfile(profiles, profile) {
if (!profile) return;
const [year, month, day] = profile.birthday.split('-').map(Number);
const [hour, minute] = profile.birthTime.split(':').map(Number);
const settings = wx.getStorageSync('lunar-settings') || {};
const chart = buildChart({
year, month, day, hour, minute,
gender: profile.gender,
ziSect: settings.ziHourSect || 'lateZiNextDay'
});
// 保存八字供运势页使用
wx.setStorageSync('lunar-user-bazi', bazi);
wx.setStorageSync('lunar-user-bazi', chart.bazi);
this.setData({
isDemo: false,
profiles,
activeProfileId: profile.id,
profile,
showGlossary: false,
...chart
});
},
reset() {
this.setData({ bazi: null });
selectProfile(e) {
const id = e.currentTarget.dataset.id;
const profile = this.data.profiles.find(p => p.id === id);
if (!profile) return;
birthProfile.setActiveProfile(id);
this.showProfile(this.data.profiles, profile);
},
toggleGlossary() {
this.setData({ showGlossary: !this.data.showGlossary });
},
goSettings() {
wx.switchTab({ url: '/pages/settings/settings' });
},
goFortune() {
+150 -97
View File
@@ -1,104 +1,157 @@
<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 class="culture-card">
<view class="culture-title">八字 · 传统历法文化</view>
<view class="culture-text">八字(四柱)是中国传统文化的重要组成部分,源自古人观测天象、制定历法的干支纪时体系与五行哲学思想,属于传统民俗文化与历法知识范畴,不是封建迷信。本页面仅按传统历法规则进行排盘展示与知识科普,内容供传统文化学习与娱乐参考,不构成任何人生决策建议。</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>
<!-- 空态:示例提示 + 绑定入口 -->
<block wx:if="{{isDemo}}">
<view class="card empty-card">
<view class="empty-title">你还没有绑定生辰信息</view>
<view class="empty-desc">下方是一份示例排盘,帮助你了解八字页面的内容。在个人中心可免费绑定 3 个出生年月(本人、家人),绑定后即可查看专属排盘。</view>
<view class="btn-primary text-center mt-2" bindtap="goSettings">去绑定我的生辰</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 class="demo-banner">
<text class="demo-tag">示例</text>
<text class="demo-text">以下排盘基于虚构生辰(1990-08-08 10:30 男),仅演示页面效果</text>
</view>
</block>
<!-- 已绑定:档案选择 -->
<view class="card" wx:if="{{!isDemo}}">
<view class="section-title">我的生辰</view>
<view class="flex gap-2 profile-chips">
<view
class="profile-chip {{item.id === activeProfileId ? 'active' : ''}}"
wx:for="{{profiles}}"
wx:key="id"
bindtap="selectProfile"
data-id="{{item.id}}"
>{{item.name}}</view>
<view class="profile-chip add-chip" bindtap="goSettings">管理 </view>
</view>
<view class="text-xs text-muted mt-1">
{{profile.name}} · {{profile.gender === 'female' ? '女' : '男'}} · 公历 {{profile.birthday}} {{profile.birthTime}}
</view>
</view>
<!-- 四柱八字 -->
<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-ten">{{item.tenStar}}</text>
<text class="pillar-char {{item.stemClass}}">{{item.heavenStem}}</text>
<text class="pillar-char {{item.branchClass}}">{{item.earthBranch}}</text>
<text class="pillar-hide" wx:if="{{item.hideStems}}">藏 {{item.hideStems}}</text>
<text class="pillar-nayin">{{item.nayin}}</text>
</view>
</view>
</view>
<!-- 命盘概览 -->
<view class="card">
<view class="section-title">命盘概览</view>
<view class="meta-grid">
<view class="meta-item">
<text class="meta-label">日主</text>
<text class="meta-value">{{bazi.eightChar.dayMaster}}</text>
</view>
<view class="meta-item">
<text class="meta-label">五行旺</text>
<text class="meta-value">{{elementAnalysis.dominant}}</text>
</view>
<view class="meta-item">
<text class="meta-label">五行弱</text>
<text class="meta-value">{{elementAnalysis.weakest}}</text>
</view>
<view class="meta-item">
<text class="meta-label">空亡</text>
<text class="meta-value">{{bazi.eightChar.emptyBranches[0]}}{{bazi.eightChar.emptyBranches[1]}}</text>
</view>
<view class="meta-item">
<text class="meta-label">年柱纳音</text>
<text class="meta-value">{{pillars[0].nayin}}</text>
</view>
<view class="meta-item">
<text class="meta-label">五行均衡</text>
<text class="meta-value">{{elementAnalysis.isBalanced ? '较均衡' : '有偏旺'}}</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 {{item.cls}}" style="width: {{item.percent}}%"></view>
</view>
<text class="element-count">{{item.count}}</text>
</view>
</view>
<view class="mt-2 text-xs text-muted">按天干、地支计 1 分,藏干计 0.5 分;得分越高代表该五行在命盘中越突出。</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="card">
<view class="glossary-header" bindtap="toggleGlossary">
<text class="section-title glossary-title">这些字段是什么意思?</text>
<text class="glossary-toggle">{{showGlossary ? '收起' : '展开'}}</text>
</view>
<block wx:if="{{showGlossary}}">
<view class="glossary-item" wx:for="{{glossary}}" wx:key="term">
<text class="glossary-term">{{item.term}}</text>
<text class="glossary-desc">{{item.desc}}</text>
</view>
</block>
</view>
<!-- 底部操作 -->
<view class="flex gap-2 mt-2 bottom-actions">
<block wx:if="{{isDemo}}">
<view class="btn-primary flex-1 text-center" bindtap="goSettings">绑定生辰,查看我的排盘</view>
</block>
<block wx:else>
<view class="btn-outline flex-1 text-center" bindtap="goSettings">管理生辰</view>
<view class="btn-primary flex-1 text-center" bindtap="goFortune">看今日运势</view>
</block>
</view>
<!-- 底部免责声明 -->
<view class="disclaimer">
八字排盘为传统历法文化展示,内容仅供学习参考,请理性看待,切勿迷信。
</view>
</view>
+200 -23
View File
@@ -9,35 +9,103 @@
color: #C41E3A;
}
.form-item {
margin-bottom: 24rpx;
/* 文化声明卡片 */
.culture-card {
background: linear-gradient(135deg, #C41E3A 0%, #8B1A2B 100%);
border-radius: 24rpx;
padding: 28rpx 24rpx;
margin-bottom: 16rpx;
}
.form-label {
.culture-title {
color: #FFFFFF;
font-size: 32rpx;
font-weight: 700;
margin-bottom: 12rpx;
}
.culture-text {
color: rgba(255, 255, 255, 0.92);
font-size: 24rpx;
line-height: 1.7;
}
/* 空态卡片 */
.empty-card {
text-align: center;
}
.empty-title {
font-size: 32rpx;
font-weight: 600;
color: #1A1A1A;
margin-bottom: 12rpx;
}
.empty-desc {
font-size: 24rpx;
color: #6B5E53;
margin-bottom: 8rpx;
display: block;
line-height: 1.7;
}
.picker-input {
padding: 20rpx;
background: #FFFBF5;
border-radius: 12rpx;
border: 1rpx solid #E8D5C4;
/* 示例横幅 */
.demo-banner {
display: flex;
align-items: center;
gap: 12rpx;
background: #FFF7E6;
border: 1rpx solid #F0D9A8;
border-radius: 16rpx;
padding: 16rpx 20rpx;
margin-bottom: 16rpx;
}
.btn-outline.active {
background: #C41E3A;
.demo-tag {
flex-shrink: 0;
background: #D99A06;
color: #FFFFFF;
border-color: #C41E3A;
font-size: 20rpx;
border-radius: 8rpx;
padding: 2rpx 12rpx;
}
.demo-text {
font-size: 22rpx;
color: #8A6D1A;
line-height: 1.5;
}
/* 档案选择 */
.profile-chips {
flex-wrap: wrap;
}
.profile-chip {
padding: 10rpx 28rpx;
border-radius: 999rpx;
border: 2rpx solid #E8D5C4;
font-size: 26rpx;
color: #6B5E53;
background: #FFFFFF;
}
.profile-chip.active {
background: #C41E3A;
border-color: #C41E3A;
color: #FFFFFF;
}
.add-chip {
border-style: dashed;
color: #9E8E7E;
}
/* 四柱 */
.pillar {
display: flex;
flex-direction: column;
align-items: center;
padding: 20rpx;
padding: 16rpx 8rpx;
background: #FFFBF5;
border-radius: 12rpx;
}
@@ -47,18 +115,69 @@
color: #9E8E7E;
}
.pillar-ganzhi {
font-size: 36rpx;
font-weight: 700;
color: #C41E3A;
margin: 8rpx 0;
}
.pillar-ten {
font-size: 20rpx;
color: #6B5E53;
margin: 4rpx 0;
}
.pillar-char {
font-size: 44rpx;
font-weight: 700;
line-height: 1.2;
color: #1A1A1A;
}
.pillar-hide {
font-size: 18rpx;
color: #9E8E7E;
margin-top: 8rpx;
text-align: center;
word-break: break-all;
}
.pillar-nayin {
font-size: 18rpx;
color: #C41E3A;
margin-top: 4rpx;
}
/* 五行配色 */
.el-wood { color: #2E7D32; }
.el-fire { color: #C41E3A; }
.el-earth { color: #8D6E63; }
.el-metal { color: #B8860B; }
.el-water { color: #1565C0; }
/* 命盘概览 */
.meta-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16rpx;
}
.meta-item {
display: flex;
flex-direction: column;
align-items: center;
background: #FFFBF5;
border-radius: 12rpx;
padding: 16rpx 8rpx;
}
.meta-label {
font-size: 20rpx;
color: #9E8E7E;
}
.meta-value {
font-size: 28rpx;
font-weight: 600;
color: #1A1A1A;
margin-top: 4rpx;
}
/* 五行分析 */
.element-bar {
display: flex;
flex-direction: column;
@@ -79,23 +198,29 @@
.element-track {
flex: 1;
height: 16rpx;
background: #E8D5C4;
background: #F0E6DA;
border-radius: 8rpx;
overflow: hidden;
}
.element-fill {
height: 100%;
background: #C41E3A;
border-radius: 8rpx;
}
.element-fill.el-wood { background: #2E7D32; }
.element-fill.el-fire { background: #C41E3A; }
.element-fill.el-earth { background: #8D6E63; }
.element-fill.el-metal { background: #B8860B; }
.element-fill.el-water { background: #1565C0; }
.element-count {
width: 60rpx;
text-align: right;
font-size: 24rpx;
}
/* 大运/流年 */
.fortune-item {
display: flex;
flex-direction: column;
@@ -105,3 +230,55 @@
border-radius: 12rpx;
min-width: 160rpx;
}
/* 字段说明 */
.glossary-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.glossary-title {
margin-bottom: 0;
}
.glossary-toggle {
font-size: 24rpx;
color: #9E8E7E;
}
.glossary-item {
padding: 16rpx 0;
border-bottom: 1rpx solid #F0E6DA;
}
.glossary-item:last-child {
border-bottom: none;
}
.glossary-term {
display: block;
font-size: 26rpx;
font-weight: 600;
color: #C41E3A;
margin-bottom: 6rpx;
}
.glossary-desc {
display: block;
font-size: 24rpx;
color: #6B5E53;
line-height: 1.7;
}
/* 底部 */
.bottom-actions {
margin-bottom: 16rpx;
}
.disclaimer {
text-align: center;
font-size: 20rpx;
color: #9E8E7E;
padding: 8rpx 0 24rpx;
}