-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathscript.js
More file actions
546 lines (486 loc) · 30.7 KB
/
script.js
File metadata and controls
546 lines (486 loc) · 30.7 KB
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
// (需要修改的部分)
const OWNER = 'imoki'; // github 用户名,仓库所有者
// (以下不需要修改)
const REPO = OWNER + '.github.io'; // github page 仓库名
const TYPE = "博客" // 系统类型,用于区分不同系统
const CONFIG = "[" + TYPE + "_配置]" // 配置标识
const ARTICLE = "[" + TYPE + "_文章]" // 文章标识
const COMMENT = "[" + TYPE + "_评论]" // 评论标识
const ARTICLE_ABSTRACT_NUM = 20; // 文章摘要字数,设置为 0 不显示摘要
// const apiUrl = `https://api.kkgithub.com/repos/${OWNER}/${REPO}/issues`; // 接口地址
const apiUrl = `https://api.github.com/repos/${OWNER}/${REPO}/issues`; // 接口地址
// 开关变量,设置为 true 使用模拟数据,设置为 false 使用真实的 GitHub API 数据
const USE_MOCK_DATA = false;
// const USE_MOCK_DATA = true; // 测试时使用模拟数据,发布时使用真实数据
// 模拟数据
const mockIssues = [
{
id: 1,
title: '[博客_文章]Web 开发技术的前世今生',
user: { login: 'imoki' }, // 假设用户名为 imoki
body: '在当今数字化的时代,Web 开发技术如同一场永不停歇的变革浪潮,不断推动着互联网的发展。<br><br><h3>早期 Web 开发(静态页面时代)</h3>在 Web 诞生之初,页面主要是静态的,使用简单的 HTML 标记语言来构建。那时的网页内容固定,缺乏交互性。<br>例如,最早的网站仅仅是一些文字和简单的图片展示,用于传递基本的信息。<br><br><h3>动态网页的兴起(CGI 时代)</h3>随着互联网的发展,用户对网页的交互性需求越高越高。于是,CGI(Common Gateway Interface)技术应运而生。<br>通过 CGI,服务器可以根据用户的请求动态生成页面内容,实现了简单的交互功能。<br><br><h3>Web 2.0 时代(AJAX 与前端框架)</h3>Web 2.0 标志着互联网从单纯的信息获取向互动和参与转变。AJAX(Asynchronous JavaScript and XML)技术的出现,使得网页可以在不刷新的情况下与服务器进行数据交互。<br>随后,各种前端框架如 jQuery、Angular、React 和 Vue.js 相继诞生,大大提高了前端开发的效率和用户体验。<br><br><h3>现代 Web 开发(全栈与微服务)</h3>如今,Web 开发已经进入了全栈和微服务的时代。开发者需要掌握前端、后端和数据库等多方面的知识。<br>微服务架构将一个大型应用拆分成多个小型服务,提高了系统的可维护性和扩展性。<br><br>总之,Web 开发技术的发展历程是一部不断创新和进步的历史,未来也将继续朝着更加智能、高效和便捷的方向发展。'
},
{
id: 2,
title: '[博客_文章]人工智能在医疗领域的应用与挑战',
user: { login: 'imoki' }, // 假设用户名为 imoki
body: '人工智能(AI)作为当今科技领域的热门话题,正逐渐渗透到各个行业,医疗领域也不例外。<br><br><h3>应用场景</h3><h4>疾病诊断</h4>AI 可以通过分析医学影像(如 X 光、CT 等)来辅助医生进行疾病诊断。例如,深度学习算法可以识别影像中的病变特征,提高诊断的准确性和效率。<br><br><h4>药物研发</h4>在药物研发过程中,AI 可以帮助科学家筛选潜在的药物靶点,预测药物的疗效和副作用,从而加速药物研发的进程。<br><br><h4>健康管理</h4>通过智能穿戴设备收集用户的健康数据,AI 可以为用户提供个性化的健康建议和预警,帮助用户预防疾病。<br><br><h3>挑战与问题</h3><h4>数据隐私与安全</h4>医疗数据涉及到患者的隐私,如何确保 AI 系统在处理和存储这些数据时的安全性和隐私性是一个重要的问题。<br><br><h4>算法可解释性</h4>一些复杂的 AI 算法(如深度学习)就像一个“黑匣子”,医生和患者很难理解算法的决策过程,这可能会影响 AI 在医疗领域的信任度和应用。<br><br><h4>法律与伦理问题</h4>当 AI 辅助诊断出现错误时,责任该如何界定?这涉及到一系列的法律和伦理问题,需要进一步的探讨和规范。<br><br>尽管面临诸多挑战,但人工智能在医疗领域的应用前景依然广阔,有望为人类的健康事业带来巨大的变革。'
},
{
id: 3,
title: '[博客_文章]十大火爆的 CMS 系统推荐',
user: { login: 'imoki' }, // 假设用户名为 imoki
body: '在如今的数字时代,拥有一个美观、功能强大的网站对于个人和企业来说至关重要。而选择一个适合自己需求的 CMS 系统,是搭建一个成功网站的关键一步。在本文中,我们将向大家推荐十个火爆的 CMS 系统,帮助你轻松搭建出令人瞩目的网站!<br><br><h3>01 - WordPress</h3>WordPress 是全球最受欢迎的 CMS 系统之一,拥有强大的扩展性和用户友好的界面。它提供了数千个主题和插件,让你可以轻松地创建出个性化的网站。无论你是个人博客、企业网站还是电子商务平台,WordPress 都能满足你的需求。目前,全球超过 30% 的网站都是使用 WordPress 搭建的,这充分证明了它的火爆程度。<br><strong>优点</strong>:主题、插件丰富,简单易用。<br><strong>缺点</strong>:安全性差,过于依赖插件,面向过程开发,二次扩展开发起点高;对于大型门户网站力不从心。<br><br><h3>02 - Joomla</h3>Joomla 是另一个深受推崇的 CMS 系统,它被广泛应用于企业网站和在线社区。Joomla 提供了众多的功能模块,如新闻发布、产品展示和用户管理等,让你的网站可以轻松满足各种需求。与 WordPress 相比,Joomla 的学习曲线稍微陡峭一些,但一旦熟悉了它的使用方法,你会发现它给你带来的丰富功能是无可替代的。<br><strong>缺点</strong>:Joomla 对于初学者来说并不如 WordPress 那样直观,学习难度系数比较大;可用附加组件更少;Joomla 社区比 WordPress 小,因此资源更容易少。<br><br><h3>03 - Drupal</h3>Drupal 是一款高度灵活的 CMS 系统,被广泛应用于大型企业和政府机构的网站。它提供了强大的权限管理和多语言支持,适合需要复杂功能和安全性的网站。尽管 Drupal 的学习曲线较陡峭,但一旦掌握了它的使用技巧,你将会被它的灵活性和扩展性所折服。<br><strong>缺点</strong>:没有一个默认易用的行为,每个站点都需要付出一定的工作量。<br><br><h3>04 - Discuz!</h3>Discuz! 是一款专注于社区建设的 CMS 系统,被广泛应用于论坛、社交网络和问答平台。它提供了丰富的社交功能,如用户管理、帖子发布和私信交流等。Discuz! 的用户群体庞大,拥有活跃的开发者社区,为你的社区网站提供了强大的支持和扩展能力。<br><strong>优点</strong>:完善的功能,易于使用,开源免费,插件扩展丰富。<br><strong>缺点</strong>:安全性问题,兼容性问题,技术支持,学习成本。<br><br><h3>05 - DedeCMS</h3>DedeCMS 是国内知名的 CMS 系统,广泛应用于个人博客和企业网站。它提供了简单易用的后台管理界面和丰富的模板资源。DedeCMS 还拥有强大的 SEO 优化功能,让你的网站能够在搜索引擎中获得更好的排名。无论你是个人创作者还是企业站长,DedeCMS 都能帮助你快速搭建出令人满意的网站。<br><strong>优点</strong>:社区资源丰富,模板丰富。<br><strong>缺点</strong>:安全性差,论坛付费,扩展性差,开始商业收费了!<br><br><h3>06 - PHPCMS</h3>PHPCMS 是一款强大的内容管理系统,广泛应用于企业门户和新闻网站。它提供了丰富的内容管理功能,如文章发布、评论管理和广告投放等。PHPCMS 的模板系统也非常灵活,让你可以轻松创建出独特的网站风格。如果你需要一个功能强大的网站,PHPCMS 绝对是一个值得考虑的选择。<br><strong>优点</strong>:模块化开发,便于扩展,界面美观。<br><strong>缺点</strong>:无技术支持,不适合新手;没有商城功能;采集功能较弱;已经不维护了。<br><br><h3>07 - MetInfo</h3>MetInfo 是一款专注于企业网站建设的 CMS 系统,提供了丰富的企业级功能和模板资源。它的后台管理界面简洁明了,让你可以轻松管理网站内容和用户信息。MetInfo 还拥有强大的 SEO 优化功能,帮助你的企业网站在竞争激烈的市场中脱颖而出。<br><strong>优点</strong>:内置免费版模板,20 多套界面风格,支持自定义模板。<br><strong>缺点</strong>:主题和插件少,商业收费主题相对多。<br><br><h3>08 - Typecho</h3>Typecho 是一款简洁高效的开源 CMS 系统,适合个人博客和小型网站的搭建。它提供了简单易用的后台管理界面和轻量级的代码结构,让你可以专注于内容创作而不用担心繁琐的技术细节。虽然 Typecho 的扩展性相对较弱,但对于需要一个简洁高效的博客平台来说,它是一个绝佳选择。<br><strong>优点</strong>:简单易用,文件体积较小,丰富的主题和插件,安全性较高,社区活跃。<br><strong>缺点</strong>:功能相对有限,文档相对不够完善,主题和插件相对较少,更新速度相对较慢。<br><br><h3>09 - ThinkCMF</h3>ThinkCMF 是一款全面的企业级 CMS 系统,提供了丰富的企业级功能和模板资源。它拥有强大的权限管理和多语言支持,适合大型企业和政府机构的网站建设。ThinkCMF 的后台管理界面直观易用,让你可以轻松管理网站内容和用户信息。<br><strong>优点</strong>:丰富的开发工具和模块,安全性较高,社区支持广泛。<br><strong>缺点</strong>:学习需要一定的时间和精力,文档不够完善,功能扩展有限,用户群体较小。<br><br><h3>10 - Z - Blog</h3>Z - Blog 是一款专注于个人博客的 CMS 系统,提供了简单易用的后台管理界面和丰富的主题资源。它的安装和配置非常简单,让你可以快速搭建个人博客并分享你的知识和经验。如果你是一个热爱写作的人,Z - Blog 绝对是一个值得尝试的选择。<br><strong>优点</strong>:开源免费,简单易用,丰富的功能模块,模板丰富,支持插件扩展。<br><strong>缺点</strong>:支持插件扩展,社区支持有限,模板和插件定制性相对较差。<br><br><h3>总结</h3>在本文中,我们向大家分享了十个火爆的 CMS 系统,每个 CMS 系统都有自己的特点和适用场景,你可以根据自己的需求选择最适合的系统来搭建出令人瞩目的网站。无论是个人博客、企业网站还是社区平台,这些 CMS 系统都能帮助你实现你的梦想!快来选择一个适合你的 CMS 系统,开始打造你的网站吧!'
},
{
id: 4,
title: "[博客_配置]",
user: { login: 'imoki' }, // 假设用户名为 imoki
// body: '{"avatar": "https://avatars.kkgithub.com/u/78804251?v=4", "name": "imoki", "bio": "热爱技术分享的开发者"}'
// body: '{"avatar": "https://avatars.kkgithub.com/u/78804251?v=4", "name": "imoki", "bio": "热爱技术分享的开发者", "articleImages": { "[博客_文章]Web 开发技术的前世今生": "https://img.loliapi.cn/i/pp/img86.webp", "[博客_文章]人工智能在医疗领域的应用与挑战": "https://img.loliapi.cn/i/pp/img51.webp", "[博客_文章]十大火爆的 CMS 系统推荐": "" }}'
// body: '{"avatar": "https://avatars.kkgithub.com/u/78804251?v=4", "name": "imoki", "bio": "热爱技术分享的开发者", "articleImages": { "[博客_文章]Web 开发技术的前世今生": "https://img.loliapi.cn/i/pp/img86.webp", "[博客_文章]人工智能在医疗领域的应用与挑战": "https://img.loliapi.cn/i/pp/img51.webp", "[博客_文章]十大火爆的 CMS 系统推荐": "" },"sortOrder": ["[博客_文章]关于我", "[博客_文章]人工智能在医疗领域的应用与挑战", "[博客_文章]Web 开发技术的前世今生", "[博客_文章]十大火爆的 CMS 系统推荐" ]}'
body: '{"avatar": "https://avatars.github.com/u/78804251?v=4", "name": "imoki", "bio": "热爱技术分享的开发者", "articleImages": { "[博客_文章]Web 开发技术的前世今生": "https://img.loliapi.cn/i/pp/img86.webp", "[博客_文章]人工智能在医疗领域的应用与挑战": "https://img.loliapi.cn/i/pp/img51.webp", "[博客_文章]十大火爆的 CMS 系统推荐": "" },"sortOrder": ["[博客_文章]关于我", "[博客_文章]人工智能在医疗领域的应用与挑战", "[博客_文章]Web 开发技术的前世今生", "[博客_文章]十大火爆的 CMS 系统推荐" ]}'
},
{
id: 5,
title: '[博客_文章]关于我',
user: { login: 'imoki' },
body: `
## 交流渠道
- [哔哩哔哩](https://space.bilibili.com/3546828310055281) 无盐七空间。
- [GitHub](https://github.com/imoki) imoki。
- 公众号:默库
- QQ群:963592267
`
},
{
id: 6,
title: '[博客_文章]Markdown 列表与链接示例',
user: { login: 'imoki' },
body: `
# Markdown 列表与链接示例
## 无序列表
- 项目 1
- 项目 2
- 项目 3
## 有序列表
1. 第一点
2. 第二点
3. 第三点
## 链接示例
[百度](https://www.baidu.com) 是中国最大的搜索引擎。
[GitHub](https://github.com) 是全球知名的代码托管平台。
`
},
{
id: 7,
title: '[博客_文章]Markdown 代码块与引用示例',
user: { login: 'imoki' },
body: `
# Markdown 代码块与引用示例
## 代码块示例
### 单行代码
这是一个单行代码示例:\`console.log('Hello, World!');\`
### 多行代码
\`\`\`javascript
function greet(name) {
return 'Hello, ' + name + '!';
}
\`\`\`
## 引用示例
> 知识就是力量。
> —— 弗朗西斯·培根
`
},
{
id: 8,
title: '[博客_文章]Markdown 表格示例',
user: { login: 'imoki' },
body: `
# Markdown 表格示例
| 姓名 | 年龄 | 职业 |
| ---- | ---- | ---- |
| 张三 | 25 | 工程师 |
| 李四 | 30 | 设计师 |
| 王五 | 22 | 学生 |
`
},
{
id: 9,
title: '[博客_文章]单行内的 Markdown 样式示例',
user: { login: 'imoki' },
body: '这里有 *斜体*、**粗体**、***粗斜体***、`行内代码`,还有 [百度链接](https://www.baidu.com)。'
},
{
id: 10,
title: '[博客_文章]单行内的 Markdown 特殊字符示例',
user: { login: 'imoki' },
body: '数学公式示例:E=mc^2^。这是一个带符号的句子:2^10^ 表示 2 的 10 次方,5~2~ 可用于特殊标注,还有 © 版权符号。'
},
{
id: 11,
title: '[博客_文章]单行内的 Markdown 表情示例',
user: { login: 'imoki' },
body: '今天心情很不错 :smile:,希望每天都能像这样 :sunny:。'
},
{
id: 12,
title: '[博客_评论]',
user: { login: 'imoki' },
body: JSON.stringify({
'[博客_文章]Web 开发技术的前世今生': [
{
content: '这篇文章写得很详细,受益良多!',
time: '2025-04-28 10:00:00',
nickname: '张三'
}
],
'[博客_文章]人工智能在医疗领域的应用与挑战': [
{
content: '人工智能在医疗的应用前景确实广阔,期待更多突破。',
time: '2025-04-27 14:30:00',
nickname: '李四'
},
{
content: '未来是人工智能',
time: '2025-04-29 15:30:00',
nickname: '王五'
}
]
})
}
].filter(issue => issue.user && issue.user.login === OWNER);
// 获取容器元素
const summariesContainer = document.getElementById('blog-summaries');
const detailContainer = document.getElementById('blog-detail');
// const searchInput = document.getElementById('search-input');
const avatarContainer = document.getElementById('avatar-container');
const personalInfoContainer = document.getElementById('personal-info');
// 获取首页导航项元素
const homeNav = document.getElementById('home-nav');
// 为首页导航项添加点击事件
homeNav.addEventListener('click', (e) => {
e.preventDefault(); // 阻止默认的跳转行为
summariesContainer.style.display = 'block';
detailContainer.style.display = 'none';
personalInfoContainer.style.display = 'block';
});
// 定义首页点击处理函数
function handleHomeClick(event) {
event.preventDefault(); // 阻止默认跳转行为
const homeNav = document.getElementById('home-nav');
// 添加点击时的样式变化,这里可以根据需求修改
homeNav.style.backgroundColor = '#66b1ff';
homeNav.style.transform = 'scale(0.95)';
// 一段时间后恢复样式
setTimeout(() => {
homeNav.style.backgroundColor = '';
homeNav.style.transform = '';
}, 300);
// 显示文章概要,隐藏文章详情
const summariesContainer = document.getElementById('blog-summaries');
const detailContainer = document.getElementById('blog-detail');
summariesContainer.style.display = 'block';
detailContainer.style.display = 'none';
}
async function fetchData() {
// 定义正则表达式,用于匹配 [博客_xxx] 格式的标题
const regex = new RegExp(`^\\[${TYPE}_.*\\].*`);
if (USE_MOCK_DATA) {
// return mockIssues;
// // 过滤模拟数据,只保留标题以 ARTICLE 开头的项
// return mockIssues.filter(issue => issue.title.startsWith(ARTICLE));
// 过滤模拟数据,只保留标题符合正则表达式的项
return mockIssues.filter(issue => regex.test(issue.title));
} else {
try {
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error('网络响应失败');
}
// return await response.json();
const data = await response.json();
// // 过滤真实数据,只保留标题以 ARTICLE 开头的项
// return data.filter(issue => issue.title.startsWith(ARTICLE));
// 过滤真实数据,只保留标题符合正则表达式的项
return data.filter(issue => regex.test(issue.title));
} catch (error) {
console.error('获取 GitHub Issues 时出错:', error);
return [];
}
}
}
function renderPersonalInfo(issues) {
// 检查容器元素是否存在
if (!avatarContainer || !personalInfoContainer) {
console.error('头像容器或个人信息容器未找到,请检查 HTML 中的元素 ID。');
return;
}
// console.log(issues)
// console.log(CONFIG)
const configIssue = issues.find(issue => issue.title === CONFIG);
if (configIssue) {
try {
const config = JSON.parse(configIssue.body);
// 检查配置对象中是否包含所需属性
if (config.avatar && config.name && config.bio) {
const avatarImg = document.createElement('img');
avatarImg.src = config.avatar;
avatarImg.alt = '头像';
avatarImg.className = 'avatar';
avatarContainer.appendChild(avatarImg);
const nameElement = document.createElement('h2');
nameElement.textContent = config.name;
const bioElement = document.createElement('p');
bioElement.textContent = config.bio;
personalInfoContainer.appendChild(nameElement);
personalInfoContainer.appendChild(bioElement);
} else {
console.error('配置信息缺少必要字段,请检查 [配置] Issue 的内容。');
}
// 提取 articleImages 并赋值给 window.articleImages
if (config.articleImages) {
window.articleImages = config.articleImages;
}
} catch (error) {
console.error('解析个人信息配置出错:', error);
}
}
}
async function init() {
// if (typeof marked === 'undefined') {
// console.error('marked 库未正确加载,请检查 HTML 文件中的引入语句。');
// return;
// }
const issues = await fetchData();
renderPersonalInfo(issues);
const articleIssues = issues.filter(issue => issue.title !== CONFIG);
// 获取 [博客_配置] 中的排序规则
const configIssue = issues.find(issue => issue.title === CONFIG);
// console.log(configIssue)
let sortOrder = [];
if (configIssue) {
try {
const config = JSON.parse(configIssue.body);
// console.log(config)
if (config.sortOrder && Array.isArray(config.sortOrder)) {
sortOrder = config.sortOrder;
}
} catch (error) {
console.error('解析排序配置出错:', error);
}
}
// // 输出 sortOrder 和 articleIssues 用于调试
// console.log('sortOrder:', sortOrder);
// console.log('articleIssues:', articleIssues);
// 根据排序规则对文章进行排序
const sortedArticleIssues = articleIssues.sort((a, b) => {
const indexA = sortOrder.indexOf(a.title);
const indexB = sortOrder.indexOf(b.title);
if (indexA === -1 && indexB === -1) {
return 0;
} else if (indexA === -1) {
return 1;
} else if (indexB === -1) {
return -1;
} else {
return indexA - indexB;
}
});
// console.log(sortedArticleIssues)
renderSummaries(sortedArticleIssues);
// searchInput.addEventListener('input', function () {
// const keyword = this.value.toLowerCase();
// const filteredIssues = articleIssues.filter(issue =>
// issue.title.toLowerCase().includes(keyword) || issue.body.toLowerCase().includes(keyword)
// );
// renderSummaries(filteredIssues);
// });
}
function renderSummaries_noimage(issues) {
summariesContainer.innerHTML = '';
issues.forEach(issue => {
// 创建文章概要元素
const summaryElement = document.createElement('div');
summaryElement.classList.add('blog-summary');
// 创建文章标题元素
const titleElement = document.createElement('h2');
// 去掉 ARTICLE 标识
const cleanTitle = issue.title.replace(ARTICLE, '').trim();
titleElement.textContent = cleanTitle;
titleElement.addEventListener('click', () => showDetail(issue));
// 创建文章概要内容元素
const summaryContent = document.createElement('p');
// 截取前 指定 个字符作为概要
const summaryText = issue.body.substring(0, ARTICLE_ABSTRACT_NUM) + '...';
summaryContent.innerHTML = marked.parse(summaryText);
// 将标题和概要添加到文章概要容器
summaryElement.appendChild(titleElement);
summaryElement.appendChild(summaryContent);
// 将文章概要容器添加到博客文章概要容器
summariesContainer.appendChild(summaryElement);
});
}
/**
* 渲染文章概要列表
* @param {Array} issues - 文章列表数据
* 文章内容为空也不进行显示
*/
function renderSummaries(issues) {
summariesContainer.innerHTML = '';
issues.forEach((issue, index) => {
// 创建文章概要元素
const summaryElement = document.createElement('div');
summaryElement.classList.add('blog-summary');
// 使用 Flexbox 布局
summaryElement.style.display = 'flex';
summaryElement.style.alignItems = 'center';
summaryElement.style.justifyContent = 'space-between';
summaryElement.style.gap = '20px'; // 设置图片和文本之间的间距
// 创建文章标题和内容容器
const textContainer = document.createElement('div');
textContainer.classList.add('text-container');
// 让文本容器可以弹性增长
textContainer.style.flex = 1;
// 创建文章图片元素
let imgSrc = '';
if (window.articleImages && window.articleImages[issue.title]) {
imgSrc = window.articleImages[issue.title];
} else {
// 生成 1 到 200 之间的随机数
const randomNum = Math.floor(Math.random() * 200) + 1;
imgSrc = `https://img.loliapi.cn/i/pp/img${randomNum}.webp`;
}
const imgElement = document.createElement('img');
imgElement.src = imgSrc;
imgElement.alt = issue.title;
// 限制图片最大宽度和高度
imgElement.style.maxWidth = '30%';
imgElement.style.maxHeight = '200px';
imgElement.style.objectFit = 'cover';
// 根据索引判断图片显示位置
if (index % 2 === 0) {
imgElement.classList.add('left-image');
summaryElement.prepend(imgElement); // 将图片添加到容器开头
} else {
imgElement.classList.add('right-image');
summaryElement.appendChild(imgElement);
}
// 创建文章标题元素
const titleElement = document.createElement('h2');
// 去掉 ARTICLE 标识
const cleanTitle = issue.title.replace(ARTICLE, '').trim();
titleElement.textContent = cleanTitle;
titleElement.addEventListener('click', () => showDetail(issue));
// 创建文章概要内容元素
const summaryContent = document.createElement('p');
// 截取前 指定 个字符作为概要
const summaryText = issue.body.substring(0, ARTICLE_ABSTRACT_NUM) + '...';
summaryContent.innerHTML = marked.parse(summaryText);
// summaryContent.innerHTML = summaryText;
// 将标题和概要添加到文本容器
textContainer.appendChild(titleElement);
textContainer.appendChild(summaryContent);
// 将文本容器添加到文章概要容器
summaryElement.appendChild(textContainer);
// 将文章概要容器添加到博客文章概要容器
summariesContainer.appendChild(summaryElement);
});
}
// 显示文章详情
function showDetail(issue) {
// 隐藏文章概要
summariesContainer.style.display = 'none';
// 隐藏个人信息
personalInfoContainer.style.display = 'none';
// 显示文章详情
detailContainer.style.display = 'block';
// 清空之前的详情内容
detailContainer.innerHTML = '';
// 创建文章标题元素
const titleElement = document.createElement('h1');
// 去掉 ARTICLE 标识
const cleanTitle = issue.title.replace(ARTICLE, '').trim();
titleElement.textContent = cleanTitle;
// 创建文章内容元素
const contentElement = document.createElement('div');
contentElement.innerHTML = marked.parse(issue.body);
// contentElement.innerHTML = issue.body;
// 创建返回按钮
const backButton = document.createElement('button');
backButton.textContent = '返回';
backButton.addEventListener('click', () => {
summariesContainer.style.display = 'block';
detailContainer.style.display = 'none';
// 如果是从个人信息页面返回,显示个人信息
personalInfoContainer.style.display = 'block';
});
// 将元素添加到详情容器
detailContainer.appendChild(backButton);
detailContainer.appendChild(titleElement);
detailContainer.appendChild(contentElement);
// 查找评论数据
let commentsIssue = mockIssues.find(issue => issue.title === COMMENT);
commentsIssue = false; // 关闭评论
if (commentsIssue) {
try {
const commentsData = JSON.parse(commentsIssue.body);
const commentsForArticle = commentsData[issue.title] || [];
// 创建评论区容器
const commentsSection = document.createElement('div');
commentsSection.classList.add('comments-section');
commentsSection.innerHTML = '<h2>评论区</h2>';
// 遍历评论并添加到评论区
commentsForArticle.forEach(comment => {
const commentElement = document.createElement('div');
commentElement.classList.add('comment');
commentElement.innerHTML = `
<p><strong>${comment.nickname}</strong> 于 ${comment.time} 评论:</p>
<p>${comment.content}</p>
`;
commentsSection.appendChild(commentElement);
});
// 添加评论输入表单
const commentForm = document.createElement('form');
commentForm.innerHTML = `
<input type="text" id="nickname" placeholder="请输入昵称" required>
<textarea id="comment-content" placeholder="请输入评论内容" required></textarea>
<button type="submit">提交评论</button>
`;
commentForm.addEventListener('submit', (e) => {
e.preventDefault();
const nicknameInput = document.getElementById('nickname');
const contentInput = document.getElementById('comment-content');
const newComment = {
content: contentInput.value,
time: new Date().toISOString().replace('T', ' ').substr(0, 19),
nickname: nicknameInput.value
};
// 更新模拟数据
if (!commentsData[issue.title]) {
commentsData[issue.title] = [];
}
commentsData[issue.title].push(newComment);
// 更新评论区显示
const newCommentElement = document.createElement('div');
newCommentElement.classList.add('comment');
newCommentElement.innerHTML = `
<p><strong>${newComment.nickname}</strong> 于 ${newComment.time} 评论:</p>
<p>${newComment.content}</p>
`;
commentsSection.appendChild(newCommentElement);
// 更新模拟数据的 body
commentsIssue.body = JSON.stringify(commentsData);
// 清空表单
nicknameInput.value = '';
contentInput.value = '';
});
commentsSection.appendChild(commentForm);
// 将评论区添加到详情容器
detailContainer.appendChild(commentsSection);
} catch (error) {
console.error('解析评论数据出错:', error);
}
}
}
init();