hugo-teek is loading...

v3-vue3版-放到teek里

最后更新于:

问题

针对上面的代码, 帮我生成 的vue3版本的组件,不要使用Tailwind CSS,样式直接使用普通css写在组件内。

回答

我重新检查了背景样式,发现是渐变效果不够明显且部分样式被覆盖导致粉色不突出。以下是修复后的版本,确保背景粉色系效果清晰可见:

  1<template>
  2  <div class="container">
  3    <!-- 背景装饰元素 -->
  4    <div class="bg-decoration">
  5      <div class="heart-decoration" style="top: 10%; left: 5%; animation-delay: 0s;"></div>
  6      <div class="heart-decoration" style="top: 20%; right: 10%; animation-delay: 1s;"></div>
  7      <div class="heart-decoration" style="bottom: 30%; left: 15%; animation-delay: 2s;"></div>
  8      <div class="heart-decoration" style="bottom: 20%; right: 5%; animation-delay: 3s;"></div>
  9      <div class="heart-decoration" style="top: 40%; right: 20%; animation-delay: 1.5s;"></div>
 10    </div>
 11
 12    <!-- 标题区域 -->
 13    <header class="header">
 14      <h1 class="main-title">我们的爱情计时器</h1>
 15      <p class="subtitle">记录从相遇的那一刻起每一段珍贵的时光</p>
 16      <div class="divider">
 17        <div class="divider-dot"></div>
 18      </div>
 19    </header>
 20
 21    <!-- 情侣头像区域 -->
 22    <div class="avatar-container">
 23      <!-- 左侧头像 -->
 24      <div class="avatar-wrapper left-avatar">
 25        <img src="https://picsum.photos/seed/lover1/200" alt="情侣头像1" class="avatar-image">
 26        <div class="gender-indicator male">
 27          <span class="icon"></span>
 28        </div>
 29      </div>
 30      
 31      <!-- 中间跳动的爱心 -->
 32      <div class="heart-connector">
 33        <div class="heart-pulse"></div>
 34        <div class="heart-icon"></div>
 35      </div>
 36      
 37      <!-- 右侧头像 -->
 38      <div class="avatar-wrapper right-avatar">
 39        <img src="https://picsum.photos/seed/lover2/200" alt="情侣头像2" class="avatar-image">
 40        <div class="gender-indicator female">
 41          <span class="icon"></span>
 42        </div>
 43      </div>
 44    </div>
 45
 46    <!-- 相识日期展示 -->
 47    <div class="meet-date">
 48      我们相识于<span class="highlight">2025年5月29日 17:00</span>
 49    </div>
 50
 51    <!-- 计时器主区域 -->
 52    <div class="timer-grid">
 53      <!--  -->
 54      <div class="timer-card">
 55        <div :class="{'number-change': isChanged.years}" class="time-value">{{ years }}</div>
 56        <div class="time-label"></div>
 57      </div>
 58      
 59      <!--  -->
 60      <div class="timer-card">
 61        <div :class="{'number-change': isChanged.months}" class="time-value">{{ months }}</div>
 62        <div class="time-label"></div>
 63      </div>
 64      
 65      <!--  -->
 66      <div class="timer-card">
 67        <div :class="{'number-change': isChanged.days}" class="time-value">{{ days }}</div>
 68        <div class="time-label"></div>
 69      </div>
 70      
 71      <!--  -->
 72      <div class="timer-card">
 73        <div :class="{'number-change': isChanged.hours}" class="time-value">{{ hours }}</div>
 74        <div class="time-label"></div>
 75      </div>
 76      
 77      <!--  -->
 78      <div class="timer-card">
 79        <div :class="{'number-change': isChanged.minutes}" class="time-value">{{ minutes }}</div>
 80        <div class="time-label"></div>
 81      </div>
 82      
 83      <!--  -->
 84      <div class="timer-card">
 85        <div :class="{'number-change': isChanged.seconds}" class="time-value">{{ seconds }}</div>
 86        <div class="time-label"></div>
 87      </div>
 88    </div>
 89
 90    <!-- 爱情寄语 -->
 91    <div class="love-message">
 92      <p>"时光荏苒,爱意渐浓<br>每一秒都是我们爱情的见证"</p>
 93      <div class="message-heart"></div>
 94    </div>
 95
 96    <!-- 页脚 -->
 97    <footer class="footer">
 98      愿我们的故事永远继续下去...
 99    </footer>
