跳到主要内容

情侣相册

最后更新于:

情侣相册

image-20250912212724371

需求

1帮我写个简单的相册:
2
3图片按时间排序,每张图片下有日期,及文字描述。
4
5这个相册主要记录下一对小情侣之间的美好图片回忆。
6
7请帮我输出具体的代码。

v1-2025.9.12-豆包输出-本地测试

豆包回答

我将为您创建一个温馨浪漫的情侣回忆相册网页,按时间排序展示照片,并包含日期和文字描述。这个设计将采用柔和的色调,营造出甜蜜温馨的氛围,同时确保照片展示清晰、交互友好。

::: dtails 具体代码

couple-album.html文件:

  1<!DOCTYPE html>
  2<html lang="zh-CN">
  3<head>
  4    <meta charset="UTF-8">
  5    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6    <title>我们的回忆 | 爱情相册</title>
  7    <!-- 引入Tailwind CSS -->
  8    <script src="https://cdn.tailwindcss.com"></script>
  9    <!-- 引入Font Awesome -->
 10    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
 11    
 12    <!-- 配置Tailwind自定义颜色和字体 -->
 13    <script>
 14        tailwind.config = {
 15            theme: {
 16                extend: {
 17                    colors: {
 18                        primary: '#E94560', // 浪漫粉红色
 19                        secondary: '#1A1A2E', // 深色背景
 20                        accent: '#FFD700', // 金色点缀
 21                        light: '#F7F7F9', // 浅色背景
 22                    },
 23                    fontFamily: {
 24                        romantic: ['"Dancing Script"', 'cursive', 'sans-serif'],
 25                        sans: ['Inter', 'system-ui', 'sans-serif'],
 26                    },
 27                }
 28            }
 29        }
 30    </script>
 31    
 32    <!-- 自定义工具类 -->
 33    <style type="text/tailwindcss">
 34        @layer utilities {
 35            .content-auto {
 36                content-visibility: auto;
 37            }
 38            .photo-card-shadow {
 39                box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05), 0 0 0 1px rgba(233, 69, 96, 0.1);
 40            }
 41            .album-gradient {
 42                background: linear-gradient(120deg, #fdfbfb 0%, #f7f4f7 100%);
 43            }
 44        }
 45    </style>
 46    
 47    <!-- 引入Google字体 -->
 48    <link href="https://fonts.googleapis.com/css2?family=Dancing+Script:wght@400;700&family=Inter:wght@300;400;500;600&display=swap" rel="stylesheet">
 49</head>
 50
 51<body class="album-gradient min-h-screen">
 52    <!-- 顶部导航栏 -->
 53    <header class="sticky top-0 z-50 bg-white/80 backdrop-blur-md shadow-sm transition-all duration-300">
 54        <div class="container mx-auto px-4 py-4 flex justify-between items-center">
 55            <h1 class="text-3xl md:text-4xl font-romantic text-primary">
 56                <i class="fa fa-heart mr-2 animate-pulse"></i>我们的故事
 57            </h1>
 58            <div class="flex items-center space-x-4">
 59                <button id="sortButton" class="flex items-center text-secondary hover:text-primary transition-colors">
 60                    <i class="fa fa-sort mr-1"></i>
 61                    <span>按时间</span>
 62                </button>
 63                <button id="addPhotoBtn" class="bg-primary hover:bg-primary/90 text-white px-4 py-2 rounded-full shadow-md hover:shadow-lg transition-all transform hover:-translate-y-0.5">
 64                    <i class="fa fa-plus mr-1"></i>添加回忆
 65                </button>
 66            </div>
 67        </div>
 68    </header>
 69
 70    <!-- 主内容区 -->
 71    <main class="container mx-auto px-4 py-8">
 72        <!-- 相册介绍 -->
 73        <div class="text-center mb-12 max-w-3xl mx-auto">
 74            <h2 class="text-[clamp(1.8rem,4vw,2.5rem)] font-romantic text-secondary mb-4">记录我们的每一个美好瞬间</h2>
 75            <p class="text-gray-600 text-lg">时光荏苒,爱意绵长。这里收藏着属于我们的点点滴滴,每一张照片都是一段珍贵的回忆。</p>
 76        </div>
 77        
 78        <!-- 照片筛选标签 -->
 79        <div class="flex flex-wrap justify-center gap-2 mb-8">
 80            <button class="filter-tag active px-4 py-2 rounded-full bg-primary text-white" data-filter="all">全部回忆</button>
 81            <button class="filter-tag px-4 py-2 rounded-full bg-white text-gray-700 hover:bg-primary/10 transition-colors" data-filter="date">约会时光</button>
 82            <button class="filter-tag px-4 py-2 rounded-full bg-white text-gray-700 hover:bg-primary/10 transition-colors" data-filter="travel">旅行足迹</button>
 83            <button class="filter-tag px-4 py-2 rounded-full bg-white text-gray-700 hover:bg-primary/10 transition-colors" data-filter="festival">节日庆典</button>
 84            <button class="filter-tag px-4 py-2 rounded-full bg-white text-gray-700 hover:bg-primary/10 transition-colors" data-filter="daily">日常点滴</button>
 85        </div>
 86        
 87        <!-- 照片网格 -->
 88        <div id="photoGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
 89            <!-- 照片将通过JavaScript动态加载 -->
 90        </div>
 91        
 92        <!-- 加载更多按钮 -->
 93        <div class="text-center mt-12">
 94            <button id="loadMoreBtn" class="px-6 py-3 bg-white text-primary border border-primary rounded-full hover:bg-primary hover:text-white transition-all duration-300 shadow-sm hover:shadow">
 95                加载更多回忆 <i class="fa fa-angle-down ml-1"></i>
 96            </button>
 97        </div>
 98    </main>
 99    
