<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>信陵文化斗數排盤</title>
<!-- 載入 Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- 載入 React 和 ReactDOM -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<!-- 載入 Babel (用於解析 JSX) -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- 設定列印樣式 -->
<style>
@media print {
@page {
size: A4 portrait;
margin: 10mm;
}
body {
background: white;
-webkit-print-color-adjust: exact;
}
.print-hidden {
display: none !important;
}
.no-print-border {
border: none !important;
}
}
.writing-vertical-rl {
writing-mode: vertical-rl;
text-orientation: upright;
}
</style>
</head>
<body class="bg-stone-100 text-stone-900">
<div id="root"></div>
<script type="text/babel">
const { useState, useEffect } = React;
// --- 圖示組件 (SVG) ---
const Printer = ({ size = 24, className = "" }) => (
<svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><polyline points="6 9 6 2 18 2 18 9"></polyline><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"></path><rect x="6" y="14" width="12" height="8"></rect></svg>
);
const Settings = ({ size = 24, className = "" }) => (
<svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
);
const Info = ({ size = 24, className = "" }) => (
<svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg>
);
const Moon = ({ size = 24, className = "" }) => (
<svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>
);
// --- 基礎數據定義 ---
const TIAN_GAN = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'];
const DI_ZHI = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥'];
const PALACE_NAMES = ['命宮', '兄弟', '夫妻', '子女', '財帛', '疾厄', '遷移', '交友', '官祿', '田宅', '福德', '父母'];
const FIVE_ELEMENTS = { 2: '水二局', 3: '木三局', 4: '金四局', 5: '土五局', 6: '火六局' };
const ZIWEI_SERIES = ['紫微', '天機', null, '太陽', '武曲', '天同', null, null, '廉貞'];
const TIANFU_SERIES = ['天府', '太陰', '貪狼', '巨門', '天相', '天梁', '七殺', null, null, null, '破軍'];
const SI_HUA = {
'甲': { 祿: '廉貞', 權: '破軍', 科: '武曲', 忌: '太陽' },
'乙': { 祿: '天機', 權: '天梁', 科: '紫微', 忌: '太陰' },
'丙': { 祿: '天同', 權: '天機', 科: '文昌', 忌: '廉貞' },
'丁': { 祿: '太陰', 權: '天同', 科: '天機', 忌: '巨門' },
'戊': { 祿: '貪狼', 權: '太陰', 科: '右弼', 忌: '天機' },
'己': { 祿: '武曲', 權: '貪狼', 科: '天梁', 忌: '文曲' },
'庚': { 祿: '太陽', 權: '武曲', 科: '太陰', 忌: '天同' },
'辛': { 祿: '巨門', 權: '太陽', 科: '文曲', 忌: '文昌' },
'壬': { 祿: '天梁', 權: '紫微', 科: '左輔', 忌: '武曲' },
'癸': { 祿: '破軍', 權: '巨門', 科: '太陰', 忌: '貪狼' },
};
// --- 工具函數 ---
const getGanIdx = (gan) => TIAN_GAN.indexOf(gan);
const getZhiIdx = (zhi) => DI_ZHI.indexOf(zhi);
const getMonthGan = (yearGanIdx, monthZhiIdx) => {
const base = (yearGanIdx % 5) * 2 + 2;
let offset = (getZhiIdx(monthZhiIdx) - 2 + 12) % 12;
return TIAN_GAN[(base + offset) % 10];
};
const getMingShen = (month, hourZhi) => {
const startZhi = 2;
const hourIdx = getZhiIdx(hourZhi);
let mingPos = (startZhi + (month - 1) - hourIdx + 12) % 12;
let shenPos = (startZhi + (month - 1) + hourIdx) % 12;
return { mingPos, shenPos };
};
const getBureau = (mingGan, mingZhi) => {
const mingGanIdx = getGanIdx(mingGan);
const mingZhiIdx = getZhiIdx(mingZhi);
const elementMap = [
[4, 2, 6, 5, 3], [2, 6, 5, 3, 4], [6, 5, 3, 4, 2], [5, 3, 4, 2, 6], [3, 4, 2, 6, 5]
];
const row = Math.floor(mingGanIdx / 2);
const col = Math.floor(mingZhiIdx / 2) % 5;
return elementMap[row][col];
};
const getZiweiPos = (bureau, day) => {
let pos = 2;
let quotient, remainder;
if (day % bureau === 0) {
quotient = day / bureau;
remainder = 0;
} else {
quotient = Math.floor(day / bureau) + 1;
remainder = day % bureau;
}
let basePos = (2 + (quotient - 1)) % 12;
if (remainder === 0) {
pos = basePos;
} else {
const makeup = bureau - remainder;
if (makeup % 2 === 0) pos = (basePos + makeup) % 12;
else pos = (basePos - makeup + 12) % 12;
}
return pos;
};
const getTianfuPos = (ziweiPos) => {
const map = {0:4, 1:3, 2:2, 3:1, 4:0, 5:11, 6:10, 7:9, 8:8, 9:7, 10:6, 11:5};
return map[ziweiPos];
};
const getChangQu = (hourZhi) => {
const hIdx = getZhiIdx(hourZhi);
return { chang: (10 - hIdx + 12) % 12, qu: (4 + hIdx) % 12 };
};
const getZuoYou = (month) => {
return { zuo: (4 + (month - 1)) % 12, you: (10 - (month - 1) + 12) % 12 };
};
const getDaXian = (mingPos, bureau, gender, yearGan) => {
const yearGanIdx = getGanIdx(yearGan);
const isYangYear = yearGanIdx % 2 === 0;
const isMale = gender === 'M';
let isClockwise = false;
if ((isMale && isYangYear) || (!isMale && !isYangYear)) isClockwise = true;
const ranges = [];
for (let i = 0; i < 12; i++) {
let pos = isClockwise ? (mingPos + i) % 12 : (mingPos - i + 12) % 12;
let startAge = bureau + (i * 10);
let endAge = startAge + 9;
ranges.push({ pos, text: `${startAge}-${endAge}` });
}
return ranges;
};
// --- 主程式組件 ---
function ZwdsApp() {
const [inputData, setInputData] = useState({
name: '某人', gender: 'M', lunarYear: 1990, lunarMonth: 1, lunarDay: 15,
birthHour: '子', yearGan: '庚', yearZhi: '午', currentYear: new Date().getFullYear(),
});
const [chartData, setChartData] = useState(null);
const [showPrintMode, setShowPrintMode] = useState(false);
const calculateGanZhiYear = (year) => {
const gan = TIAN_GAN[(year - 4) % 10];
const zhi = DI_ZHI[(year - 4) % 12];
return { gan, zhi };
};
const handleGenerate = () => {
const { lunarMonth, lunarDay, birthHour, yearGan, yearZhi, gender } = inputData;
const { mingPos, shenPos } = getMingShen(parseInt(lunarMonth), birthHour);
const yearGanIdx = getGanIdx(yearGan);
const mingPalaceGan = getMonthGan(yearGanIdx, DI_ZHI[mingPos]);
const bureauVal = getBureau(mingPalaceGan, DI_ZHI[mingPos]);
const bureauName = FIVE_ELEMENTS[bureauVal];
const zwPos = getZiweiPos(bureauVal, parseInt(lunarDay));
const tfPos = getTianfuPos(zwPos);
const { chang, qu } = getChangQu(birthHour);
const { zuo, you } = getZuoYou(parseInt(lunarMonth));
const daXian = getDaXian(mingPos, bureauVal, gender, yearGan);
const cells = Array(12).fill(null).map((_, idx) => ({
id: idx, zhi: DI_ZHI[idx], gan: getMonthGan(yearGanIdx, DI_ZHI[idx]),
stars: [], minorStars: [], name: '', isShen: idx === shenPos, daXian: '', liuNian: false,
}));
for (let i = 0; i < 12; i++) {
const palaceIdx = (mingPos - i + 12) % 12;
cells[palaceIdx].name = PALACE_NAMES[i];
}
daXian.forEach(d => { cells[d.pos].daXian = d.text; });
ZIWEI_SERIES.forEach((star, i) => {
if (star) {
const pos = (zwPos - i + 12) % 12;
cells[pos].stars.push({ name: star, type: 'major', group: 'ziwei' });
}
});
TIANFU_SERIES.forEach((star, i) => {
if (star) {
const pos = (tfPos + i) % 12;
cells[pos].stars.push({ name: star, type: 'major', group: 'tianfu' });
}
});
cells[chang].minorStars.push({ name: '文昌', type: 'good' });
cells[qu].minorStars.push({ name: '文曲', type: 'good' });
cells[zuo].minorStars.push({ name: '左輔', type: 'good' });
cells[you].minorStars.push({ name: '右弼', type: 'good' });
const luCunMap = {'甲':2, '乙':3, '丙':5, '丁':6, '戊':5, '己':6, '庚':8, '辛':9, '壬':11, '癸':0};
const luPos = luCunMap[yearGan];
if (luPos !== undefined) cells[luPos].minorStars.push({name: '祿存', type: 'good'});
if (luPos !== undefined) {
cells[(luPos + 1) % 12].minorStars.push({name: '擎羊', type: 'bad'});
cells[(luPos - 1 + 12) % 12].minorStars.push({name: '陀羅', type: 'bad'});
}
const siHuaYear = SI_HUA[yearGan];
cells.forEach(cell => {
cell.stars.forEach(star => {
Object.entries(siHuaYear).forEach(([hua, starName]) => {
if (star.name === starName) {
star.hua = hua;
star.huaType = 'year';
}
});
});
});
setChartData({ cells, info: { bureau: bureauName, mingGan: mingPalaceGan, mingZhi: DI_ZHI[mingPos], mingPos: mingPos } });
};
useEffect(() => {
const gz = calculateGanZhiYear(inputData.lunarYear);
setInputData(prev => ({...prev, yearGan: gz.gan, yearZhi: gz.zhi}));
}, [inputData.lunarYear]);
const getLiuNianData = () => {
if (!chartData) return null;
const currentGZ = calculateGanZhiYear(inputData.currentYear);
const liuNianZhiIdx = getZhiIdx(currentGZ.zhi);
const newCells = JSON.parse(JSON.stringify(chartData.cells));
newCells[liuNianZhiIdx].isLiuNianMing = true;
const siHuaLiu = SI_HUA[currentGZ.gan];
newCells.forEach(cell => {
cell.stars.forEach(star => {
Object.entries(siHuaLiu).forEach(([hua, starName]) => {
if (star.name === starName) star.liuHua = hua;
});
});
cell.minorStars.forEach(star => {
Object.entries(siHuaLiu).forEach(([hua, starName]) => {
if (star.name === starName) star.liuHua = hua;
});
});
});
return { cells: newCells, gan: currentGZ.gan, zhi: currentGZ.zhi };
};
const renderData = showPrintMode || chartData ? (getLiuNianData() || chartData) : null;
const displayCells = renderData ? renderData.cells : [];
const gridMapping = [
{ zhiIdx: 5, r: 1, c: 1 }, { zhiIdx: 6, r: 1, c: 2 }, { zhiIdx: 7, r: 1, c: 3 }, { zhiIdx: 8, r: 1, c: 4 },
{ zhiIdx: 4, r: 2, c: 1 }, { zhiIdx: 9, r: 2, c: 4 },
{ zhiIdx: 3, r: 3, c: 1 }, { zhiIdx: 10, r: 3, c: 4 },
{ zhiIdx: 2, r: 4, c: 1 }, { zhiIdx: 1, r: 4, c: 2 }, { zhiIdx: 0, r: 4, c: 3 }, { zhiIdx: 11, r: 4, c: 4 },
];
const renderCell = (zhiIdx) => {
const cell = displayCells[zhiIdx];
if (!cell) return null;
return (
<div className={`relative h-full border border-stone-400 bg-stone-50 p-1 flex flex-col justify-between print:border-stone-800 ${cell.isLiuNianMing ? 'bg-yellow-50 ring-2 ring-yellow-400 ring-inset print:ring-0 print:bg-stone-50' : ''}`}>
<div className="flex flex-wrap gap-0.5 text-[10px] text-stone-500 leading-tight">
{cell.minorStars.map((s, i) => (
<span key={i} className={`${s.type === 'bad' ? 'text-red-400' : 'text-blue-400'} flex items-center`}>
{s.name}
{s.liuHua && <span className="ml-[1px] text-[8px] bg-red-600 text-white px-[1px] rounded">{s.liuHua}</span>}
</span>
))}
</div>
<div className="flex flex-col items-center justify-center gap-1 my-1">
{cell.stars.map((star, i) => (
<div key={i} className={`font-bold text-lg writing-vertical-rl tracking-widest ${star.group === 'ziwei' ? 'text-purple-700' : 'text-indigo-700'} relative`}>
{star.name}
{star.hua && (
<span className={`absolute -right-3 top-2 text-[10px] rounded-full px-1 text-white w-4 h-4 flex items-center justify-center ${star.hua === '祿' ? 'bg-green-600' : star.hua === '權' ? 'bg-red-600' : star.hua === '科' ? 'bg-blue-600' : 'bg-stone-800'}`}>
{star.hua}
</span>
)}
{star.liuHua && (
<span className={`absolute -left-3 top-4 text-[10px] rounded-full px-1 text-white w-4 h-4 flex items-center justify-center border border-white shadow-sm z-10 ${star.liuHua === '祿' ? 'bg-green-500' : star.liuHua === '權' ? 'bg-red-500' : star.liuHua === '科' ? 'bg-blue-500' : 'bg-black'}`}>
{star.liuHua}
</span>
)}
</div>
))}
{cell.stars.length === 0 && <span className="text-stone-300 text-xs py-4">空宮</span>}
</div>
<div className="mt-auto">
<div className="flex justify-between items-end border-t border-stone-200 pt-1">
<div className="flex flex-col items-start">
<span className="text-[10px] font-mono text-stone-400">{cell.gan}</span>
<span className="text-sm font-bold text-red-800">{cell.zhi}</span>
</div>
<div className="flex flex-col items-center">
{cell.isShen && <span className="text-[10px] bg-stone-200 px-1 rounded text-stone-600 mb-0.5">身宮</span>}
{cell.isLiuNianMing && <span className="text-[10px] bg-yellow-200 px-1 rounded text-stone-700 mb-0.5 print:border print:border-stone-800">流命</span>}
<span className="font-serif text-base bg-red-50 px-1 text-red-900 rounded print:bg-transparent print:text-black">{cell.name}</span>
</div>
<div className="flex flex-col items-end">
<span className="text-[9px] text-stone-400">大限</span>
<span className="text-xs font-mono text-stone-600">{cell.daXian}</span>
</div>
</div>
</div>
</div>
);
};
return (
<div className="min-h-screen font-sans pb-10 print:pb-0">
{/* Header */}
<div className="bg-purple-900 text-white p-4 shadow-md print-hidden">
<div className="max-w-5xl mx-auto flex justify-between items-center">
<h1 className="text-xl font-bold flex items-center gap-2">
<Moon size={20} /> 信陵文化斗數排盤 (南派)
</h1>
<div className="flex gap-3">
<button onClick={() => window.print()} className="flex items-center gap-1 bg-purple-700 hover:bg-purple-600 px-3 py-1.5 rounded text-sm transition-colors">
<Printer size={16} /> 列印 / 存為PDF
</button>
</div>
</div>
</div>
<div className="max-w-5xl mx-auto mt-6 px-4 print:px-0 print:mt-0">
{/* Input Section */}
<div className="bg-white p-6 rounded-xl shadow-sm mb-6 border border-stone-200 print-hidden">
<div className="flex items-center gap-2 mb-4 border-b pb-2 border-stone-100">
<Settings size={18} className="text-stone-400" />
<h2 className="font-bold text-stone-700">命盤設定</h2>
</div>
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
<div className="space-y-1">
<label className="text-xs font-bold text-stone-500">姓名</label>
<input type="text" value={inputData.name} onChange={(e) => setInputData({...inputData, name: e.target.value})} className="w-full border border-stone-300 rounded px-2 py-1.5 focus:outline-none focus:border-purple-500" />
</div>
<div className="space-y-1">
<label className="text-xs font-bold text-stone-500">性別</label>
<select value={inputData.gender} onChange={(e) => setInputData({...inputData, gender: e.target.value})} className="w-full border border-stone-300 rounded px-2 py-1.5">
<option value="M">男</option>
<option value="F">女</option>
</select>
</div>
<div className="space-y-1">
<label className="text-xs font-bold text-stone-500">農曆生年 (西元)</label>
<input type="number" value={inputData.lunarYear} onChange={(e) => setInputData({...inputData, lunarYear: parseInt(e.target.value)})} className="w-full border border-stone-300 rounded px-2 py-1.5" />
</div>
<div className="space-y-1">
<label className="text-xs font-bold text-stone-500">農曆月/日</label>
<div className="flex gap-2">
<select className="flex-1 border border-stone-300 rounded px-2 py-1.5" value={inputData.lunarMonth} onChange={(e) => setInputData({...inputData, lunarMonth: e.target.value})}>
{Array.from({length: 12}, (_, i) => i + 1).map(m => <option key={m} value={m}>{m}月</option>)}
</select>
<select className="flex-1 border border-stone-300 rounded px-2 py-1.5" value={inputData.lunarDay} onChange={(e) => setInputData({...inputData, lunarDay: e.target.value})}>
{Array.from({length: 30}, (_, i) => i + 1).map(d => <option key={d} value={d}>{d}日</option>)}
</select>
</div>
</div>
<div className="space-y-1">
<label className="text-xs font-bold text-stone-500">生時 (地支)</label>
<select value={inputData.birthHour} onChange={(e) => setInputData({...inputData, birthHour: e.target.value})} className="w-full border border-stone-300 rounded px-2 py-1.5">
{DI_ZHI.map(z => <option key={z} value={z}>{z}時</option>)}
</select>
</div>
<div className="space-y-1">
<label className="text-xs font-bold text-stone-500">生年干支 (自動/手動)</label>
<div className="flex gap-1">
<select value={inputData.yearGan} onChange={(e) => setInputData({...inputData, yearGan: e.target.value})} className="w-1/2 border rounded px-1">
{TIAN_GAN.map(g => <option key={g} value={g}>{g}</option>)}
</select>
<select value={inputData.yearZhi} onChange={(e) => setInputData({...inputData, yearZhi: e.target.value})} className="w-1/2 border rounded px-1">
{DI_ZHI.map(z => <option key={z} value={z}>{z}</option>)}
</select>
</div>
</div>
<div className="col-span-1 md:col-span-2 flex items-end">
<button onClick={handleGenerate} className="w-full bg-purple-700 hover:bg-purple-800 text-white font-bold py-2 px-4 rounded transition-colors shadow-sm">起盤 / 更新</button>
</div>
</div>
<div className="mt-4 pt-4 border-t border-stone-100 text-xs text-stone-500 flex gap-2 items-center">
<Info size={14} />
<span>註:本系統採用南派設定。為求精確,請直接輸入農曆生日,系統不會自動進行節氣換算。</span>
</div>
</div>
{/* Chart Display */}
{displayCells.length > 0 && (
<div className="bg-white shadow-2xl print:shadow-none max-w-4xl mx-auto aspect-square md:aspect-auto md:h-[900px] print:h-[260mm] print:w-[190mm] flex flex-col relative overflow-hidden border-4 border-stone-800 print:border-2 print:mt-0">
<div className="grid grid-rows-4 grid-cols-4 h-full w-full">
{gridMapping.map((map) => (
<div key={map.zhiIdx} style={{ gridRow: map.r, gridColumn: map.c }} className="w-full h-full">
{renderCell(map.zhiIdx)}
</div>
))}
<div className="row-start-2 row-span-2 col-start-2 col-span-2 flex flex-col p-6 print:p-4 justify-center border border-stone-200 no-print-border">
<div className="text-center mb-6">
<h2 className="text-3xl font-serif font-bold text-stone-800 tracking-widest mb-2">{inputData.name} 命盤</h2>
<div className="h-px w-24 bg-red-800 mx-auto"></div>
</div>
<div className="grid grid-cols-2 gap-4 text-sm text-stone-700 font-serif">
<div className="text-right text-stone-500">農曆生辰:</div>
<div className="font-bold">{inputData.yearGan}{inputData.yearZhi} 年 {inputData.lunarMonth} 月 {inputData.lunarDay} 日 {inputData.birthHour} 時</div>
<div className="text-right text-stone-500">五行局:</div>
<div className="font-bold text-red-800">{chartData?.info.bureau}</div>
<div className="text-right text-stone-500">命主:</div>
<div className="font-bold">{inputData.gender === 'M' ? '乾造' : '坤造'}</div>
</div>
<div className="mt-8 border-t border-stone-200 pt-4">
<div className="flex flex-col items-center gap-2">
<div className="text-xs font-bold text-stone-400 uppercase tracking-widest print-hidden">Current Flow</div>
<div className="flex items-center gap-4">
<button onClick={() => setInputData(p => ({...p, currentYear: p.currentYear - 1}))} className="print-hidden p-1 rounded-full hover:bg-stone-100">←</button>
<div className="text-xl font-bold text-purple-800 border-b-2 border-purple-200 px-2">流年 {renderData.gan}{renderData.zhi} ({inputData.currentYear})</div>
<button onClick={() => setInputData(p => ({...p, currentYear: p.currentYear + 1}))} className="print-hidden p-1 rounded-full hover:bg-stone-100">→</button>
</div>
<p className="text-[10px] text-stone-400 mt-1 print-hidden">切換年份查看流年四化及命宮位置</p>
</div>
</div>
<div className="mt-auto text-center opacity-30">
<span className="font-serif text-4xl">信陵文化</span>
</div>
</div>
</div>
</div>
)}
</div>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<ZwdsApp />);
</script>
</body>
</html>