给hugo博客加上观看电影记录栏目

【更新日志】新增观影栏目,记录每年观看过的电影

临近过年上班也没啥动力,就想着总结一下2024年看过哪些电影,突然灵机一动,想到可以给博客加上一个观影栏目,以卡片的形式展示看过的电影列表,之前逛其他博客的时候也有看到类似的电影记录栏目。说干就干,差不多一个小时就实现了一个简单的页面,同时把2023年和2024年看过的电影都列出来了,如下图所示。

如图所示

实现这个效果大概需要增加三个代码文件,分别是movies.yaml存放电影数据,page/movies/index.md新增一个菜单页面,以及layouts/_default/movies.html编写这个页面的具体样式。

增加影片数据

有的人是通过API读取豆瓣的观影记录,这样很方便,不过我并不用豆瓣,所以选择了最笨的方法,手动编写电影的标题、封面图、年份和评分,按照观看年份分组,手动去豆瓣下载封面图,看上去好像很笨,其实一年就看了大概十部电影,分分钟就填写完成了。

在data文件夹下新建一个movies.yaml,或者其他文件夹下,记得修改代码中的.Site.data.movies成你放置的文件路径。共有三个yaml,分别是movies.yaml、shows.yaml、books.yaml

2024:
  - title: 飞驰人生2 
    cover: /images/movies/2024/feichi.jpg
    year: 2024
    rating: 7.6
  - title: 周处除三害
    cover: /images/movies/2024/zhouchu.jpg
    rating: 8.1
    year: 2023
  - title: 姥姥的外孙
    cover: /images/movies/2024/laolao.jpg
    rating: 8.8
    year: 2024
2023:
  - title: 流浪地球2 
    cover: /images/movies/2023/liulang.jpg
    year: 2023
    rating: 8.3

增加观影页面

content/page/movies/index.md 新增一个菜单页面,slug是地址路径,layout是使用的模板名称,然后设置菜单的顺序以及图标

---
title: 观影
description: 个人年度电影总结,列出所有观看过的电影,按照年份分组
slug: movies
layout: movies 
readingTime: false
toc: false
comments: false
license: false
menu:
    main:
        weight: -45
        params: 
            icon: tag
---

增加观影页面代码

layouts/_default/movies.html 这个文件编写html和css样式,也可以定义一些变量在markdown文件中声明。这里我把电影按照年份分组,在第一排放置了年份选择按钮,按照年份倒序排列,默认选择最近的一年。该代码文件由cursor编写:

点击展开代码
{{ define "body-class" }}template-movies{{ end }}
{{ define "main" }}
    <header>
        <h2 class="article-title">观影记录</h2>
    </header>

    <!-- Movies Section -->
    {{ $moviesData := .Site.Data.movies }}
    {{ $currentYear := now.Format "2006" }}

    {{ $sortedYears := slice }}
    {{ range $year, $movies := $moviesData }}
        {{ $sortedYears = $sortedYears | append $year }}
    {{ end }}
    {{ $sortedYears = sort $sortedYears "value" "desc" }}

    {{ $latestYear := index $sortedYears 0 }}

    <div class="year-buttons">
        {{ range $sortedYears }}
            <button class="year-btn{{ if eq . $latestYear }} active{{ end }}" data-year="{{ . }}">{{ . }}</button>
        {{ end }}
    </div>

    {{ if $moviesData }}
    <h3 class="section-title">电影</h3>

    {{ range $year, $movies := $moviesData }}
        <div class="movies-grid{{ if eq $year $latestYear }} active{{ end }}" data-year="{{ $year }}" data-type="movies">
            {{ range $movies }}
                <div class="movie-card">
                    <div class="movie-poster">
                        {{ if .cover }}
                            <img src="{{ .cover }}" alt="{{ .title }}" loading="lazy">
                        {{ else }}
                            <div class="no-poster">No Poster Available</div>
                        {{ end }}
                    </div>
                    <div class="movie-info">
                        <h3 class="movie-title">{{ .title }} <span class="movie-year">{{ .year }}</span></h3>
                        <div class="movie-meta">
                            {{ if .rating }}
                                <span class="rating"> {{ printf "%.1f" .rating }}</span>
                            {{ end }}
                        </div>
                    </div>
                </div>
            {{ end }}
        </div>
    {{ end }}
    {{ end }}

    <!-- TV Shows Section -->
    {{ $tvData := .Site.Data.shows }}
    
    {{ $tvSortedYears := slice }}
    {{ range $year, $shows := $tvData }}
        {{ $tvSortedYears = $tvSortedYears | append $year }}
    {{ end }}

    <h3 class="section-title">剧集</h3>

    {{ range $year, $shows := $tvData }}
        <div class="movies-grid{{ if eq $year $latestYear }} active{{ end }}" data-year="{{ $year }}" data-type="tv">
            {{ range $shows }}
                <div class="movie-card">
                    <div class="movie-poster">
                        {{ if .cover }}
                            <img src="{{ .cover }}" alt="{{ .title }}" loading="lazy">
                        {{ else }}
                            <div class="no-poster">No Poster Available</div>
                        {{ end }}
                    </div>
                    <div class="movie-info">
                        <h3 class="movie-title">{{ .title }} <span class="movie-year">{{ .year }}</span></h3>
                        <div class="movie-meta">
                            {{ if .rating }}
                                <span class="rating"> {{ printf "%.1f" .rating }}</span>
                            {{ end }}
                        </div>
                    </div>
                </div>
            {{ end }}
        </div>
    {{ end }}

    <!-- Books Section -->
    {{ $booksData := .Site.Data.books }}
    
    {{ $bookSortedYears := slice }}
    {{ range $year, $books := $booksData }}
        {{ $bookSortedYears = $bookSortedYears | append $year }}
    {{ end }}

    <h3 class="section-title">书籍</h3>

    {{ range $year, $books := $booksData }}
        <div class="movies-grid{{ if eq $year $latestYear }} active{{ end }}" data-year="{{ $year }}" data-type="books">
            {{ range $books }}
                <div class="movie-card">
                    <div class="movie-poster">
                        {{ if .cover }}
                            <img src="{{ .cover }}" alt="{{ .title }}" loading="lazy">
                        {{ else }}
                            <div class="no-poster">No Cover Available</div>
                        {{ end }}
                    </div>
                    <div class="movie-info">
                        <h3 class="movie-title">{{ .title }} <span class="movie-year">{{ .year }}</span></h3>
                        <div class="movie-meta">
                            {{ if .rating }}
                                <span class="rating"> {{ printf "%.1f" .rating }}</span>
                            {{ end }}
                        </div>
                    </div>
                </div>
            {{ end }}
        </div>
    {{ end }}

    <style>
        .section-title {
            margin: 0rem 0 0.5rem 0;  /* 减小上下边距 */
            font-size: 1.8rem;
            color: var(--card-text-color-main);
        }

        .year-buttons {
            margin: 0rem 0;
            text-align: left;
        }

        .year-btn {
            padding: 0.7rem 1.5rem;
            margin: 0 0rem;
            border: 2px solid var(--card-background);
            background: transparent;
            color: var(--card-text-color-secondary);
            border-radius: 4px;
            cursor: pointer;
            transition: all 0.2s;
            font-size: 1.6rem;
            font-weight: 500;
            opacity: 0.7;
        }

        .year-btn:hover {
            opacity: 0.9;
            border-color: var(--accent-color);
        }

        .year-btn.active {
            background: var(--accent-color);
            color: var(--accent-color-text);
            border-color: var(--accent-color);
            opacity: 1;
        }

        .movies-grid {
            display: none;
            grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
            gap: 1rem;
            padding: 0rem 0;  /* 减小上下内边距 */
        }
        
        @media (min-width: 768px) {
            .movies-grid {
                grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
                gap: 1.2rem;
            }
        }
        
        .movies-grid.active {
            display: grid;
        }
        
        .movie-card {
            background: var(--card-background);
            border-radius: 6px;
            overflow: hidden;
            transition: transform 0.2s;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        
        .movie-card:hover {
            transform: translateY(-2px);
        }
        
        .movie-poster {
            position: relative;
            padding-top: 130%;
            background: #2a2a2a;
        }
        
        .movie-poster img {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        
        .no-poster {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            color: #888;
            font-size: 0.9rem;
        }
        
        .movie-info {
            padding: 0.8rem;
        }
        
        .movie-title {
            margin: 0 0 0.5rem 0;
            font-size: 1.4rem;
            line-height: 1.3;
            font-weight: 600;
            color: var(--card-text-color-main);
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        .movie-year {
            font-size: 1.2rem;
            color: var(--card-text-color-secondary);
            font-weight: 600;
        }
        
        .movie-meta {
            display: flex;
            justify-content: space-between;
            font-size: 1.2rem;
            color: var(--card-text-color-secondary);
        }

        .rating {
            font-weight: 500;
        }
    </style>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const yearButtons = document.querySelectorAll('.year-btn');
            const grids = document.querySelectorAll('.movies-grid');

            yearButtons.forEach(button => {
                button.addEventListener('click', function() {
                    const year = this.dataset.year;
                    
                    // Remove active class from all buttons
                    yearButtons.forEach(btn => btn.classList.remove('active'));
                    
                    // Remove active class from all grids
                    grids.forEach(grid => grid.classList.remove('active'));
                    
                    // Add active class to clicked button
                    this.classList.add('active');
                    
                    // Add active class to all corresponding grids with matching year
                    document.querySelectorAll(`.movies-grid[data-year="${year}"]`).forEach(grid => {
                        grid.classList.add('active');
                    });
                });
            });
        });
    </script>

    {{ partialCached "footer/footer" . }}
{{ end }}
总结下来发现回想自己一年都看了什么电影并不容易,因为有些是去影院观看,有些是在流媒体平台观看的,有些是在jellyfin上看的,甚至jellyfin还分了好多个账号,最终还是看着豆瓣的年度电影榜单挨个回想自己是否看过。以后可以考虑增加一个电影、书籍数据库,就不用纯靠记忆了。

Licensed under CC BY-NC-SA 4.0
感谢你的阅读,如果我成功帮助到了你,可以关闭屏蔽广告插件访问本网站,也可以打赏我一杯咖啡,谢谢!
加载中...
感谢Jimmy 隐私政策