100    <!-- 照片查看模态框 -->
101    <div id="photoModal" class="fixed inset-0 bg-black/80 z-50 hidden flex items-center justify-center p-4">
102        <div class="relative max-w-4xl w-full max-h-[90vh]">
103            <button id="closeModal" class="absolute -top-12 right-0 text-white text-2xl hover:text-primary transition-colors">
104                <i class="fa fa-times"></i>
105            </button>
106            <img id="modalImage" src="" alt="照片大图" class="max-w-full max-h-[80vh] object-contain mx-auto">
107            <div class="bg-white/90 backdrop-blur-sm p-4 mt-4 rounded-lg">
108                <h3 id="modalDate" class="text-primary font-semibold text-lg mb-2"></h3>
109                <p id="modalDescription" class="text-gray-700"></p>
110            </div>
111        </div>
112    </div>
113    
114    <!-- 添加照片模态框 -->
115    <div id="addPhotoModal" class="fixed inset-0 bg-black/60 z-50 hidden items-center justify-center p-4">
116        <div class="bg-white rounded-xl p-6 max-w-md w-full">
117            <div class="flex justify-between items-center mb-4">
118                <h3 class="text-xl font-romantic text-primary">添加新回忆</h3>
119                <button id="closeAddModal" class="text-gray-500 hover:text-primary">
120                    <i class="fa fa-times"></i>
121                </button>
122            </div>
123            <form id="addPhotoForm" class="space-y-4">
124                <div>
125                    <label class="block text-gray-700 mb-1" for="photoDate">日期</label>
126                    <input type="date" id="photoDate" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/50">
127                </div>
128                <div>
129                    <label class="block text-gray-700 mb-1" for="photoDescription">描述这段回忆</label>
130                    <textarea id="photoDescription" rows="3" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/50" placeholder="记录下当时的心情和故事..."></textarea>
131                </div>
132                <div>
133                    <label class="block text-gray-700 mb-1" for="photoCategory">分类</label>
134                    <select id="photoCategory" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/50">
135                        <option value="date">约会时光</option>
136                        <option value="travel">旅行足迹</option>
137                        <option value="festival">节日庆典</option>
138                        <option value="daily">日常点滴</option>
139                    </select>
140                </div>
141                <div>
142                    <label class="block text-gray-700 mb-1" for="photoUrl">照片地址</label>
143                    <input type="text" id="photoUrl" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/50" placeholder="输入照片的URL地址">
144                </div>
145                <button type="submit" class="w-full bg-primary hover:bg-primary/90 text-white py-3 rounded-lg transition-colors">
146                    保存回忆
147                </button>
148            </form>
149        </div>
150    </div>
151    
152    <!-- 页脚 -->
153    <footer class="bg-secondary text-white py-8 mt-16">
154        <div class="container mx-auto px-4 text-center">
155            <p class="font-romantic text-2xl mb-2">我们的故事,未完待续...</p>
156            <p class="text-gray-300 text-sm">© <span id="currentYear"></span> 爱与回忆 | 永远在一起</p>
157        </div>
158    </footer>
159
160    <script>
161        // 照片数据 - 按时间倒序排列(最新的在前)
162        const photos = [
163            {
164                id: 1,
165                date: '2023-10-15',
166                description: '第一次一起看海,海风很轻,你的笑容很甜。我们在沙滩上写下彼此的名字,约定要一起看遍世界的每一片海。',
167                url: 'https://picsum.photos/id/1039/800/600',
168                category: 'date'
169            },
170            {
171                id: 2,
172                date: '2023-09-21',
173                description: '中秋节一起做月饼,虽然形状不太完美,但这是我们一起完成的第一个节日美食。月光下的你,比月亮还要温柔。',
174                url: 'https://picsum.photos/id/292/800/600',
175                category: 'festival'
176            },
177            {
178                id: 3,
179                date: '2023-08-05',
180                description: '周末一起去郊外露营,晚上躺在帐篷里看星星,你说要把最亮的那颗星星命名为我们的名字。',
181                url: 'https://picsum.photos/id/883/800/600',
182                category: 'travel'
183            },
184            {
185                id: 4,
186                date: '2023-07-10',
187                description: '第一次一起做饭,你负责洗菜我负责炒,虽然有点手忙脚乱,但吃到嘴里的那一刻觉得无比幸福。',
188                url: 'https://picsum.photos/id/431/800/600',
189                category: 'daily'
190            },
191            {
192                id: 5,
193                date: '2023-06-01',
194                description: '儿童节一起去了游乐园,你像个孩子一样拉着我玩遍了所有项目,旋转木马上的笑容是我见过最美的风景。',
195                url: 'https://picsum.photos/id/338/800/600',
196                category: 'date'
197            },
198            {
199                id: 6,
200                date: '2023-05-20',
201                description: '520收到的惊喜,你说每天都要像今天一样爱我。其实有你的每一天,都是情人节。',
202                url: 'https://picsum.photos/id/240/800/600',
203                category: 'festival'
204            }
205        ];
206        
207        // 页面加载时显示的照片数量
208        let visibleCount = 6;
209        // 当前排序方式 (desc: 倒序, asc: 正序)
210        let sortOrder = 'desc';
211        // 当前筛选类别
212        let currentFilter = 'all';
213        
214        // DOM元素
215        const photoGrid = document.getElementById('photoGrid');
216        const loadMoreBtn = document.getElementById('loadMoreBtn');
217        const sortButton = document.getElementById('sortButton');
218        const photoModal = document.getElementById('photoModal');
219        const modalImage = document.getElementById('modalImage');
220        const modalDate = document.getElementById('modalDate');
221        const modalDescription = document.getElementById('modalDescription');
222        const closeModal = document.getElementById('closeModal');
223        const addPhotoBtn = document.getElementById('addPhotoBtn');
224        const addPhotoModal = document.getElementById('addPhotoModal');
225        const closeAddModal = document.getElementById('closeAddModal');
226        const addPhotoForm = document.getElementById('addPhotoForm');
227        const filterTags = document.querySelectorAll('.filter-tag');
228        const currentYearEl = document.getElementById('currentYear');
229        
230        // 设置当前年份
231        currentYearEl.textContent = new Date().getFullYear();
232        
233        // 初始化相册
234        function initAlbum() {
235            renderPhotos();
236            setupEventListeners();
237        }
238        
239        // 渲染照片
240        function renderPhotos() {
241            // 清空网格
242            photoGrid.innerHTML = '';
243            
244            // 筛选和排序照片
245            let filteredPhotos = [...photos];
246            
247            // 应用筛选
248            if (currentFilter !== 'all') {
249                filteredPhotos = filteredPhotos.filter(photo => photo.category === currentFilter);
250            }
251            
252            // 应用排序
253            filteredPhotos.sort((a, b) => {
254                const dateA = new Date(a.date);
255                const dateB = new Date(b.date);
256                return sortOrder === 'desc' ? dateB - dateA : dateA - dateB;
257            });
258            
259            // 限制显示数量
260            const photosToShow = filteredPhotos.slice(0, visibleCount);
261            
262            // 没有照片时显示提示
263            if (photosToShow.length === 0) {
264                photoGrid.innerHTML = `
265                    <div class="col-span-full text-center py-12">
266                        <i class="fa fa-image text-gray-300 text-5xl mb-4"></i>
267                        <p class="text-gray-500">没有找到符合条件的回忆</p>
268                    </div>
269                `;
270                return;
271            }
272            
273            // 创建照片卡片
274            photosToShow.forEach(photo => {
275                const formattedDate = formatDate(photo.date);
276                
277                const photoCard = document.createElement('div');
278                photoCard.className = 'photo-card bg-white rounded-xl overflow-hidden photo-card-shadow transform transition-all duration-300 hover:-translate-y-2 hover:shadow-xl';
279                photoCard.dataset.category = photo.category;
280                
281                photoCard.innerHTML = `
282                    <div class="relative overflow-hidden group">
283                        <img src="${photo.url}" alt="回忆照片" class="w-full h-64 object-cover transition-transform duration-500 group-hover:scale-110">
284                        <div class="absolute inset-0 bg-primary/20 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-center justify-center">
285                            <button class="view-photo-btn bg-white text-primary p-3 rounded-full transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300">
286                                <i class="fa fa-search-plus"></i>
287                            </button>
288                        </div>
289                    </div>
290                    <div class="p-5">
291                        <div class="flex justify-between items-center mb-2">
292                            <span class="text-primary font-semibold">${formattedDate}</span>
293                            <span class="text-xs px-2 py-1 rounded-full bg-primary/10 text-primary">
294                                ${getCategoryName(photo.category)}
295                            </span>
296                        </div>
297                        <p class="text-gray-600 line-clamp-3">${photo.description}</p>
298                    </div>
299                `;
300                
301                photoGrid.appendChild(photoCard);
302                
303                // 添加查看照片事件
304                const viewBtn = photoCard.querySelector('.view-photo-btn');
305                viewBtn.addEventListener('click', () => openPhotoModal(photo));
306                
307                // 点击照片也可以查看大图
308                const img = photoCard.querySelector('img');
309                img.addEventListener('click', () => openPhotoModal(photo));
310            });
311            
312            // 控制"加载更多"按钮显示
313            if (visibleCount >= filteredPhotos.length) {
314                loadMoreBtn.classList.add('hidden');
315            } else {
316                loadMoreBtn.classList.remove('hidden');
317            }
318        }
319        
320        // 格式化日期
321        function formatDate(dateString) {
322            const date = new Date(dateString);
323            return date.toLocaleDateString('zh-CN', {
324                year: 'numeric',
325                month: 'long',
326                day: 'numeric'
327            });
328        }
329        
330        // 获取分类名称
331        function getCategoryName(category) {
332            const categories = {
333                'date': '约会时光',
334                'travel': '旅行足迹',
335                'festival': '节日庆典',
336                'daily': '日常点滴'
337            };
338            return categories[category] || category;
339        }
340        
341        // 打开照片模态框
342        function openPhotoModal(photo) {
343            modalImage.src = photo.url;
344            modalImage.alt = photo.description;
345            modalDate.textContent = formatDate(photo.date);
346            modalDescription.textContent = photo.description;
347            photoModal.classList.remove('hidden');
348            document.body.style.overflow = 'hidden'; // 防止背景滚动
349        }
350        
351        // 关闭照片模态框
352        function closePhotoModal() {
353            photoModal.classList.add('hidden');
354            document.body.style.overflow = ''; // 恢复滚动
355        }
356        
357        // 切换排序方式
358        function toggleSortOrder() {
359            sortOrder = sortOrder === 'desc' ? 'asc' : 'desc';
360            renderPhotos();
361            
362            // 更新排序按钮文本
363            const sortText = sortButton.querySelector('span');
364            sortText.textContent = sortOrder === 'desc' ? '按时间(最新在前)' : '按时间(最早在前)';
365        }
366        
367        // 加载更多照片
368        function loadMorePhotos() {
369            visibleCount += 3;
370            renderPhotos();
371        }
372        
373        // 切换筛选类别
374        function setFilter(category) {
375            currentFilter = category;
376            visibleCount = 6; // 重置显示数量
377            
378            // 更新筛选标签样式
379            filterTags.forEach(tag => {
380                if (tag.dataset.filter === category) {
381                    tag.classList.add('bg-primary', 'text-white');
382                    tag.classList.remove('bg-white', 'text-gray-700', 'hover:bg-primary/10');
383                } else {
384                    tag.classList.remove('bg-primary', 'text-white');
385                    tag.classList.add('bg-white', 'text-gray-700', 'hover:bg-primary/10');
386                }
387            });
388            
389            renderPhotos();
390        }
391        
392        // 打开添加照片模态框
393        function openAddPhotoModal() {
394            addPhotoModal.classList.remove('hidden');
395            addPhotoModal.classList.add('flex');
396            document.body.style.overflow = 'hidden';
397        }
398        
399        // 关闭添加照片模态框
400        function closeAddPhotoModalFunc() {
401            addPhotoModal.classList.add('hidden');
402            addPhotoModal.classList.remove('flex');
403            document.body.style.overflow = '';
404            addPhotoForm.reset();
405        }
406        
407        // 添加新照片
408        function addNewPhoto(e) {
409            e.preventDefault();
410            
411            const date = document.getElementById('photoDate').value;
412            const description = document.getElementById('photoDescription').value;
413            const category = document.getElementById('photoCategory').value;
414            const url = document.getElementById('photoUrl').value;
415            
416            // 简单验证
417            if (!date || !description || !url) {
418                alert('请填写所有必填字段');
419                return;
420            }
421            
422            // 创建新照片对象
423            const newPhoto = {
424                id: photos.length + 1,
425                date,
426                description,
427                url,
428                category
429            };
430            
431            // 添加到照片数组
432            photos.unshift(newPhoto);
433            
434            // 重新渲染
435            renderPhotos();
436            
437            // 关闭模态框
438            closeAddPhotoModalFunc();
439            
440            // 显示成功提示
441            alert('回忆添加成功!');
442        }
443        
444        // 设置事件监听器
445        function setupEventListeners() {
446            // 排序按钮
447            sortButton.addEventListener('click', toggleSortOrder);
448            
449            // 加载更多按钮
450            loadMoreBtn.addEventListener('click', loadMorePhotos);
451            
452            // 关闭照片模态框
453            closeModal.addEventListener('click', closePhotoModal);
454            
455            // 点击模态框背景关闭
456            photoModal.addEventListener('click', (e) => {
457                if (e.target === photoModal) {
458                    closePhotoModal();
459                }
460            });
461            
462            // 添加照片按钮
463            addPhotoBtn.addEventListener('click', openAddPhotoModal);
464            
465            // 关闭添加照片模态框
466            closeAddModal.addEventListener('click', closeAddPhotoModalFunc);
467            
468            // 点击添加照片模态框背景关闭
469            addPhotoModal.addEventListener('click', (e) => {
470                if (e.target === addPhotoModal) {
471                    closeAddPhotoModalFunc();
472                }
473            });
474            
475            // 提交添加照片表单
476            addPhotoForm.addEventListener('submit', addNewPhoto);
477            
478            // 筛选标签
479            filterTags.forEach(tag => {
480                tag.addEventListener('click', () => {
481                    setFilter(tag.dataset.filter);
482                });
483            });
484            
485            // 滚动时改变导航栏样式
486            window.addEventListener('scroll', () => {
487                const header = document.querySelector('header');
488                if (window.scrollY > 50) {
489                    header.classList.add('py-2', 'shadow');
490                    header.classList.remove('py-4');
491                } else {
492                    header.classList.add('py-4');
493                    header.classList.remove('py-2', 'shadow');
494                }
495            });
496        }
497        
498        // 页面加载完成后初始化
499        document.addEventListener('DOMContentLoaded', initAlbum);
500    </script>
501</body>
502</html>

