给网站加一个倒数日卡片~(成功啦~)
Published in:2024-02-07 | category: 前端
Words: 3.8k | Reading time: 19min | reading:

想给网站加一个倒数日卡片
但是主题里没有相关配置
因为对网站之类的完全零基础,看了一圈感觉自己想要的效果跟网站上已有的”座右铭”卡片的实现很像
准备学习借用一下~

motto.ejs(座右铭卡片)
1
2
3
4
5
6
7
8
9
10
<% if (theme.motto.on && page.current === 1) { %>
<div class="motto">
<h3 class="motto-title"><%= theme.motto.title %></h3>
<div class="motto-content">
<p>
<%= theme.motto.content %>
</p>
</div>
</div>
<% } %>
theme.motto.on?感觉好像懂了什么
主题配置文件新增:
1
2
3
# 首页倒数日
countdown:
on: true

刚刚还在想卡片的样式是在哪里定义的,然后想起来还有ccs

motto.styl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.motto {
width: 100%;
margin-bottom: 16px;
background: #fff;
box-shadow: 0 1px 20px -6px rgba(0, 0, 0, 0.5);
padding: 20px;
border-radius: 10px;
box-sizing: border-box;
transition: all 0.3s;
position: relative;
background: convert(hexo-config('motto.background'));

.motto-title {
text-align: center;
}

.motto-content {
text-align: center;
padding: 15px 20%;
color: #34495e;
}
}

@media (max-width: 551px) {
.motto {
.motto-content {
padding: 15px 10%;
}
}
}

感觉设置多个平行内容跟公告有点像,看看去

主题配置文件
1
list: # list相当于数组对象,[{title:'xx',date: 'xx', url: 'xxx', color: 'red'}]根据自己实际情况,增加或者删除

我也储存一下