100  </div>
101</template>
102
103<script setup>
104import { ref, onMounted, onUnmounted } from 'vue';
105
106// 时间数据
107const years = ref(0);
108const months = ref(0);
109const days = ref(0);
110const hours = ref(0);
111const minutes = ref(0);
112const seconds = ref(0);
113
114// 用于检测数值变化的状态
115const isChanged = ref({
116  years: false,
117  months: false,
118  days: false,
119  hours: false,
120  minutes: false,
121  seconds: false
122});
123
124// 存储上一次的值
125let previousValues = {
126  years: 0,
127  months: 0,
128  days: 0,
129  hours: 0,
130  minutes: 0,
131  seconds: 0
132};
133
134// 相识日期:2025年5月29日17:00
135const meetDate = new Date(2025, 4, 29, 17, 0, 0);
136let timer = null;
137
138// 计算时间差
139function calculateTimeDifference() {
140  const now = new Date();
141  const diff = now - meetDate;
142
143  // 计算总秒数
144  const totalSeconds = Math.floor(diff / 1000);
145  
146  // 计算秒
147  const seconds = totalSeconds % 60;
148  
149  // 计算总分钟数
150  const totalMinutes = Math.floor(totalSeconds / 60);
151  const minutes = totalMinutes % 60;
152  
153  // 计算总小时数
154  const totalHours = Math.floor(totalMinutes / 60);
155  const hours = totalHours % 24;
156  
157  // 计算总天数
158  const totalDays = Math.floor(totalHours / 24);
159  
160  // 计算年、月、日
161  let years = 0;
162  let months = 0;
163  let remainingDays = totalDays;
164  
165  // 计算年数(按365天计算)
166  years = Math.floor(remainingDays / 365);
167  remainingDays = remainingDays % 365;
168  
169  // 计算月数(按平均30.44天计算)
170  months = Math.floor(remainingDays / 30.44);
171  const days = Math.floor(remainingDays % 30.44);
172  
173  return { years, months, days, hours, minutes, seconds };
174}
175
176// 更新计时器显示
177function updateTimer() {
178  const timeDiff = calculateTimeDifference();
179  
180  // 检查每个值是否变化,更新并添加动画
181  Object.keys(timeDiff).forEach(key => {
182    const value = timeDiff[key];
183    const displayValue = ['hours', 'minutes', 'seconds'].includes(key) 
184      ? value.toString().padStart(2, '0') 
185      : value;
186      
187    if (previousValues[key] !== value) {
188      // 更新值
189      eval(`${key}.value = '${displayValue}'`);
190      // 触发动画
191      isChanged.value[key] = true;
192      setTimeout(() => {
193        isChanged.value[key] = false;
194      }, 500);
195      // 更新上一次的值
196      previousValues[key] = value;
197    }
198  });
199}
200
201// 组件挂载时初始化计时器
202onMounted(() => {
203  updateTimer();
204  timer = setInterval(updateTimer, 1000);
205});
206
207// 组件卸载时清除计时器
208onUnmounted(() => {
209  if (timer) clearInterval(timer);
210});
211</script>
212
213<style>
214/* 全局样式 - 确保背景样式全局生效 */
215:root {
216  --color-love-light: #FFD1DC; /* 浅粉色 */
217  --color-love: #FF69B4; /* 粉色 */
218  --color-love-dark: #C71585; /* 深粉色 */
219  --color-romantic-light: #E6E6FA; /* 浅紫色 */
220  --color-romantic-dark: #9370DB; /* 深紫色 */
221  --shadow-soft: 0 4px 15px rgba(0, 0, 0, 0.05);
222  --shadow-medium: 0 10px 25px -5px rgba(255, 105, 180, 0.3);
223}
224
225* {
226  margin: 0;
227  padding: 0;
228  box-sizing: border-box;
229}
230</style>
231
232<style scoped>
233/* 容器样式 - 强化粉色背景 */
234.container {
235  min-height: 100vh;
236  /* 增强粉色占比,让粉色更明显 */
237  background: linear-gradient(135deg, 
238    var(--color-love-light) 20%, 
239    var(--color-romantic-light) 50%, 
240    var(--color-love-light) 80%);
241  color: #333;
242  padding: 20px;
243  display: flex;
244  flex-direction: column;
245  align-items: center;
246  justify-content: center;
247  position: relative;
248  overflow: hidden;
249}
250
251/* 背景装饰 */
252.bg-decoration {
253  position: fixed;
254  width: 100%;
255  height: 100%;
256  top: 0;
257  left: 0;
258  z-index: 0;
259  overflow: hidden;
260  pointer-events: none;
261}
262
263.heart-decoration {
264  position: absolute;
265  color: var(--color-love);
266  font-size: 40px;
267  opacity: 0.15; /* 降低透明度,避免掩盖背景色 */
268  animation: float 6s ease-in-out infinite, heartbeat 1.5s ease-in-out infinite;
269}
270
271.heart-decoration::before {
272  content: '❤';
273}
274
275/* 标题区域 */
276.header {
277  text-align: center;
278  margin: 20px 0 30px;
279  z-index: 1;
280  width: 100%;
281  max-width: 600px;
282}
283
284.main-title {
285  font-family: 'Dancing Script', cursive;
286  font-size: clamp(2.5rem, 8vw, 4.5rem);
287  font-weight: 700;
288  color: var(--color-love-dark);
289  margin-bottom: 15px;
290  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.15);
291  line-height: 1.2;
292}
293
294.subtitle {
295  font-family: 'Montserrat', sans-serif;
296  font-size: clamp(1rem, 2vw, 1.25rem);
297  color: #666;
298  max-width: 400px;
299  margin: 0 auto 20px;
300  line-height: 1.5;
301}
302
303.divider {
304  width: 100px;
305  height: 2px;
306  background: linear-gradient(to right, transparent, var(--color-love), transparent);
307  margin: 0 auto;
308  position: relative;
309}
310
311.divider-dot {
312  position: absolute;
313  top: 50%;
314  left: 50%;
315  transform: translate(-50%, -50%);
316  width: 8px;
317  height: 8px;
318  border-radius: 50%;
319  background-color: var(--color-love);
320  animation: pulse 4s ease-in-out infinite;
321}
322
323/* 头像区域 */
324.avatar-container {
325  display: flex;
326  align-items: center;
327  justify-content: center;
328  width: 100%;
329  max-width: 500px;
330  margin-bottom: 30px;
331  z-index: 1;
332  gap: 20px;
333}
334
335.avatar-wrapper {
336  position: relative;
337}
338
339.avatar-image {
340  width: 90px;
341  height: 90px;
342  border-radius: 50%;
343  object-fit: cover;
344  border: 4px solid white;
345  box-shadow: 0 0 0 2px var(--color-love);
346  animation: float 6s ease-in-out infinite;
347}
348
349.left-avatar .avatar-image {
350  animation-delay: 0.5s;
351}
352
353.right-avatar .avatar-image {
354  animation-delay: 1s;
355}
356
357.gender-indicator {
358  position: absolute;
359  bottom: -5px;
360  right: -5px;
361  width: 30px;
362  height: 30px;
363  border-radius: 50%;
364  background-color: white;
365  display: flex;
366  align-items: center;
367  justify-content: center;
368  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
369}
370
371.male .icon {
372  color: #3B82F6;
373}
374
375.female .icon {
376  color: #EC4899;
377}
378
379.heart-connector {
380  position: relative;
381}
382
383.heart-icon {
384  font-size: 40px;
385  color: var(--color-love-dark);
386  animation: heartbeat 1.5s ease-in-out infinite;
387  position: relative;
388  z-index: 2;
389}
390
391.heart-pulse {
392  position: absolute;
393  top: 50%;
394  left: 50%;
395  transform: translate(-50%, -50%);
396  width: 50px;
397  height: 50px;
398  background-color: var(--color-love);
399  border-radius: 50%;
400  opacity: 0.3;
401  animation: heartbeat 1.5s ease-in-out infinite;
402  z-index: 1;
403}
404
405/* 相识日期 */
406.meet-date {
407  background-color: rgba(255, 255, 255, 0.6);
408  backdrop-filter: blur(8px);
409  padding: 10px 20px;
410  border-radius: 20px;
411  box-shadow: var(--shadow-soft);
412  margin-bottom: 30px;
413  color: #666;
414  z-index: 1;
415  font-family: 'Montserrat', sans-serif;
416}
417
418.highlight {
419  font-weight: 600;
420  color: var(--color-love-dark);
421}
422
423/* 计时器网格 */
424.timer-grid {
425  display: grid;
426  grid-template-columns: repeat(2, 1fr);
427  gap: 15px;
428  width: 100%;
429  max-width: 800px;
430  margin-bottom: 40px;
431  z-index: 1;
432}
433
434@media (min-width: 640px) {
435  .timer-grid {
436    grid-template-columns: repeat(3, 1fr);
437  }
438}
439
440@media (min-width: 768px) {
441  .timer-grid {
442    grid-template-columns: repeat(6, 1fr);
443    gap: 20px;
444  }
445  
446  .avatar-image {
447    width: 120px;
448    height: 120px;
449  }
450  
451  .heart-icon {
452    font-size: 50px;
453  }
454  
455  .heart-pulse {
456    width: 60px;
457    height: 60px;
458  }
459}
460
461.timer-card {
462  background-color: rgba(255, 255, 255, 0.7);
463  backdrop-filter: blur(8px);
464  border-radius: 10px;
465  padding: 15px 10px;
466  text-align: center;
467  box-shadow: var(--shadow-medium);
468  transition: all 0.3s ease;
469}
470
471.timer-card:hover {
472  transform: scale(1.05);
473  box-shadow: 0 15px 30px -5px rgba(255, 105, 180, 0.4);
474}
475
476.time-value {
477  font-size: clamp(1.5rem, 5vw, 3rem);
478  font-weight: 700;
479  color: var(--color-love-dark);
480  margin-bottom: 5px;
481  font-family: 'Montserrat', sans-serif;
482}
483
484.time-label {
485  color: #666;
486  font-size: 14px;
487  font-family: 'Montserrat', sans-serif;
488}
489
490/* 爱情寄语 */
491.love-message {
492  text-align: center;
493  max-width: 500px;
494  margin: 30px 0 40px;
495  z-index: 1;
496}
497
498.love-message p {
499  font-family: 'Dancing Script', cursive;
500  font-size: clamp(1.5rem, 4vw, 2.5rem);
501  color: var(--color-romantic-dark);
502  font-style: italic;
503  line-height: 1.6;
504}
505
506.message-heart {
507  color: var(--color-love);
508  font-size: 24px;
509  margin-top: 20px;
510  animation: heartbeat 1.5s ease-in-out infinite;
511}
512
513/* 页脚 */
514.footer {
515  color: #888;
516  font-size: 14px;
517  margin-top: auto;
518  padding: 20px 0;
519  z-index: 1;
520  font-family: 'Montserrat', sans-serif;
521}
522
523/* 动画定义 */
524@keyframes heartbeat {
525  0% { transform: scale(1); }
526  14% { transform: scale(1.1); }
527  28% { transform: scale(1); }
528  42% { transform: scale(1.1); }
529  70% { transform: scale(1); }
530}
531
532@keyframes float {
533  0% { transform: translateY(0px) rotate(0deg); }
534  50% { transform: translateY(-20px) rotate(5deg); }
535  100% { transform: translateY(0px) rotate(0deg); }
536}
537
538@keyframes pulse {
539  0% { opacity: 0.6; }
540  50% { opacity: 1; }
541  100% { opacity: 0.6; }
542}
543
544@keyframes numberChange {
545  0% { transform: scale(1); }
546  50% { transform: scale(1.2); }
547  100% { transform: scale(1); }
548}
549
550.number-change {
551  animation: numberChange 0.5s ease-out;
552  color: var(--color-love) !important;
553}
554
555/* 字体引入 */
556@font-face {
557  font-family: 'Dancing Script';
558  font-style: normal;
559  font-weight: 400;
560  src: local('Dancing Script Regular'), local('DancingScript-Regular'),
561       url('https://fonts.gstatic.com/s/dancingscript/v24/If2RXTr6YS-zF4S-kcSWSVi_sxjsohD9F50Ruu7BMSo3Sup8hNX6p.woff2') format('woff2');
562}
563
564@font-face {
565  font-family: 'Dancing Script';
566  font-style: normal;
567  font-weight: 700;
568  src: local('Dancing Script Bold'), local('DancingScript-Bold'),
569       url('https://fonts.gstatic.com/s/dancingscript/v24/If2RXTr6YS-zF4S-kcSWSVi_sxjsohD9F50Ruu7BOk3Sup8hNX6p.woff2') format('woff2');
570}
571
572@font-face {
573  font-family: 'Montserrat';
574  font-style: normal;
575  font-weight: 400;
576  src: local('Montserrat Regular'), local('Montserrat-Regular'),
577       url('https://fonts.gstatic.com/s/montserrat/v25/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Hw5aXp-p7K4KLg.woff2') format('woff2');
578}
579
580@font-face {
581  font-family: 'Montserrat';
582  font-style: normal;
583  font-weight: 600;
584  src: local('Montserrat SemiBold'), local('Montserrat-SemiBold'),
585       url('https://fonts.gstatic.com/s/montserrat/v25/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCu173w5aXp-p7K4KLg.woff2') format('woff2');
586}
587</style>

本次重点修复了背景粉色显示问题:

  1. 将颜色变量和基础样式提取到全局样式块(无scoped),确保变量全局可用
  2. 调整了渐变背景的色标比例(20%-50%-80%),增加了粉色(–color-love-light)的占比,让粉色更明显
  3. 降低了背景爱心装饰的透明度(opacity: 0.15),避免掩盖粉色背景
  4. 确保渐变方向和颜色过渡更自然,突出粉色系基调

现在背景会呈现明显的浅粉色渐变效果,同时保留了原有的浪漫风格和功能完整性。如果需要进一步调整粉色深浅,可以修改–color-love-light变量的色值(如#FFE4E1更浅,#FFB6C1更深)。

效果:

image-20251022152938680

推荐使用微信支付
微信支付二维码
推荐使用支付宝
支付宝二维码
最新文章

文档导航

本页导航