:::

这个情侣回忆相册具有以下特点:

  1. 温馨浪漫的设计风格:采用粉红色作为主色调,搭配优雅的字体和柔和的背景,营造出甜蜜浪漫的氛围,非常适合记录情侣间的美好回忆。
  2. 时间排序功能:照片默认按时间倒序排列(最新的在前),用户可以点击排序按钮切换为正序排列(最早的在前)。
  3. 分类筛选系统:提供了四种回忆分类(约会时光、旅行足迹、节日庆典、日常点滴),方便快速筛选查看特定类型的回忆。
  4. 响应式布局:在手机、平板和桌面设备上都能完美展示,照片网格会根据屏幕尺寸自动调整布局。
  5. 交互体验
    • 照片卡片悬停时有放大和阴影效果
    • 点击照片可查看大图和完整描述
    • 支持添加新的回忆照片
    • 滚动时导航栏会有动态变化效果
  6. 完整功能:包含照片展示、详情查看、排序、筛选、加载更多和添加新回忆等功能。

您可以直接使用这个代码,也可以根据需要修改照片数据、颜色方案或添加更多功能。

测试效果

还是不错的。

存在问题

问题1:在豆包里都有这个红心,为啥在我部署好的服务器上,红心消失了。。。

image-20250912211420362

v2-2025.9.12-豆包输出-集成到teek里