countdown.ejs新增:
1
2
3
4
5
6
7
8
9
10
11
12
<script>
let listData = [
{
title: "计算机二级",
targetDate: "2024-03-23", // 目标日期
},
{
title: "蓝桥杯省赛",
targetDate: "2024-04-13", // 目标日期
}
];
</script>
countdown.ejs新增倒数日函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<script>
function countdown(targetDate, callback) {
// 将目标日期和当前日期转换为时间戳(毫秒)
const targetTime = new Date(targetDate).getTime();
const currentTime = new Date().getTime();

// 计算剩余时间(毫秒)
const remainingTime = targetTime - currentTime;

// 如果剩余时间小于等于0
if (remainingTime <= 0) {
return '倒计时结束';
}

// 将剩余时间转换为天、小时、分钟和秒
const days = Math.floor(remainingTime / (1000 * 60 * 60 * 24));
const hours = Math.floor(
(remainingTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
);
const minutes = Math.floor(
(remainingTime % (1000 * 60 * 60)) / (1000 * 60)
);
const seconds = Math.floor((remainingTime % (1000 * 60)) / 1000);

// 返回剩余时间的字符串格式
return `${days}${hours}小时 ${minutes}分钟 ${seconds}秒`;
}
</script>

现在countdown.ejs是这样的:

countdown.ejs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<%if (theme.countdown.on && page.current === 1) {
listData.forEach(function(item) { %>
<div class="index-notice" id="appIndexNotice">
<h3>
<i class="fas fa-bullhorn index-notice-icon"></i><%= item.title %>
</h3>
<div class="index-notice-content">
<% item.listData.forEach(function(data) { %>
<div class="countdown-card">
<h4><%= data.title %></h4>
<p>目标日期: <%= data.targetDate %></p>
<p>剩余时间: <%= countdown(data.targetDate) %></p>
</div>
<% }); %>
</div>
</div>
<% }); }%>
<script>
function countdown(targetDate) {
// 将目标日期和当前日期转换为时间戳(毫秒)
const targetTime = new Date(targetDate).getTime();
const currentTime = new Date().getTime();

// 计算剩余时间(毫秒)
const remainingTime = targetTime - currentTime;

// 如果剩余时间小于等于0,则执行回调函数
if (remainingTime <= 0) {
return '倒计时结束';
}

// 将剩余时间转换为天、小时、分钟和秒
const days = Math.floor(remainingTime / (1000 * 60 * 60 * 24));
const hours = Math.floor(
(remainingTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
);
const minutes = Math.floor(
(remainingTime % (1000 * 60 * 60)) / (1000 * 60)
);
const seconds = Math.floor((remainingTime % (1000 * 60)) / 1000);

// 返回剩余时间的字符串格式
return `${days}${hours}小时 ${minutes}分钟 ${seconds}秒`;
}
</script>
<script>
let listData = [
{
title: "计算机二级",
targetDate: "2024-03-23", // 目标日期
},
{
title: "蓝桥杯省赛",
targetDate: "2024-04-13", // 目标日期
}
];
</script>


现在新建countdown.styl
(我现在还不太清楚要不要定义卡片放在页面哪个位置,到最后再说吧)

找到一个东西:

motto.ejs:
1
2
3
4
5
6
7
@media (max-width: 551px) {
.motto {
.motto-content {
padding: 15px 10%;
}
}
}

感觉是卡片排列的底层逻辑,由于这里是屏幕宽度小于等于 551px 时,于是要找一个总的默认的.styl文件看一看
找到一个感觉很像的:

home.styl:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  .widget {
margin-bottom: 16px;
background: #fff;
border-radius: 10px;
box-shadow: 0 1px 20px -6px rgba(0, 0, 0, 0.5);

.content {
padding: 8px 16px;
}
}


@media screen and (max-width: 1200px) {
& {
width: 80%;
}
}

@media screen and (max-width: 992px) {
& {
width: 95%;
}
}

@media screen and (max-width: 992px) {
& {
width: 95%;
flex-direction: column;

.l_content {
width: 100%;
margin: 0 auto;
}
}
}

刚刚发现.styl文件里还要一个这个属性

motto.styl:
1
position: relative

总之总之卡片/组件位置应该不用我准确定义了

主题配置文件新增:
1
2
3
4
# 首页倒数日
countdown:
on: true
background: blue//新增

最后的countdown.styl(太晚了,具体的没细改,主打的一个出现了就是最好的!)

countdown.styl:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
.index-notice {
width: 100%;
margin-bottom: 16px;
background: #fff;
box-shadow: 0 1px 20px -6px rgba(0, 0, 0, 0.5);
padding: 20px;
border-radius: 10px;
box-sizing: border-box;
transition: all 0.3s;
position: relative;
background: convert(hexo-config('countdown.background'));

.index-notice-icon {
text-align: center;
}

.index-notice-content{
margin-top: 10px;
}

.countdown-card {
text-align: center;
padding: 15px 20%;
color: #34495e;
}
}

@media (max-width: 551px) {
.motto {
.motto-content {
padding: 15px 10%;
}
}
}

countdown.ejs和countdown.styl都备份好了,开始第一次测试~

发现没成功,但是我又发现了一个需要配置的文件:

index.ejs:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<% if(theme.swiper.on ) { %>
<!-- 首页轮播 -->
<%- partial('_partial/swiper') %>
<% } %>

<div id="l_main">
<div class="l_content">
<!-- 自定义的内容 -->
<%- partial('_partial/home_widget') %>
<!-- 首页座右铭 -->
<%- partial('_partial/motto') %>
<!-- 首页公告 -->
<%- partial('_partial/notice') %>
<!-- 首页文章置顶 -->
<%- partial('_partial/topArticle', {page: page}) %>

<div class="bg-floor" id="home-bg-floor" style="position: fixed;left: 0;top: 0;width: 100%;height: 100%;z-index: -2;"></div>
<!-- 每一篇文章卡片 -->
<%- partial('_partial/card/post') %>
<!-- 翻页 -->
<%- partial('_partial/paginator') %>
</div>

<%- partial('_partial/side') %>
</div>
<!-- 花瓣和雪花飘落 -->
<%- partial('_partial/scripts/falling') %>

<!-- 灯笼 -->
<%- partial('_partial/lantern') %>

然后照葫芦画瓢:

index.ejs新增:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<% if(theme.swiper.on ) { %>
<!-- 首页轮播 -->
<%- partial('_partial/swiper') %>
<% } %>

<div id="l_main">
<div class="l_content">
<!-- 自定义的内容 -->
<%- partial('_partial/home_widget') %>
<!-- 首页倒数日 -->
<%- partial('_partial/countdown') %>
<!-- 首页座右铭 -->
<%- partial('_partial/motto') %>
<!-- 首页公告 -->
<%- partial('_partial/notice') %>
<!-- 首页文章置顶 -->
<%- partial('_partial/topArticle', {page: page}) %>

<div class="bg-floor" id="home-bg-floor" style="position: fixed;left: 0;top: 0;width: 100%;height: 100%;z-index: -2;"></div>
<!-- 每一篇文章卡片 -->
<%- partial('_partial/card/post') %>
<!-- 翻页 -->
<%- partial('_partial/paginator') %>
</div>

<%- partial('_partial/side') %>
</div>
<!-- 花瓣和雪花飘落 -->
<%- partial('_partial/scripts/falling') %>

<!-- 灯笼 -->
<%- partial('_partial/lantern') %>

第二次测试~
私密马赛,报bug了:

bug:
1
2
3
4
5
6
7
D:\github_code\blog\themes\hexo-theme-bamboo\layout\_partial\countdown.ejs:1
>> 1| <%if (theme.countdown.on && page.current === 1) {
2| listData.forEach(function(item) { %>
3| <div class="index-notice" id="appIndexNotice">
4| <h3>

listData is not defined

修改了一下countdown.ejs:

index.ejs新增:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<%if (theme.countdown.on && page.current === 1) {
let listData = [
{
title: "计算机二级",
targetDate: "2024-03-23", // 目标日期
},
{
title: "蓝桥杯省赛",
targetDate: "2024-04-13", // 目标日期
}
];

listData.forEach(function(item) { %>
<div class="index-notice" id="appIndexNotice">
<h3>
<i class="fas fa-bullhorn index-notice-icon"></i><%= item.title %>
</h3>
<div class="index-notice-content">
<% item.listData.forEach(function(data) { %>
<div class="countdown-card">
<h4><%= data.title %></h4>
<p>目标日期: <%= data.targetDate %></p>
<p>剩余时间: <%= countdown(data.targetDate) %></p>
</div>
<% }); %>
</div>
</div>
<% }); }%>
<script>
let listData = [
{
title: "计算机二级",
targetDate: "2024-03-23", // 目标日期
},
{
title: "蓝桥杯省赛",
targetDate: "2024-04-13", // 目标日期
}
];
</script>
<script>
function countdown(targetDate) {
// 将目标日期和当前日期转换为时间戳(毫秒)
const targetTime = new Date(targetDate).getTime();
const currentTime = new Date().getTime();

// 计算剩余时间(毫秒)
const remainingTime = targetTime - currentTime;

// 如果剩余时间小于等于0,则执行回调函数
if (remainingTime <= 0) {
return '倒计时结束';
}

// 将剩余时间转换为天、小时、分钟和秒
const days = Math.floor(remainingTime / (1000 * 60 * 60 * 24));
const hours = Math.floor(
(remainingTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
);
const minutes = Math.floor(
(remainingTime % (1000 * 60 * 60)) / (1000 * 60)
);
const seconds = Math.floor((remainingTime % (1000 * 60)) / 1000);

// 返回剩余时间的字符串格式
return `${days}${hours}小时 ${minutes}分钟 ${seconds}秒`;
}
</script>


变量名错了/(ㄒoㄒ)/~~再改一下:

countdown.ejs新增:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<%if (theme.countdown.on && page.current === 1) {
let listData = [
{
title: "计算机二级",
targetDate: "2024-03-23", // 目标日期
},
{
title: "蓝桥杯省赛",
targetDate: "2024-04-13", // 目标日期
}
];

listData.forEach(function(item) { %>
<div class="index-notice" id="appIndexNotice">
<h3>
<i class="fas fa-bullhorn index-notice-icon"></i><%= item.title %>
</h3>
<div class="index-notice-content">
<div class="countdown-card">
<h4><%= item.title %></h4>
<p>目标日期: <%= item.targetDate %></p>
<p>剩余时间: <%= countdown(item.targetDate) %></p>
</div>
</div>
</div>
<% }); }%>
<script>
let listData = [
{
title: "计算机二级",
targetDate: "2024-03-23", // 目标日期
},
{
title: "蓝桥杯省赛",
targetDate: "2024-04-13", // 目标日期
}
];
</script>
<script>
function countdown(targetDate) {
// 将目标日期和当前日期转换为时间戳(毫秒)
const targetTime = new Date(targetDate).getTime();
const currentTime = new Date().getTime();

// 计算剩余时间(毫秒)
const remainingTime = targetTime - currentTime;

// 如果剩余时间小于等于0,则执行回调函数
if (remainingTime <= 0) {
return '倒计时结束';
}

// 将剩余时间转换为天、小时、分钟和秒
const days = Math.floor(remainingTime / (1000 * 60 * 60 * 24));
const hours = Math.floor(
(remainingTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
);
const minutes = Math.floor(
(remainingTime % (1000 * 60 * 60)) / (1000 * 60)
);
const seconds = Math.floor((remainingTime % (1000 * 60)) / 1000);

// 返回剩余时间的字符串格式
return `${days}${hours}小时 ${minutes}分钟 ${seconds}秒`;
}
</script>


又报错啦被自己蠢笑啦

countdown.ejs:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<%if (theme.countdown.on && page.current === 1) {
let listData = [
{
title: "计算机二级",
targetDate: "2024-03-23", // 目标日期
},
{
title: "蓝桥杯省赛",
targetDate: "2024-04-13", // 目标日期
}
];

function countdown(targetDate) {
// 将目标日期和当前日期转换为时间戳(毫秒)
const targetTime = new Date(targetDate).getTime();
const currentTime = new Date().getTime();

// 计算剩余时间(毫秒)
const remainingTime = targetTime - currentTime;

// 如果剩余时间小于等于0,则执行回调函数
if (remainingTime <= 0) {
return '倒计时结束';
}

// 将剩余时间转换为天、小时、分钟和秒
const days = Math.floor(remainingTime / (1000 * 60 * 60 * 24));
const hours = Math.floor(
(remainingTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
);
const minutes = Math.floor(
(remainingTime % (1000 * 60 * 60)) / (1000 * 60)
);
const seconds = Math.floor((remainingTime % (1000 * 60)) / 1000);

// 返回剩余时间的字符串格式
return `${days}${hours}小时 ${minutes}分钟 ${seconds}秒`;
}

listData.forEach(function (item) { %>
<div class="index-notice" id="appIndexNotice">
<h3>
<i class="fas fa-bullhorn index-notice-icon"></i><%= item.title %>
</h3>
<div class="index-notice-content">
<div class="countdown-card">
<h4><%= item.title %></h4>
<p>目标日期: <%= item.targetDate %></p>
<p>剩余时间: <%= countdown(item.targetDate) %></p>
</div>
</div>
</div>
<% }); }%>

第三次测试~(给代码磕个头/(ㄒoㄒ)/~~)
成功了!!!!!!

哈哈哈哈哈哈
哈哈哈哈哈哈

等会。。。。/(ㄒoㄒ)/~~
两个bug:
1.看起来用的不是我现在的时间呀,像是我上传的时间,因为怎么样他都不变
2.我公告栏怎么不滚动了????Orz

第一个bug,突然想起来这个网站是静态,请教了GPT老师:

GPT老师

是的,这段代码获取的是客户端的当前日期和时间,而不是服务器的日期和时间。如果你的网站是静态的,即没有与服务器进行交互更新页面内容的能力,那么 new Date().getTime() 获取的时间将始终是用户打开网页时的时间,不会实时更新。

如果你想要在静态网站中实现实时倒计时功能,你可以考虑使用 JavaScript 配合客户端的时区偏移来获取当前时间。以下是一个示例实现:

1
2
3
4
5
6
7
8
9
function getCurrentTime() {
var date = new Date();
var offset = date.getTimezoneOffset() * 60 * 1000; // 获取客户端时区偏移(以毫秒为单位)
var currentTime = date.getTime() - offset; // 当前时间减去时区偏移得到客户端时间
return currentTime;
}

var targetTime = new Date(targetDate).getTime();
var currentTime = getCurrentTime();

在这个示例中,getCurrentTime 函数通过获取客户端的时区偏移,将客户端时间与服务器时间进行同步。这样就能在静态网站中实现实时的倒计时功能。请注意,这种方法仍然依赖于客户端的时间,因此可能会受到用户设备时间不准确或篡改的影响。

然后又加了实时滚动功能:

countdown.ejs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<!DOCTYPE html>
<html>
<head>
<title>实时倒计时</title>
<style>
.countdown-card {
font-size: 20px;
text-align: center;
}
</style>
</head>
<body>
<div id="countdown-container">
<% let listData = [
{
title: "计算机二级",
targetDate: "2024-03-23", // 目标日期
},
{
title: "蓝桥杯省赛",
targetDate: "2024-04-13", // 目标日期
}
];

listData.forEach(function(item) { %>
<div class="index-notice">
<h3>
<i class="fas fa-bullhorn index-notice-icon"></i> <%= item.title %>
</h3>
<div class="index-notice-content">
<div class="countdown-card">
<h4><%= item.title %></h4>
<p>目标日期: <%= item.targetDate %></p>
<p>剩余时间: <span id="countdown-<%= item.title %>">0</span></p>
</div>
</div>
</div>
<% }) %>
</div>

<script>
function getCurrentTime() {
var date = new Date();
var offset = date.getTimezoneOffset() * 60 * 1000;
var currentTime = date.getTime() - offset;
return currentTime;
}

function updateCountdown(id, remainingTime) {
var obj = document.getElementById(id);
var days = Math.floor(remainingTime / (1000 * 60 * 60 * 24));
var hours = Math.floor((remainingTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((remainingTime % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((remainingTime % (1000 * 60)) / 1000);

obj.textContent = `${days}${hours}小时 ${minutes}分钟 ${seconds}秒`;

if (remainingTime <= 0) {
clearInterval(timer);
obj.textContent = '倒计时结束';
}
}

function countdown(targetDate, id) {
var targetTime = new Date(targetDate).getTime();
var currentTime = getCurrentTime();
var remainingTime = targetTime - currentTime;

if (remainingTime <= 0) {
document.getElementById(id).textContent = '倒计时结束';
return;
}

var timer = setInterval(function() {
remainingTime -= 1000;
updateCountdown(id, remainingTime);
}, 1000);
}

window.addEventListener('DOMContentLoaded', (event) => {
<% listData.forEach(function(item) { %>
countdown("<%= item.targetDate %>", 'countdown-<%= item.title %>');
<% }) %>
});
</script>
</body>
</html>

02:37了。我去睡觉了~(第二个bug自己好了。。。)

Prev:
电路游戏:Turing Complete
Next:
test