
列星随行,日月递炤,四时代御,阴阳大化,风雨博施,万物各得其和以生,各得其养以成
<script>
new Vue({
el: '#app',
data: {
hundredDays: Array.from({ length: 100 }, (_, i) => ({
day: i + 1,
checked: [1].includes(i + 1)
})),
habits: [
{ day: '01', streak: 1, time: '2025-11-5' },
]
},
methods: {
toggleDay(index) {
this.hundredDays[index].checked = !this.hundredDays[index].checked;
}
}
})
</script>
<!-- run -->
<style>
#app {
margin: 0 auto;
padding: 20px;
background: #fff;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}
.postBody {
padding: 0px 20px !important;
}
.container {
width: 100%;
text-align: center;
margin: 0 auto 20px;
padding: 0 5px;
}
h1 {
font-size: 1.5rem;
margin: 0 0 10px 0;
color: #2c3e50;
}
#cnblogs_post_body h3 {
margin: 0 !important;
}
.subtitle {
font-size: 0.85rem;
color: #7f8c8d;
margin: 0 0 15px 0;
}
.grid {
display: grid;
grid-template-columns: repeat(15, 1fr);
gap: 12px;
justify-content: center;
width: min(740px, 95vw); /* 稍微加宽容器,容纳更大的按钮 */
margin: 0 auto;
padding: 10px;
box-sizing: border-box;
}
.day {
width: 100%;
aspect-ratio: 1 / 1;
min-width: 50px; /* ← 增大 */
max-width: 50px; /* ← 增大 */
background-color: #ffffff;
border: 1px solid #e1e8ed;
border-radius: 10px; /* ← 稍大圆角,更柔和 */
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 11px; /* ← 字体稍大,更清晰 */
color: #95a5a6;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.06); /* ← 阴影稍强 */
transition: all 0.25s ease;
cursor: pointer;
}
.day.checked {
background-color: #a8e6cf;
border-color: #88d1b0;
color: #2c6e49;
box-shadow: 0 3px 6px rgba(168, 230, 207, 0.5);
}
.day:not(.checked):hover {
background-color: #f9fbfa;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12);
border-color: #cbd5e0;
}
.footer {
margin-top: 15px;
font-size: 0.75rem;
color: #95a5a6;
}
.waterfall-container {
columns: 3 280px;
column-gap: 15px;
margin: 20px auto;
padding: 0 15px;
box-sizing: border-box;
}
.habit-card {
background: #e8f5e9;
border: 2px dashed #8bc34a;
border-radius: 10px;
padding: 12px 15px;
margin-bottom: 15px;
break-inside: avoid;
}
.habit-title {
color: #2e7d32;
font-size: 17px;
margin: 0 0 10px;
padding-bottom: 6px;
border-bottom: 1px solid #c8e6c9;
font-weight: bold;
}
.habit-meta {
color: #666;
font-size: 0.8em;
margin-right: 8px;
display: block;
margin-bottom: 5px;
}
.streak-badge {
background: #e8f5e9;
color: #2e7d32;
padding: 1px 6px;
border-radius: 10px;
font-size: 0.75em;
font-weight: 500;
margin-left: 6px;
font-size: 11px;
}
/* 移动端适配 */
@media (max-width: 600px) {
.grid {
gap: 10px;
width: min(640px, 95vw);
}
.day {
min-width: 30px;
max-width: 42px;
font-size: 10px;
border-radius: 8px;
}
}
@media (max-width: 420px) {
.grid {
gap: 8px;
width: min(500px, 95vw);
}
.day {
min-width: 26px;
max-width: 36px;
font-size: 9px;
border-radius: 7px;
}
}
</style>
<div id="app">
<div class="container">
<p class="subtitle">坚持100天,遇见更好的自己 💪</p>
<div class="grid">
<div v-for="(item, index) in hundredDays" :key="index" :class="['day', item.checked ? 'checked' : '']"
@click="toggleDay(index)">
{{ item.day }}
</div>
</div>
<p class="footer">✅ 灰色:未打卡 | 🟢 薄荷绿:已打卡</p>
</div>
<div class="waterfall-container">
<div class="habit-card" v-for="(habit, index) in habits" :key="index">
<h3 class="habit-title">第{{ habit.day }}天打卡</h3>
<span class="habit-meta">
连续打卡 {{ habit.streak }} 天 | 打卡时间: {{ habit.time }}
<span class="streak-badge">🔥 {{ habit.streak }}天</span>
</span>
</div>
</div>
</div>