提出问题

1前面的 那个 情侣相册模块,请帮我生成一个 vue3版本的组件,不要使用Tailwind CSS,样式直接使用普通css写在组件内。

豆包回答

我将为您创建一个 Vue3 版本的情侣相册组件,不依赖 Tailwind CSS,使用原生 CSS 编写样式并整合在组件内部,保持原有的浪漫风格和功能特性。

具体代码:

这个 Vue3 版本的情侣相册组件具有以下特点:

  1. 组件化结构:分为CoupleAlbum.vue(主组件)和PhotoCard.vue(照片卡片组件),便于维护和扩展。
  2. 原生 CSS 实现:完全不依赖任何 CSS 框架,所有样式使用普通 CSS 编写,方便您根据需求进行修改。
  3. 完整的功能:
    • 照片按时间排序(可切换正序 / 倒序)
    • 分类筛选系统
    • 照片查看模态框
    • 添加新回忆功能
    • 响应式布局设计
  4. 精美的交互效果:
    • 卡片悬停时的上浮和阴影变化
    • 照片缩放效果
    • 平滑的过渡动画
    • 滚动时导航栏样式变化
  5. 数据管理:使用 Vue3 的 Composition API 管理状态和数据,逻辑清晰。

使用方法:

  1. 将两个组件文件放入您的 Vue3 项目中
  2. 在需要使用相册的页面中导入CoupleAlbum组件并使用
  3. 照片数据存储在CoupleAlbum.vuephotos数组中,您可以根据需要修改或扩展
  4. 如需调整样式,直接修改各组件内的<style>部分即可

