demo1.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. <template>
  2. <div class="max-w-2xl mx-auto p-6 text-center">
  3. <h1 class="text-2xl font-bold mb-6">随机名言生成器</h1>
  4. <!-- 分类选择 -->
  5. <div class="mb-6">
  6. <select
  7. v-model="selectedCategory"
  8. class="px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary"
  9. >
  10. <option value="all">所有分类</option>
  11. <option value="motivation">励志</option>
  12. <option value="life">生活</option>
  13. <option value="love">爱情</option>
  14. <option value="friendship">友情</option>
  15. <option value="success">成功</option>
  16. </select>
  17. </div>
  18. <!-- 名言卡片 -->
  19. <div
  20. v-if="currentQuote"
  21. class="bg-white rounded-xl shadow-lg p-8 mb-6 transition-opacity duration-500"
  22. :class="{ 'opacity-0': isLoading }"
  23. >
  24. <div class="text-2xl font-light mb-4 italic">
  25. "{{ currentQuote.text }}"
  26. </div>
  27. <div class="text-right font-medium">
  28. —— {{ currentQuote.author }}
  29. </div>
  30. <div class="mt-4 text-sm text-gray-500">
  31. 分类: {{ getCategoryName(currentQuote.category) }}
  32. </div>
  33. </div>
  34. <!-- 加载状态 -->
  35. <div v-if="isLoading" class="mb-6 text-gray-500">
  36. <div class="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-primary mb-2"></div>
  37. <p>加载中...</p>
  38. </div>
  39. <!-- 按钮 -->
  40. <button
  41. @click="fetchQuote"
  42. class="bg-primary text-white px-6 py-3 rounded-lg hover:bg-primary/90 transition-colors shadow-md hover:shadow-lg"
  43. >
  44. 获取新名言
  45. </button>
  46. </div>
  47. </template>
  48. <script setup lang="ts">
  49. import { ref, reactive, onMounted } from 'vue';
  50. // 名言接口
  51. interface Quote {
  52. text: string;
  53. author: string;
  54. category: QuoteCategory;
  55. }
  56. type QuoteCategory = 'motivation' | 'life' | 'love' | 'friendship' | 'success';
  57. // 模拟名言数据
  58. const mockQuotes: Quote[] = [
  59. {
  60. text: "成功不是终点,失败也并非末日,重要的是继续前进的勇气。",
  61. author: "温斯顿·丘吉尔",
  62. category: "motivation"
  63. },
  64. {
  65. text: "生活不是等待暴风雨过去,而是学会在雨中跳舞。",
  66. author: "维维安·格林",
  67. category: "life"
  68. },
  69. {
  70. text: "爱是当你遇到某个人,他的幸福比你自己的更重要。",
  71. author: "H.杰克逊·布朗",
  72. category: "love"
  73. },
  74. {
  75. text: "真正的朋友是那些在你光芒四射时出现,却在你落魄时留下的人。",
  76. author: "沃尔特·温切尔",
  77. category: "friendship"
  78. },
  79. {
  80. text: "成功就是从失败到失败,也依然不改热情。",
  81. author: "温斯顿·丘吉尔",
  82. category: "success"
  83. },
  84. {
  85. text: "不要等待机会,要创造机会。",
  86. author: "萧伯纳",
  87. category: "motivation"
  88. },
  89. {
  90. text: "生命中最美好的事情,往往是那些你从未计划过的。",
  91. author: "无名氏",
  92. category: "life"
  93. },
  94. {
  95. text: "爱情不是彼此凝视,而是一起注视同一个方向。",
  96. author: "安托万·德·圣埃克苏佩里",
  97. category: "love"
  98. },
  99. {
  100. text: "朋友是那个知道你所有缺点,却依然喜欢你的人。",
  101. author: "埃尔伯特·哈伯德",
  102. category: "friendship"
  103. },
  104. {
  105. text: "成功的秘诀在于始终如一地坚持目标。",
  106. author: "本杰明·迪斯雷利",
  107. category: "success"
  108. }
  109. ];
  110. // 状态管理
  111. const currentQuote = ref<Quote | null>(null);
  112. const isLoading = ref(false);
  113. const selectedCategory = ref<QuoteCategory | 'all'>('all');
  114. // 获取分类名称
  115. const getCategoryName = (category: QuoteCategory) => {
  116. const names: Record<QuoteCategory, string> = {
  117. motivation: '励志',
  118. life: '生活',
  119. love: '爱情',
  120. friendship: '友情',
  121. success: '成功'
  122. };
  123. return names[category];
  124. };
  125. // 获取随机名言
  126. const fetchQuote = () => {
  127. isLoading.value = true;
  128. // 模拟API请求延迟
  129. setTimeout(() => {
  130. let filteredQuotes = mockQuotes;
  131. // 如果选择了特定分类,过滤名言
  132. if (selectedCategory.value !== 'all') {
  133. filteredQuotes = mockQuotes.filter(quote =>
  134. quote.category === selectedCategory.value
  135. );
  136. }
  137. // 如果没有匹配的名言,使用全部名言
  138. if (filteredQuotes.length === 0) {
  139. filteredQuotes = mockQuotes;
  140. }
  141. // 随机选择一条名言
  142. const randomIndex = Math.floor(Math.random() * filteredQuotes.length);
  143. currentQuote.value = filteredQuotes[randomIndex];
  144. isLoading.value = false;
  145. }, 800);
  146. };
  147. // 组件挂载时获取第一条名言
  148. onMounted(() => {
  149. fetchQuote();
  150. });
  151. </script>
  152. <style scoped>
  153. /* 自定义样式 */
  154. </style>