这个组件保持了原有的浪漫风格,同时使用 Vue3 的特性实现了更好的可维护性和扩展性,方便您集成到自己的项目中。


亲自测试:

(1)创建文件:在docs\.vitepress\theme\components\CoupleAlbum目录下创建如下2个文件

具体信息见上文 豆包输出的代码:

1CoupleAlbum.vue  
2PhotoCard.vue

image-20250912212151862

(2)注册

编辑docs\.vitepress\theme\index.ts文件,新加如下几行信息:

1// 导入情侣相册组件
2import CoupleAlbum from './components/CoupleAlbum/CoupleAlbum.vue'
3import PhotoCard from './components/CoupleAlbum/PhotoCard.vue'
4
5
6
7    app.component('CoupleAlbum', CoupleAlbum) // 注册情侣相册组件
8    app.component('PhotoCard', PhotoCard)

image-20250912212517691

(3)使用

创建docs\90.关于\70.情侣相册.md文件:

 1---
 2title: 情侣相册
 3date: 2025-01-04 11:19:48
 4permalink: /about/love
 5layout: page
 6categories:
 7  - 更多
 8tags:
 9  - 关于我
10sidebar: false
11article: false
12comment: false
13articleTopTip: false
14articleBottomTip: false
15copyright: false
16---
17
18<CoupleAlbum />

(4)验证

运行后,验证:

image-20250912212724371

结束。

v3-2025.9.13-豆包输出-解决1个告警问题

提出问题

 1Port 5173 is in use, trying another one...
 2
 3  vitepress v1.6.4
 4
 5  ➜  Local:   http://localhost:5174/
 6  ➜  Network: use --host to expose
 7  ➜  press h to show help
 8[vite:css] @import must precede all other statements (besides @charset or empty @layer)
 9346|    
10347|    /* 引入Google字体 */
11348|    @import url('https://fonts.googleapis.com/css2?family=Dancing+Script:wght@400;700&family=Inter:wght@300;400;500;600&display=swap');
12   |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13349|    
14
15
16最近在处理 前面 那个情侣相册  时 ,发现在运行vitepress项目时弹出了一个告警,该如何解决呢?

image-20250913070303204

豆包生成

这个错误提示是由于 CSS 中 @import 语句的位置不正确导致的。在 CSS 规范中,@import 规则必须放在所有其他 CSS 语句之前(@charset 或空的 @layer 除外)。

要解决这个问题,你需要调整代码中 @import 语句的位置:

  1. 找到包含 @import url('https://fonts.googleapis.com/css2?family=Dancing+Script:wght@400;700&family=Inter:wght@300;400;500;600&display=swap'); 这行代码的 CSS 文件
  2. 将这个 @import 语句移动到该 CSS 文件的最顶部,确保它在所有其他 CSS 规则之前

例如,错误的写法可能是这样的:

css

1/* 一些其他样式 */
2body {
3  margin: 0;
4}
5
6/* 引入Google字体 */
7@import url('https://fonts.googleapis.com/css2?family=Dancing+Script:wght@400;700&family=Inter:wght@300;400;500;600&display=swap');

正确的写法应该是:

css

1/* 引入Google字体 - 放在最顶部 */
2@import url('https://fonts.googleapis.com/css2?family=Dancing+Script:wght@400;700&family=Inter:wght@300;400;500;600&display=swap');
3
4/* 其他样式放在@import之后 */
5body {
6  margin: 0;
7}

调整后,VitePress 在编译 CSS 时就不会再报这个错误了。这是一个 CSS 语法规范要求,确保 @import 语句在样式表的最前面。

验证测试

(1)按上面所述更新自己文件 docs\.vitepress\theme\components\CoupleAlbum\CoupleAlbum.vue

  1<template>
  2    <div class="couple-album">
  3      <!-- 顶部导航 -->
  4      <header class="album-header" :class="{ 'scrolled': isScrolled }">
  5        <div class="container">
  6          <h1 class="album-title">
  7            <i class="fa fa-heart"></i> 我们的故事
  8          </h1>
  9          <div class="header-actions">
 10            <button class="sort-btn" @click="toggleSortOrder">
 11              <i class="fa fa-sort"></i>
 12              <span>{{ sortText }}</span>
 13            </button>
 14            <button class="add-btn" @click="openAddModal">
 15              <i class="fa fa-plus"></i> 添加回忆
 16            </button>
 17          </div>
 18        </div>
 19      </header>
 20  
 21      <!-- 主内容区 -->
 22      <main class="album-content">
 23        <div class="container">
 24          <!-- 相册介绍 -->
 25          <div class="album-intro">
 26            <h2 class="intro-title">记录我们的每一个美好瞬间</h2>
 27            <p class="intro-text">时光荏苒爱意绵长这里收藏着属于我们的点点滴滴每一张照片都是一段珍贵的回忆</p>
 28          </div>
 29          
 30          <!-- 筛选标签 -->
 31          <div class="filter-tags">
 32            <button 
 33              class="filter-tag" 
 34              :class="{ active: currentFilter === 'all' }"
 35              @click="setFilter('all')"
 36            >
 37              全部回忆
 38            </button>
 39            <button 
 40              class="filter-tag" 
 41              :class="{ active: currentFilter === 'date' }"
 42              @click="setFilter('date')"
 43            >
 44              约会时光
 45            </button>
 46            <button 
 47              class="filter-tag" 
 48              :class="{ active: currentFilter === 'travel' }"
 49              @click="setFilter('travel')"
 50            >
 51              旅行足迹
 52            </button>
 53            <button 
 54              class="filter-tag" 
 55              :class="{ active: currentFilter === 'festival' }"
 56              @click="setFilter('festival')"
 57            >
 58              节日庆典
 59            </button>
 60            <button 
 61              class="filter-tag" 
 62              :class="{ active: currentFilter === 'daily' }"
 63              @click="setFilter('daily')"
 64            >
 65              日常点滴
 66            </button>
 67          </div>
 68          
 69          <!-- 照片网格 -->
 70          <div class="photo-grid">
 71            <PhotoCard 
 72              v-for="photo in filteredPhotos" 
 73              :key="photo.id" 
 74              :photo="photo"
 75              :on-photo-click="openPhotoModal"
 76            />
 77          </div>
 78          
 79          <!-- 无照片提示 -->
 80          <div class="no-photos" v-if="filteredPhotos.length === 0">
 81            <i class="fa fa-image"></i>
 82            <p>没有找到符合条件的回忆</p>
 83          </div>
 84        </div>
 85      </main>
 86      
 87      <!-- 页脚 -->
 88      <footer class="album-footer">
 89        <div class="container">
 90          <p class="footer-quote">我们的故事未完待续...</p>
 91          <p class="footer-copyright">© {{ currentYear }} 爱与回忆 | 永远在一起</p>
 92        </div>
 93      </footer>
 94      
 95      <!-- 照片查看模态框 -->
 96      <div class="modal-backdrop" v-if="isPhotoModalOpen" @click="closePhotoModal">
 97        <div class="modal-content" @click.stop>
 98          <button class="modal-close" @click="closePhotoModal">
 99            <i class="fa fa-times"></i>
100          </button>
101          <img 
102            :src="currentPhoto.url" 
103            :alt="currentPhoto.description" 
104            class="modal-image"
105          >
106          <div class="modal-info">
107            <h3 class="modal-date">{{ currentPhotoFormattedDate }}</h3>
108            <p class="modal-description">{{ currentPhoto.description }}</p>
109          </div>
110        </div>
111      </div>
112      
113      <!-- 添加照片模态框 -->
114      <div class="modal-backdrop" v-if="isAddModalOpen" @click="closeAddModal">
115        <div class="modal-content add-modal-content" @click.stop>
116          <div class="add-modal-header">
117            <h3 class="add-modal-title">添加新回忆</h3>
118            <button class="modal-close" @click="closeAddModal">
119              <i class="fa fa-times"></i>
120            </button>
121          </div>
122          <form class="add-photo-form" @submit.prevent="addNewPhoto">
123            <div class="form-group">
124              <label for="photoDate">日期</label>
125              <input type="date" id="photoDate" v-model="newPhoto.date" required>
126            </div>
127            <div class="form-group">
128              <label for="photoDescription">描述这段回忆</label>
129              <textarea 
130                id="photoDescription" 
131                rows="3" 
132                v-model="newPhoto.description" 
133                placeholder="记录下当时的心情和故事..."
134                required
135              ></textarea>
136            </div>
137            <div class="form-group">
138              <label for="photoCategory">分类</label>
139              <select id="photoCategory" v-model="newPhoto.category" required>
140                <option value="date">约会时光</option>
141                <option value="travel">旅行足迹</option>
142                <option value="festival">节日庆典</option>
143                <option value="daily">日常点滴</option>
144              </select>
145            </div>
146            <div class="form-group">
147              <label for="photoUrl">照片地址</label>
148              <input 
149                type="text" 
150                id="photoUrl" 
151                v-model="newPhoto.url" 
152                placeholder="输入照片的URL地址"
153                required
154              >
155            </div>
156            <button type="submit" class="submit-btn">保存回忆</button>
157          </form>
158        </div>
159      </div>
160    </div>
161  </template>
162  
163  <script setup>
164  import { ref, computed, onMounted, reactive } from 'vue';
165  import PhotoCard from './PhotoCard.vue';
166  
167  // 照片数据
168  const photos = ref([
169    {
170      id: 1,
171      date: '2023-10-15',
172      description: '第一次一起看海,海风很轻,你的笑容很甜。我们在沙滩上写下彼此的名字,约定要一起看遍世界的每一片海。',
173      url: 'https://picsum.photos/id/1039/800/600',
174      category: 'date'
175    },
176    {
177      id: 2,
178      date: '2023-09-21',
179      description: '中秋节一起做月饼,虽然形状不太完美,但这是我们一起完成的第一个节日美食。月光下的你,比月亮还要温柔。',
180      url: 'https://picsum.photos/id/292/800/600',
181      category: 'festival'
182    },
183    {
184      id: 3,
185      date: '2023-08-05',
186      description: '周末一起去郊外露营,晚上躺在帐篷里看星星,你说要把最亮的那颗星星命名为我们的名字。',
187      url: 'https://picsum.photos/id/883/800/600',
188      category: 'travel'
189    },
190    {
191      id: 4,
192      date: '2023-07-10',
193      description: '第一次一起做饭,你负责洗菜我负责炒,虽然有点手忙脚乱,但吃到嘴里的那一刻觉得无比幸福。',
194      url: 'https://picsum.photos/id/431/800/600',
195      category: 'daily'
196    },
197    {
198      id: 5,
199      date: '2023-06-01',
200      description: '儿童节一起去了游乐园,你像个孩子一样拉着我玩遍了所有项目,旋转木马上的笑容是我见过最美的风景。',
201      url: 'https://picsum.photos/id/338/800/600',
202      category: 'date'
203    },
204    {
205      id: 6,
206      date: '2023-05-20',
207      description: '520收到的惊喜,你说每天都要像今天一样爱我。其实有你的每一天,都是情人节。',
208      url: 'https://picsum.photos/id/240/800/600',
209      category: 'festival'
210    }
211  ]);
212  
213  // 状态管理
214  const sortOrder = ref('desc'); // desc: 倒序, asc: 正序
215  const currentFilter = ref('all');
216  const isScrolled = ref(false);
217  const currentYear = ref(new Date().getFullYear());
218  
219  // 模态框状态
220  const isPhotoModalOpen = ref(false);
221  const currentPhoto = ref(null);
222  const isAddModalOpen = ref(false);
223  
224  // 新照片数据
225  const newPhoto = reactive({
226    date: '',
227    description: '',
228    category: 'date',
229    url: ''
230  });
231  
232  // 处理滚动事件
233  onMounted(() => {
234    const handleScroll = () => {
235      isScrolled.value = window.scrollY > 50;
236    };
237    
238    window.addEventListener('scroll', handleScroll);
239    return () => window.removeEventListener('scroll', handleScroll);
240  });
241  
242  // 计算属性 - 排序和筛选照片
243  const filteredPhotos = computed(() => {
244    // 复制照片数组以避免修改原始数据
245    let result = [...photos.value];
246    
247    // 筛选
248    if (currentFilter.value !== 'all') {
249      result = result.filter(photo => photo.category === currentFilter.value);
250    }
251    
252    // 排序
253    result.sort((a, b) => {
254      const dateA = new Date(a.date).getTime();
255      const dateB = new Date(b.date).getTime();
256      return sortOrder.value === 'desc' ? dateB - dateA : dateA - dateB;
257    });
258    
259    return result;
260  });
261  
262  // 排序文本
263  const sortText = computed(() => {
264    return sortOrder.value === 'desc' ? '按时间(最新在前)' : '按时间(最早在前)';
265  });
266  
267  // 格式化当前照片日期
268  const currentPhotoFormattedDate = computed(() => {
269    if (!currentPhoto.value) return '';
270    const date = new Date(currentPhoto.value.date);
271    return date.toLocaleDateString('zh-CN', {
272      year: 'numeric',
273      month: 'long',
274      day: 'numeric'
275    });
276  });
277  
278  // 切换排序方式
279  const toggleSortOrder = () => {
280    sortOrder.value = sortOrder.value === 'desc' ? 'asc' : 'desc';
281  };
282  
283  // 设置筛选类别
284  const setFilter = (category) => {
285    currentFilter.value = category;
286  };
287  
288  // 打开照片模态框
289  const openPhotoModal = (photo) => {
290    currentPhoto.value = photo;
291    isPhotoModalOpen.value = true;
292    document.body.style.overflow = 'hidden';
293  };
294  
295  // 关闭照片模态框
296  const closePhotoModal = () => {
297    isPhotoModalOpen.value = false;
298    document.body.style.overflow = '';
299  };
300  
301  // 打开添加照片模态框
302  const openAddModal = () => {
303    isAddModalOpen.value = true;
304    document.body.style.overflow = 'hidden';
305    // 设置默认日期为今天
306    newPhoto.date = new Date().toISOString().split('T')[0];
307  };
308  
309  // 关闭添加照片模态框
310  const closeAddModal = () => {
311    isAddModalOpen.value = false;
312    document.body.style.overflow = '';
313    // 重置表单
314    Object.keys(newPhoto).forEach(key => {
315      newPhoto[key] = key === 'category' ? 'date' : '';
316    });
317  };
318  
319  // 添加新照片
320  const addNewPhoto = () => {
321    const newId = photos.value.length > 0 
322      ? Math.max(...photos.value.map(p => p.id)) + 1 
323      : 1;
324    
325    photos.value.unshift({
326      id: newId,
327      ...{...newPhoto}
328    });
329    
330    closeAddModal();
331    // 可以添加提示信息
332    alert('回忆添加成功!');
333  };
334  </script>
335  
336  <style scoped>
337    /* 引入Google字体 */
338  @import url('https://fonts.googleapis.com/css2?family=Dancing+Script:wght@400;700&family=Inter:wght@300;400;500;600&display=swap');
339  
340  /* 基础样式 */
341  .couple-album {
342    font-family: 'Inter', system-ui, sans-serif;
343    background: linear-gradient(120deg, #fdfbfb 0%, #f7f4f7 100%);
344    min-height: 100vh;
345    color: #333;
346  }
347  
348  .container {
349    width: 100%;
350    max-width: 1200px;
351    margin: 0 auto;
352    padding: 0 20px;
353  }
354  
355  /* 头部样式 */
356  .album-header {
357    background: rgba(255, 255, 255, 0.8);
358    backdrop-filter: blur(4px);
359    padding: 16px 0;
360    position: sticky;
361    top: 0;
362    z-index: 100;
363    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
364    transition: all 0.3s ease;
365  }
366  
367  .album-header.scrolled {
368    padding: 8px 0;
369    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
370  }
371  
372  .album-header .container {
373    display: flex;
374    justify-content: space-between;
375    align-items: center;
376  }
377  
378  .album-title {
379    margin: 0;
380    font-size: 24px;
381    font-family: 'Dancing Script', cursive;
382    color: #E94560;
383    display: flex;
384    align-items: center;
385  }
386  
387  .album-title i {
388    margin-right: 8px;
389    animation: pulse 2s infinite;
390  }
391  
392  @keyframes pulse {
393    0% { opacity: 1; }
394    50% { opacity: 0.6; }
395    100% { opacity: 1; }
396  }
397  
398  .header-actions {
399    display: flex;
400    align-items: center;
401    gap: 15px;
402  }
403  
404  .sort-btn {
405    background: none;
406    border: none;
407    color: #1A1A2E;
408    cursor: pointer;
409    display: flex;
410    align-items: center;
411    gap: 5px;
412    padding: 5px 10px;
413    border-radius: 4px;
414    transition: color 0.2s ease;
415  }
416  
417  .sort-btn:hover {
418    color: #E94560;
419  }
420  
421  .add-btn {
422    background: #E94560;
423    color: white;
424    border: none;
425    border-radius: 20px;
426    padding: 8px 16px;
427    display: flex;
428    align-items: center;
429    gap: 5px;
430    cursor: pointer;
431    box-shadow: 0 2px 5px rgba(233, 69, 96, 0.3);
432    transition: all 0.2s ease;
433  }
434  
435  .add-btn:hover {
436    background: #d13b54;
437    box-shadow: 0 4px 8px rgba(233, 69, 96, 0.4);
438    transform: translateY(-1px);
439  }
440  
441  /* 内容区样式 */
442  .album-content {
443    padding: 40px 0;
444  }
445  
446  .album-intro {
447    text-align: center;
448    max-width: 600px;
449    margin: 0 auto 40px;
450  }
451  
452  .intro-title {
453    font-family: 'Dancing Script', cursive;
454    font-size: 32px;
455    color: #1A1A2E;
456    margin: 0 0 15px;
457  }
458  
459  .intro-text {
460    color: #666;
461    font-size: 16px;
462    margin: 0;
463  }
464  
465  /* 筛选标签 */
466  .filter-tags {
467    display: flex;
468    flex-wrap: wrap;
469    justify-content: center;
470    gap: 10px;
471    margin-bottom: 30px;
472  }
473  
474  .filter-tag {
475    background: white;
476    border: none;
477    color: #666;
478    padding: 8px 16px;
479    border-radius: 20px;
480    cursor: pointer;
481    transition: all 0.2s ease;
482  }
483  
484  .filter-tag.active {
485    background: #E94560;
486    color: white;
487  }
488  
489  .filter-tag:not(.active):hover {
490    background: rgba(233, 69, 96, 0.1);
491  }
492  
493  /* 照片网格 */
494  .photo-grid {
495    display: grid;
496    grid-template-columns: 1fr;
497    gap: 25px;
498  }
499  
500  @media (min-width: 768px) {
501    .photo-grid {
502      grid-template-columns: repeat(2, 1fr);
503    }
504  }
505  
506  @media (min-width: 1024px) {
507    .photo-grid {
508      grid-template-columns: repeat(3, 1fr);
509    }
510  }
511  
512  /* 无照片提示 */
513  .no-photos {
514    text-align: center;
515    padding: 50px 0;
516    color: #aaa;
517  }
518  
519  .no-photos i {
520    font-size: 60px;
521    margin-bottom: 15px;
522    display: block;
523  }
524  
525  .no-photos p {
526    margin: 0;
527    font-size: 16px;
528  }
529  
530  /* 页脚样式 */
531  .album-footer {
532    background: #1A1A2E;
533    color: white;
534    padding: 30px 0;
535    margin-top: 50px;
536  }
537  
538  .footer-quote {
539    font-family: 'Dancing Script', cursive;
540    font-size: 24px;
541    text-align: center;
542    margin: 0 0 10px;
543  }
544  
545  .footer-copyright {
546    text-align: center;
547    color: #aaa;
548    font-size: 14px;
549    margin: 0;
550  }
551  
552  /* 模态框样式 */
553  .modal-backdrop {
554    position: fixed;
555    top: 0;
556    left: 0;
557    right: 0;
558    bottom: 0;
559    background: rgba(0, 0, 0, 0.8);
560    display: flex;
561    align-items: center;
562    justify-content: center;
563    z-index: 1000;
564    padding: 20px;
565  }
566  
567  .modal-content {
568    background: white;
569    border-radius: 8px;
570    max-width: 900px;
571    width: 100%;
572    position: relative;
573  }
574  
575  .modal-close {
576    position: absolute;
577    top: -30px;
578    right: 0;
579    background: none;
580    border: none;
581    color: white;
582    font-size: 24px;
583    cursor: pointer;
584    transition: color 0.2s ease;
585  }
586  
587  .modal-close:hover {
588    color: #E94560;
589  }
590  
591  .modal-image {
592    width: 100%;
593    max-height: 70vh;
594    object-fit: contain;
595  }
596  
597  .modal-info {
598    padding: 20px;
599  }
600  
601  .modal-date {
602    color: #E94560;
603    font-weight: 600;
604    margin: 0 0 10px;
605  }
606  
607  .modal-description {
608    color: #666;
609    margin: 0;
610    line-height: 1.6;
611  }
612  
613  /* 添加照片模态框 */
614  .add-modal-content {
615    max-width: 500px;
616    width: 100%;
617  }
618  
619  .add-modal-header {
620    display: flex;
621    justify-content: space-between;
622    align-items: center;
623    margin-bottom: 20px;
624    padding-bottom: 10px;
625    border-bottom: 1px solid #eee;
626  }
627  
628  .add-modal-title {
629    margin: 0;
630    font-family: 'Dancing Script', cursive;
631    color: #E94560;
632    font-size: 22px;
633  }
634  
635  .add-photo-form {
636    display: flex;
637    flex-direction: column;
638    gap: 15px;
639  }
640  
641  .form-group {
642    display: flex;
643    flex-direction: column;
644    gap: 5px;
645  }
646  
647  .form-group label {
648    font-size: 14px;
649    color: #555;
650  }
651  
652  .form-group input,
653  .form-group textarea,
654  .form-group select {
655    padding: 10px;
656    border: 1px solid #ddd;
657    border-radius: 4px;
658    font-family: inherit;
659    font-size: 14px;
660  }
661  
662  .form-group input:focus,
663  .form-group textarea:focus,
664  .form-group select:focus {
665    outline: none;
666    border-color: #E94560;
667    box-shadow: 0 0 0 2px rgba(233, 69, 96, 0.2);
668  }
669  
670  .submit-btn {
671    background: #E94560;
672    color: white;
673    border: none;
674    border-radius: 4px;
675    padding: 12px;
676    font-size: 16px;
677    cursor: pointer;
678    transition: background 0.2s ease;
679  }
680  
681  .submit-btn:hover {
682    background: #d13b54;
683  }
684  
685
686  </style>
687  

image-20250913070954419

(2)验证

不会再有报错了:(完美)

image-20250913071141678

结束。

最新文章

文档导航