详情页展示、cookie保存浏览量、返回页面顶端、目录处理

master
barney 2 years ago
parent 2749754eb0
commit 7e17d02726
  1. 13
      pom.xml
  2. 2
      src/main/java/cc/bnblogs/common/WebSite.java
  3. 19
      src/main/java/cc/bnblogs/controller/IndexController.java
  4. 13
      src/main/java/cc/bnblogs/mapper/ArticleMapper.java
  5. 8
      src/main/java/cc/bnblogs/pojo/Article.java
  6. 8
      src/main/java/cc/bnblogs/service/ArticleService.java
  7. 41
      src/main/java/cc/bnblogs/utils/CookieUtil.java
  8. 45
      src/main/java/cc/bnblogs/utils/MarkdownUtil.java
  9. 1
      src/main/resources/application.yml
  10. 309
      src/main/resources/static/css/detail.css
  11. 4
      src/main/resources/static/css/style.css
  12. 6
      src/main/resources/static/plugin/prism/prism.css
  13. 53
      src/main/resources/static/plugin/prism/prism.js
  14. 3
      src/main/resources/templates/admin/article.html
  15. 2
      src/main/resources/templates/common.html
  16. 666
      src/main/resources/templates/detail.html

@ -21,6 +21,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mysql-connector-java.version>8.0.30</mysql-connector-java.version>
<lombok.version>1.18.24</lombok.version>
<commonmark.version>0.18.0</commonmark.version>
</properties>
<dependencies>
@ -68,6 +69,18 @@
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<!--commonmark-java依赖-->
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>${commonmark.version}</version>
</dependency>
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark-ext-gfm-tables</artifactId>
<version>${commonmark.version}</version>
</dependency>
</dependencies>
<build>

@ -43,4 +43,6 @@ public class WebSite {
private String footer;
// 网站logo
private String logo;
// 网站域名
private String domain;
}

@ -8,6 +8,8 @@ import cc.bnblogs.pojo.Article;
import cc.bnblogs.pojo.Category;
import cc.bnblogs.pojo.Tag;
import cc.bnblogs.service.*;
import cc.bnblogs.utils.CookieUtil;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@ -15,8 +17,11 @@ import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
@ -161,7 +166,7 @@ public class IndexController {
/**
* 前台标签列表页
* @param model model
* @param model 引入的mvc模型
* @return 所有标签
*/
@GetMapping("/tag.html")
@ -176,7 +181,17 @@ public class IndexController {
}
@GetMapping("/{id}.html")
public String detail(@PathVariable Integer id) {
public String detail(@PathVariable Integer id, Model model,
HttpServletRequest request, HttpServletResponse response) {
Article article = articleService.detail(id);
// 如果cookie不存在
if (Objects.isNull(CookieUtil.getCookie(request,Article.VIEW_PREFIX + id))) {
// 更新文章浏览量
articleService.viewArticle(id);
CookieUtil.setCookie(response,Article.VIEW_PREFIX + id,"true");
}
// todo 文章内容不存在时应该抛出异常
model.addAttribute("article",article);
return "detail";
}
}

@ -4,7 +4,9 @@ import cc.bnblogs.pojo.Article;
import cc.bnblogs.pojo.Category;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
@ -19,7 +21,7 @@ public interface ArticleMapper extends JpaRepository<Article,Integer>, JpaSpecif
* @param limit 文章数
* @return 匹配的文章列表
*/
@Query(value = "select * from blog_article where type=1 and status=1 order by views limit ?1", nativeQuery = true)
@Query(value = "select * from blog_article where type=1 and status=1 order by views desc limit ?1", nativeQuery = true)
List<Article> hotList(int limit);
/**
@ -36,4 +38,13 @@ public interface ArticleMapper extends JpaRepository<Article,Integer>, JpaSpecif
*/
@Query(value="SELECT updated FROM blog_article WHERE category_id=?1 ORDER BY updated DESC LIMIT 1",nativeQuery = true)
Date lastUpdated(Integer cid);
/**
* 更新浏览量(每次+1)
* @param id 文章id
*/
@Transactional
@Modifying
@Query(value = "update blog_article set views=views+1 where id=?1",nativeQuery = true)
void updateArticleViews(Integer id);
}

@ -1,5 +1,6 @@
package cc.bnblogs.pojo;
import cc.bnblogs.utils.MarkdownUtil;
import lombok.*;
import javax.persistence.*;
@ -18,6 +19,9 @@ import java.util.List;
@Entity
@Table(name = "blog_article")
public class Article implements Serializable {
public static final String VIEW_PREFIX = "ARTICLE_VIEWS_ID_";
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ -77,5 +81,9 @@ public class Article implements Serializable {
String summary = this.content.replaceAll("[^\\u4E00-\\u9FA5a-zA-Z]", " ");
return summary.substring(0,Math.min(200,summary.length()));
}
// 解析正文内容为html
public String showHtml() {
return MarkdownUtil.parse(this.content);
}
}

@ -199,4 +199,12 @@ public class ArticleService {
return articleMapper.hotList(limit);
}
/**
* 更新文章浏览量
* @param id 文章id
*/
public void viewArticle(Integer id) {
articleMapper.updateArticleViews(id);
}
}

@ -0,0 +1,41 @@
package cc.bnblogs.utils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author zfp@bnblogs.cc
* @createTime: 2022/10/21
* @desciption: cookie工具类
*/
public class CookieUtil {
public static String getCookie(HttpServletRequest request, String cookieName) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(cookieName)) {
return cookie.getValue();
}
}
}
return null;
}
public static void setCookie(HttpServletResponse response, String cookieName, String value, int cookieMaxAge) {
Cookie cookie = new Cookie(cookieName, value);
cookie.setPath("/");
cookie.setMaxAge(cookieMaxAge);
response.addCookie(cookie);
}
public static void setCookie(HttpServletResponse response, String cookieName, String value) {
// 有效期为7天
setCookie(response, cookieName, value, 7 * 24 * 60 * 60);
}
public static void deleteCookie(HttpServletResponse response, String cookieName) {
setCookie(response, cookieName, null, 0);
}
}

@ -0,0 +1,45 @@
package cc.bnblogs.utils;
import org.commonmark.Extension;
import org.commonmark.ext.gfm.tables.TablesExtension;
import org.commonmark.node.Heading;
import org.commonmark.node.Link;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
/**
* @author zfp@bnblogs.cc
* @createTime: 2022/10/21
*/
public interface MarkdownUtil {
Parser PARSER = Parser.builder().build();
// 引入表格支持插件
List<Extension> EXTENSIONS = Collections.singletonList(TablesExtension.create());
HtmlRenderer RENDERER = HtmlRenderer.builder()
.extensions(EXTENSIONS)
.attributeProviderFactory(attributeProviderContext -> (node, tagName, attributes) -> {
if (node instanceof Link) {
attributes.put("target", "_blank");// 链接都在新标签页中打开
}
if (node instanceof Heading) {
attributes.put("id", UUID.randomUUID().toString().replace("-", ""));
attributes.put("class", "title-toc"); // 生成目录
}
}).build();
/**
* 解析markdown为html
*
* @param markdownStr markdown源文件
* @return 对应的html格式
*/
static String parse(String markdownStr) {
Node document = PARSER.parse(markdownStr);
return RENDERER.render(document);
}
}

@ -55,6 +55,7 @@ website:
- SpringBoot
- 学习
description: All the truth is simple!
domain: http://localhost:8080 #域名
avatar: https://hugo.bnblogs.cc/images/img/20220215001349.png
nickname: barney
address: 广东 广州

@ -0,0 +1,309 @@
.fw-tool-bar {
padding: 10px;
position: relative;
background-color: #21252B;
}
.fw-tool-bar.fullScreen {
position: fixed;
top: 0;
left: 0;
width: 100vw;
}
.fw-tool-bar .fw-tool-item {
display: inline-block;
width: 32px;
height: 32px;
border-radius: 3px;
line-height: 32px;
text-align: center;
}
.fw-tool-bar .fw-tool-item:hover {
background-color: #43454B;
}
.fw-tool-bar svg {
height: 18px;
width: 18px;
display: inline-block;
}
.fw-tool-bar .fw-menu-headline {
position: relative;
}
.fw-tool-bar .fw-menu-headlist {
z-index: 9999;
position: absolute;
list-style: none;
background-color: #353B45;
color: #fff;
padding: 5px 0;
top: 20px;
left: -12px;
}
.fw-tool-bar .fw-menu-headlist li {
padding: 5px 20px;
}
.fw-tool-bar .fw-menu-headlist li:hover {
background-color: #43454B;
}
.fw-tool-bar #lw-article-content {
position: absolute;
background-color: #ffffff;
width: 50%;
right: 0;
bottom: 0;
overflow-y: scroll;
transform: translateY(100%);
z-index: 9999;
display: none;
}
.CodeMirror.CodeMirror-fullscreen {
top: 52px;
}
.fw-layer-content {
padding: 0 20px;
}
.fw-layer-content .fw-form-item {
margin: 10px 0;
color: #777;
font-size: 12px;
}
.fw-layer-content .fw-form-item select,
.fw-layer-content .fw-form-item input {
outline: none;
border: 1px solid #EAEEF3;
padding: 5px;
}
#lw-article-content {
font-size: 14px !important;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑, Arial", sans-serif;
white-space: normal;
overflow-wrap: break-word;
color: rgb(96, 98, 102);
-webkit-font-smoothing: antialiased;
padding: 20px;
}
#lw-article-content h1,
#lw-article-content h2,
#lw-article-content h3,
#lw-article-content h4,
#lw-article-content h5,
#lw-article-content h6 {
color: #303133;
font-size: 18px;
font-weight: 100;
height: 30px;
line-height: 30px;
margin: 0 0 15px;
position: relative;
padding-left: 20px;
}
#lw-article-content h1::before,
#lw-article-content h2::before,
#lw-article-content h3::before,
#lw-article-content h4::before,
#lw-article-content h5::before,
#lw-article-content h6::before {
position: absolute;
background-color: #c2005f;
font-size: 22px;
top: 0;
left: 0;
}
#lw-article-content h1::before {
content: "¶";
font-weight: normal;
color: #c2005f;
left: -5px;
background-color: transparent;
}
#lw-article-content h2::before {
content: ' ';
height: 30px;
width: 4px;
/*left: 5px;*/
border-radius: 2px;
}
#lw-article-content h3::before {
content: '';
width: 4px;
height: 30px;
/*left: 5px;*/
border-radius: 0 4px 4px 0;
font-size: 20px;
}
#lw-article-content h4,
#lw-article-content h5,
#lw-article-content h6 {
padding-left: 0;
}
#lw-article-content h4::before,
#lw-article-content h5::before,
#lw-article-content h6::before {
color: #c2005f;
/*margin-left: 5px;*/
font-size: 18px;
font-weight: normal;
background-color: transparent;
position: relative;
margin-right: 5px;
}
#lw-article-content h4::after,
#lw-article-content h5::after,
#lw-article-content h6::after {
color: #c2005f;
font-weight: normal;
background-color: transparent;
position: relative;
margin-left: 5px;
}
#lw-article-content h4::before {
content: 'ß';
}
#lw-article-content h4::after {
content: 'ß';
}
#lw-article-content h5::before {
content: "ç";
}
#lw-article-content h5::after {
content: "ç";
}
#lw-article-content h6::before {
content: "∫";
}
#lw-article-content h6::after {
content: "∫";
}
#lw-article-content li {
line-height: 30px;
}
#lw-article-content p {
margin: 0 0 15px;
line-height: 30px;
}
#lw-article-content p > code {
color: #c2005f;
display: inline-block;
padding: 0 5px;
border-radius: 3px;
}
#lw-article-content hr {
border: none;
height: 1px;
background-color: #e4e7ed;
margin: 0 0 15px;
}
#lw-article-content blockquote > p {
margin: 0;
}
#lw-article-content blockquote {
color: #c2005f;
background-color: #ecf8ff;
border-left: 5px solid #c2005f;
padding: 7px 15px;
margin: 0 0 15px;
font-size: 14px;
}
#lw-article-content a {
color: #c2005f;
/*text-decoration: none;*/
}
/*#lw-article-content a[href^='http']::after {*/
/* content: "\f1d9";*/
/* font: normal normal normal 14px/1 FontAwesome;*/
/* padding-left: 5px;*/
/*}*/
#lw-article-content img {
max-width: 100%;
border-radius: 4px;
transition: transform .35s, box-shadow .35s;
border: 1px solid #cccccc;
}
#lw-article-content table {
max-width: 100%;
table-layout: fixed;
color: #909399;
margin-bottom: 15px;
font-size: 13px;
border-top: 1px solid #ebeef5;
border-left: 1px solid #ebeef5;
border-collapse: collapse;
}
#lw-article-content table thead th {
font-weight: 500;
background: #ebeef5;
padding: 8px;
min-width: 100px;
text-align: center;
border-bottom: 1px solid #ebeef5;
border-right: 1px solid #ebeef5;
}
#lw-article-content table tbody td {
padding: 8px;
text-align: center;
border-bottom: 1px solid #ebeef5;
border-right: 1px solid #ebeef5;
}
#lw-article-content {
box-sizing: border-box;
}
#lw-article-content ol,
#lw-article-content ul {
padding-left: 20px;
}
/* end */
#lw-article-content img:hover {
cursor: pointer;
}

@ -741,10 +741,6 @@ nav .lw-nav a i {
margin-top: 20px;
}
.lw-article-title p a::after {
content: ", ";
}
.lw-article .lw-article-right {
padding: 10px;
background-color: #fff;

@ -0,0 +1,6 @@
/* PrismJS 1.29.0
https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+bash+c+csharp+cpp+cil+cilkc+cilkcpp+cmake+csv+django+docker+git+go+go-module+gradle+http+java+javadoc+javadoclike+javastacktrace+json+json5+latex+makefile+markdown+markup-templating+mongodb+nginx+php+plsql+powerquery+powershell+python+jsx+tsx+scheme+sql+typescript+xml-doc+yaml&plugins=line-highlight+line-numbers+file-highlight+toolbar+copy-to-clipboard+download-button */
code[class*=language-],pre[class*=language-]{color:#ccc;background:0 0;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}
pre[data-line]{position:relative;padding:1em 0 1em 3em}.line-highlight{position:absolute;left:0;right:0;padding:inherit 0;margin-top:1em;background:hsla(24,20%,50%,.08);background:linear-gradient(to right,hsla(24,20%,50%,.1) 70%,hsla(24,20%,50%,0));pointer-events:none;line-height:inherit;white-space:pre}@media print{.line-highlight{-webkit-print-color-adjust:exact;color-adjust:exact}}.line-highlight:before,.line-highlight[data-end]:after{content:attr(data-start);position:absolute;top:.4em;left:.6em;min-width:1em;padding:0 .5em;background-color:hsla(24,20%,50%,.4);color:#f4f1ef;font:bold 65%/1.5 sans-serif;text-align:center;vertical-align:.3em;border-radius:999px;text-shadow:none;box-shadow:0 1px #fff}.line-highlight[data-end]:after{content:attr(data-end);top:auto;bottom:.4em}.line-numbers .line-highlight:after,.line-numbers .line-highlight:before{content:none}pre[id].linkable-line-numbers span.line-numbers-rows{pointer-events:all}pre[id].linkable-line-numbers span.line-numbers-rows>span:before{cursor:pointer}pre[id].linkable-line-numbers span.line-numbers-rows>span:hover:before{background-color:rgba(128,128,128,.2)}
pre[class*=language-].line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}pre[class*=language-].line-numbers>code{position:relative;white-space:inherit}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}
div.code-toolbar{position:relative}div.code-toolbar>.toolbar{position:absolute;z-index:10;top:.3em;right:.2em;transition:opacity .3s ease-in-out;opacity:0}div.code-toolbar:hover>.toolbar{opacity:1}div.code-toolbar:focus-within>.toolbar{opacity:1}div.code-toolbar>.toolbar>.toolbar-item{display:inline-block}div.code-toolbar>.toolbar>.toolbar-item>a{cursor:pointer}div.code-toolbar>.toolbar>.toolbar-item>button{background:0 0;border:0;color:inherit;font:inherit;line-height:normal;overflow:visible;padding:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}div.code-toolbar>.toolbar>.toolbar-item>a,div.code-toolbar>.toolbar>.toolbar-item>button,div.code-toolbar>.toolbar>.toolbar-item>span{color:#bbb;font-size:.8em;padding:0 .5em;background:#f5f2f0;background:rgba(224,224,224,.2);box-shadow:0 2px 0 0 rgba(0,0,0,.2);border-radius:.5em}div.code-toolbar>.toolbar>.toolbar-item>a:focus,div.code-toolbar>.toolbar>.toolbar-item>a:hover,div.code-toolbar>.toolbar>.toolbar-item>button:focus,div.code-toolbar>.toolbar>.toolbar-item>button:hover,div.code-toolbar>.toolbar>.toolbar-item>span:focus,div.code-toolbar>.toolbar>.toolbar-item>span:hover{color:inherit;text-decoration:none}

File diff suppressed because one or more lines are too long

@ -88,7 +88,8 @@
field: 'title',
align: 'center',
formatter: function (value, row) {
return `<a href="/admin/write.html?id=${row.id}">${value}</a>`
return `<a href="/admin/write.html?id=${row.id}" title="编辑文章">${value}</a>
<a target="_blank" title="打开文章" href="/${row.id}.html"><i class="fa fa-send" style="color: red"></i></a>`
}
},
{

@ -21,7 +21,7 @@
<nav class="lw-md-show">
<div class="lw-container lw-header lw-posr ">
<div class="lw-logo lw-fl">
<a th:href="@{/}">
<a th:href="@{/admin/}" title="后台管理">
<img th:src="${@webSite.logo eq null or @webSite.logo.length() <= 0}? '/static/image/logo.png': ${@webSite.logo}"
alt="Barney's Blog"
style="width: 70px;height: 70px;"

@ -1,332 +1,103 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="/static/plugin/bootstrap/css/bootstrap.min.css">
<!-- 可选的 Bootstrap 主题文件(一般不用引入) -->
<link rel="stylesheet" href="/static/plugin/bootstrap/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="/static/plugin/font-awesome/css/font-awesome.min.css">
<!-- 自定义css文件 -->
<link rel="stylesheet" href="/static/css/style.css">
<html xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/html" lang="en">
<head th:replace="common::header(~{::title},~{::link},~{::style})">
<title th:text="${article.title + ' - ' + @webSite.title}"></title>
<link rel="stylesheet" href="/static/css/detail.css">
<link rel="stylesheet" href="/static/plugin/prism/prism.css">
<style>
#article-toc {
list-style: none;
padding-left: 0;
margin-top: 10px;
}
#article-toc a {
color: #888;
padding: 5px;
text-decoration: none;
display: block;
}
#right-bottom-bar {
position: fixed;
right: 20px;
bottom: 50px;
}
#right-bottom-bar a {
display: block;
background-color: rgba(0, 0, 0, 0.5);
color: #FFFFFF;
width: 40px;
height: 40px;
line-height: 40px;
margin-top: 5px;
text-align: center;
}
#right-bottom-bar #to-top {
opacity: 0;
}
#toc-parent.toc-fixed {
position: fixed;
z-index: 999;
top: 10px;
width: 300px;
}
#lw-comment-form .lw-comment-submit {
background-color: #c2005f;
outline: none;
border: none;
padding: 5px 15px;
color: #fff;
border-radius: 5px;
}
</style>
</head>
<body>
<nav class="lw-md-show">
<div class="lw-container lw-header lw-posr ">
<div class="lw-logo lw-fl">
<a href="/">
<img src="/static/image/logo.png" alt="冷文的个人博客">
</a>
</div>
<span>让崇拜从这里开始,用代码做点好玩的事件,让每一天都变的充实起来!</span>
<div class="lw-fr lw-linkme">
<a href="#"><i class="fa fa-qq" aria-hidden="true"></i></a>
<a href="#"><i class="fa fa-wechat" aria-hidden="true"></i></a>
<a href="#"><i class="fa fa-weibo" aria-hidden="true"></i></a>
<a href="#"><i class="fa fa-envelope" aria-hidden="true"></i></a>
</div>
<div class="lw-nav lw-posa">
<a href="/"><i class="fa fa-home" aria-hidden="true"></i>首页</a>
<a href="#">技术分享</a>
<a href="#">闲言碎语</a>
<a href="#">个人随笔</a>
<a href="#"><i class="fa fa-users" aria-hidden="true"></i>友情链接</a>
<a href="#"><i class="fa fa-user" aria-hidden="true"></i>关于我</a>
<a href="#"><i class="fa fa-edit" aria-hidden="true"></i>留言板</a>
<a href="javascript:void(0)" class="lw-fr lw-search-btn" style="padding: 0;">
<i class="fa fa-search" aria-hidden="true"></i>
</a>
</div>
</div>
<body class="line-numbers">
<th:block th:include="common::nav"></th:block>
</nav>
<div class="lw-md-hidden lw-phone-header">
<a href="javascript:void(0)" class="lw-posa lw-phone-topbtn lw-search-show lw-search-btn"><i
class="fa fa-search"></i></a>
<a class="lw-index" href="/"><h1>冷文学习者</h1></a>
</div>
<div class="lw-md-hidden" style="height: 100px;"></div>
<div class="lw-container lw-main lw-posr">
<div class="lw-left-list">
<div class="lw-article-list">
<ol class="breadcrumb lw-crumb">
<li><a href="/">首页</a></li>
<li><a href="/">Freewind相关</a></li>
<li class="active">正文</li>
<li th:if="${article.type eq T(cc.bnblogs.pojo.Article).TYPE_ARTICLE}"><a th:href="@{/category/{id}.html(id=${article.category.id})}"
th:text="${article.category.name}"
></a></li>
<li class="active" th:if="${article.type eq T(cc.bnblogs.pojo.Article).TYPE_ARTICLE}">正文</li>
<li class="active" th:if="${article.type eq T(cc.bnblogs.pojo.Article).TYPE_PAGE}" th:text="${article.title}"></li>
</ol>
<div class="lw-article">
<div class="lw-article-title">
<h1>Freewind主题编辑器展示</h1>
<h1 th:text="${article.title}"></h1>
<p>
<i class="fa fa-clock-o lw-mr5"></i>2022-09-28 12:00
<i class="fa fa-eye lw-mr5 lw-ml10"></i>11283
<i class="fa fa-comment lw-ml10 lw-mr5"></i>9382
<i class="fa fa-folder lw-ml10 lw-mr5"></i> <a href="">Freewind相关</a>
<i class="fa fa-tags lw-ml10 lw-mr5"></i> <a href="">markdown</a><a href="">freewind</a><a
href="">codemirror</a>
<i class="fa fa-clock-o lw-mr5"></i>
<th:block th:text="${#dates.format(article.created,'yyyy-MM-dd HH:mm')}"></th:block>
<i class="fa fa-eye lw-mr5 lw-ml10">
</i>
<th:block th:text="${article.views}"></th:block>
<i class="fa fa-comment lw-ml10 lw-mr5">
</i>
<th:block th:text="${article.getCommentCount() > 0 ? article.getCommentCount() : 0}"></th:block>
<i th:if="${article.type eq T(cc.bnblogs.pojo.Article).TYPE_ARTICLE}"
class="fa fa-folder lw-ml10 lw-mr5"></i>
<a th:if="${article.type eq T(cc.bnblogs.pojo.Article).TYPE_ARTICLE}"
th:href="@{/category/{id}.html(id=${article.category.id})}"
th:text="${article.category.name}"></a>
<i th:if="${article.type eq T(cc.bnblogs.pojo.Article).TYPE_ARTICLE}"
class="fa fa-tags lw-ml10 lw-mr5">
</i> <a th:each="tag:${article.tags}"
th:if="${article.type eq T(cc.bnblogs.pojo.Article).TYPE_ARTICLE}"
th:href="@{/tag/{id}.html(id=${tag.getId()})}" th:text="${tag.name + ' '}"></a>
</p>
</div>
<div class="lw-article-content">
前言
Freewind主题终于迎来了1.4的更新,同时也有了自己的编辑器,编辑器基于
codemirror这款开源产品进行开发,同时也将编辑器抽出了一个项目,大家有兴趣可以参考
markdown之外的支持https://imagebed-1252410096.cos.ap-nanjing.myqcloud.com/2057/1e863a92e3cf418e930649d8067b73df.jpg
Codemirror官方文档:传送门
编辑器地址:Github
MD之外的功能展示
提示
我是一个成功提示
我是一个失败提示
我是一个信息提示
我是一个警告提示
消息
我是一个成功消息
我是一个成功消息
我是一个成功消息
我是一个成功消息
我是一个失败消息
我是一个失败消息
我是一个失败消息
我是一个失败消息
我是一个信息消息
我是一个信息消息
我是一个信息消息
我是一个信息消息
我是一个警告消息
我是一个警告消息
我是一个警告消息
我是一个警告消息
Tab栏
tab栏1tab栏2tab栏3
内容1
彩色分割线
颜色可以自定义
分组卡片
分组1分组1内容
分组2分组2内容
跳转按钮组
图标可改,采用 font-awesome
正常按钮
成功按钮
失败按钮
信息按钮
警告按钮
B站视频
音乐
支持单曲与歌单模式
Girl - Alexander 23
作词 : Alexander 23
作曲 : Alexander 23
Hey, I know we just met but... (尽管有些生疏)
Girl, tell me all of your secrets (女孩请你对我敞开心扉)
From the darkest to the deepest, uh (在黑暗的最深处)
I would love to know what's underneath those curls (有多少奥秘藏在卷发之下)
I've got 21 questions (21个问题已经待命)
How could someone of your essence,uh (像你这样的人)
End up in my arms (怎么会进入我的怀抱)
I'm not gonna lie to you, I'm a little suspicious (撒谎不是我本意,多疑在作怪)
Are you really mine or are you someone else's missus? (你是否归属于我?)
This feels way too good to be true and when that's the instance (若为一例,身心愉悦)
It usually is, usually is, is, is (当然是通常一例)
Girl, tell me all of your secrets (请对我敞开心扉)
From the darkest to the deepest, uh (不论黑暗与沉沦)
I would love to know what's underneath those curls (我想探寻卷发下的奥秘)
I've got 21 questions (想来21个连环发问)
How could someone of your essence, uh (别让你的真命天子看到)
End up in my arms (倒在我怀里的你)
You left me a voicemail, didn't know I had a voicemail (迷糊的你发来语音,以为我不知道)
Now I listen to it when I wanna hear your voice, girl (现在我沦陷在你的甜蜜中)
You're my favorite type of smoke that I have ever inhaled (沉沦在你的温柔乡)
You know you're a star, know you're a star, star, star (你是璀璨明星)
Girl, tell me all of your secrets (对我敞开心扉吧)
From the darkest to the deepest, uh (即便阴暗也好)
I would love to know what's underneath those curls (让我探寻你的秘密花园)
I've got 21 questions (发起真心提问)
How could someone of your essence, uh (我是你的真命天子)
End up in my arms (这个在臂弯中的你)
Baby, bring the beat back in (宝贝 把节奏找回来)
Girl, girl, girl, girl... (女孩)
End up in my- (沦陷在我的怀抱)
Way Down - MØ
作词 : Karen Marie Ørsted/Ajay Bhattacharyya/Cara Salimando/A.s. Govere/Letter Mbulu/Caiphus Semenya
作曲 : Karen Marie Ørsted/Ajay Bhattacharyya/Cara Salimando/A.s. Govere/Letter Mbulu/Caiphus Semenya
All of the day, all of the night (一整天 一整夜)
Flashing through the headlight (光亮一闪而过)
Lights in the sky and I'm gonna die (天上霓虹 我如临天堂)
And I'm gonna be alright (mhmm) (但我会安然无恙的)
And I hear it like a call from the wild (我仿佛听见野性的呼唤)
And I keep putting coal on the fire (我持续不断往火中加炭)
If I'm gonna lose my mind (如果我将失去理智)
Tell 'em I'ma do it stylin' (告诉他们我要按我的方式来)
Ooh, la la, ooh
I just wanna get ****** up with my baby (我只想和我的宝贝胡作非为)
Ooh, la la, ooh
Tell 'em not to worry about me (告诉他们不要担心我)
I'm on my way down (我正不断沉沦呢)
Ooh, la la, ooh
I just wanna get ****** up with my baby (我只想和我的宝贝胡作非为)
Ooh, la la, ooh
Catch me on the bottom, oh (来欲望的谷底抓我啊)
'Cause I'm on my way down (我正不断沉沦呢)
On my way down, on my way down (一路向下 直指谷底)
Time is up, time is up (时间到了 是时候了)
Time is up, time is up (时间到了 是时候了)
Catch me on the bottom, oh (来欲望的谷底抓我啊)
'Cause I'm on my way down (我正不断沉沦呢)
California (加利福尼亚)
All of my life, been trying to find the little bit of paradise (穷尽一生 寻找天堂的一丝一缕)
So I'm gonna play a video game (所以我要玩点刺激的电子游戏)
I've never been a socialite (我从来都不是什么社会名流)
I'm just waiting for the stars to align (我只是在等待天赐良机)
Yeah, waiting for the stars to align (是啊 等待天赐良机)
If I'm gonna lose my mind (如果我将失去理智)
Tell 'em I'ma do it stylin' (告诉他们我要按我的方式来)
Ooh, la la, ooh
I just wanna get ****** up with my baby (baby) (我只想和我的宝贝胡作非为)
Ooh, la la, ooh
Tell 'em not to worry about me (告诉他们不要担心我)
I'm on my way down (on my way down) (我正不断沉沦呢)
Ooh, la la, ooh
I just wanna get ****** up with my baby (baby) (我只想和我的宝贝胡作非为)
Ooh, la la, ooh
Catch me on the bottom, oh (来欲望的谷底抓我啊)
'Cause I'm on my way down (我正不断沉沦呢)
On my way down, on my way down (一路向下 直指谷底)
Time is up, time is up (时间到了 是时候了)
Time is up, time is up (时间到了 是时候了)
Time is up, time is up (时间到了 是时候了)
Catch me on the bottom, oh (来欲望的谷底抓我啊)
'Cause I'm on my way down (我正不断沉沦呢)
I'm, I'm on my way (一路向下)
I'm, I'm on my way down (我正不断沉沦呢)
I'm, I'm on my way (一路向下)
We should be together when we go down (我们应该抓紧彼此 当陷于深渊之时)
I'm, I'm on my way (一路向下)
I'm, I'm on my way down (我正不断沉沦呢)
I'm, I'm on my way (一路向下)
Catch me on the bottom, oh (来欲望的谷底抓我啊)
'Cause I'm on my way down (我正不断沉沦呢)
On my way down (一路向下 直指谷底)
Time is up, time is up (时间到了 是时候了)
Catch me on the bottom, oh (来欲望的谷底抓我啊)
'Cause I'm on my way down (我正不断沉沦呢)
California, where your dreams will come true (加利福尼亚 你梦想成真之地)
<div class="lw-article-content" id="lw-article-content" th:utext="${article.showHtml()}">
</div>
<ul class="lw-article-right">
<li>
@ -337,7 +108,8 @@
<path d="M676.5 701c-9 0-16.6-6.3-18.1-15-1.1-6-2.5-11.6-4.2-16.7l-0.1-0.2-0.1-0.2c-9.1-31.5-29.1-59-56.6-78-26.2 13.2-55.6 20.1-85.3 20.1-29.8 0-59.2-7-85.5-20.2-27.6 19-47.7 46.5-56.8 78.1-0.2 0.7-2.1 7.9-4.8 18.5-2 8.1-9.3 13.7-17.8 13.7h-10.7c-4.8 0-9.4-2-12.5-5.6-3.1-3.5-4.6-8.2-4-12.8 8.1-60.2 46.2-113.1 101.7-141.5l5.4-2.8 5.1 3.4c23.5 15.9 51.1 24.3 79.8 24.3 28.7 0 56.2-8.4 79.7-24.2l5.1-3.4 5.4 2.8c55.4 28.4 93.4 81.3 101.5 141.4 0.6 4.6-0.8 9.3-4 12.8s-7.7 5.6-12.5 5.6h-10.7zM512.2 526.3c-74.5 0-135-60-135-133.6S437.7 259 512.2 259s135 60 135 133.6c0 73.7-60.5 133.7-135 133.7z m0-222.4c-49.6 0-89.9 39.8-89.9 88.8s40.3 88.8 89.9 88.8c49.6 0 89.9-39.8 89.9-88.8s-40.3-88.8-89.9-88.8z"
fill="#FFFFFF" p-id="921"></path>
</svg>
<span>版权所属: <a href="https://kevinlu98.cn/">冷文学习者</a></span>
<span>版权所属: <a href="https://hugo.bnblos.cc/"><th:block
th:text="${@webSite.getNickname()}"></th:block></a></span>
</li>
<li>
<svg t="1664366893739" class="icon" viewBox="0 0 1024 1024" version="1.1"
@ -347,7 +119,8 @@
<path d="M610.2 324c22.6 20.5 33.8 49 33.8 85.2 0 26.6-7.5 50.2-22.4 70.7-5.6 6.9-22.2 22.4-49.6 46.5-12.5 10.5-21.8 21.4-27.8 32.6-7.7 12.9-11.5 27.8-11.5 44.7v13.9h-49v-13.9c0-20.1 3.8-37.7 11.5-52.6 7.3-17.3 27.6-40.7 61-70.1 8.1-8.1 14.9-15.3 20.5-21.8 11.7-15.3 17.5-31.2 17.5-47.7 0-24.2-6.6-42.9-19.9-56.2-14.1-14.1-34.1-21.2-59.8-21.2-29.8 0-52.2 9.9-67.1 29.6-12.9 17.3-19.3 40.5-19.3 69.5h-48.4c0-41.9 11.9-75.7 35.7-101.5 25-26.6 58.8-39.9 101.5-39.9 39.7 0.2 70.7 10.9 93.3 32.2z m-75.5 346.4c6.8 6.9 10.3 15.3 10.3 25.4 0 10.5-3.4 19.1-10.3 26-7.7 6.9-16.3 10.3-26 10.3-10.5 0-19.1-3.4-26-10.3-7.3-7.3-10.9-15.9-10.9-26 0-10.5 3.6-18.9 10.9-25.4 6.4-6.8 15.1-10.3 26-10.3 10.4 0 19.1 3.4 26 10.3z"
fill="#FFFFFF" p-id="1069"></path>
</svg>
<span>本文链接: <a href="https://kevinlu98.cn/archives/101.html">https://kevinlu98.cn/archives/101.html</a></span>
<span>本文链接: <a th:href="@{{id}.html(id=${article.id})}"
th:text="${@webSite.domain} + '/' + ${article.id}+'.html'"></a></span>
</li>
<li>
<svg t="1664366925081" class="icon" viewBox="0 0 1024 1024" version="1.1"
@ -461,194 +234,165 @@
</ul>
</div>
<div class="lw-right-list lw-md-show lw-posa">
<th:block th:fragment="right">
<div class="lw-right-item lw-profile">
<div class="lw-avatar-content lw-posr"
style="background-image:url(/static/image/5-120601094K3-50.gif);">
<div class="lw-avatar lw-posa">
<img src="/static/image/avatar.jpeg" alt="">
<img th:src="${@webSite.avatar}" src="/static/image/avatar.jpeg" alt="">
</div>
</div>
<ul class="lw-info">
<li><span>博主</span>Mr丶冷文</li>
<li><span>坐标</span>北京 昌平</li>
<li><span>标签</span>Java、Web设计、Python、大数据、爬虫</li>
<li><span>博主</span>
<th:block th:text="${@webSite.nickname}"></th:block>
</li>
<li><span>坐标</span>
<th:block th:text="${T(java.lang.String).join(' ',@webSite.address)}"></th:block>
</li>
<li><span>标签</span>
<th:block th:text="${T(java.lang.String).join('、',@webSite.tags)}"></th:block>
</li>
</ul>
</div>
<div class="lw-right-item lw-right-hot">
<h4><i class="fa fa-fire lw-mr5" aria-hidden="true"></i>热门文章</h4>
<ul class="lw-hot-list">
<li>
<a href="#">
<div class="lw-hot-img">
<span class="label label-danger lw-posa">1</span>
<img src="/static/image/1.jpg" alt="">
</div>
<p class="lw-hot-title">Freewind主题编辑器展示</p>
<p class="lw-hot-info"><i class="fa-solid fa-fire-flame-curved"></i> 65580 </p>
</a>
</li>
<li>
<a href="#">
<div class="lw-hot-img">
<span class="label label-warning lw-posa">2</span>
<img src="/static/image/2.jpg" alt="">
</div>
<p class="lw-hot-title">Conda虚拟环境使用</p>
<p class="lw-hot-info"><i class="fa-solid fa-fire-flame-curved"></i> 56283 </p>
</a>
</li>
<li>
<a href="#">
<div class="lw-hot-img">
<span class="label label-info lw-posa">3</span>
<img src="/static/image/3.jpg" alt="">
</div>
<p class="lw-hot-title">纯 CSS 图片碎裂动画教程</p>
<p class="lw-hot-info"><i class="fa-solid fa-fire-flame-curved"></i> 52213 </p>
</a>
</li>
<li>
<a href="#">
<div class="lw-hot-img">
<span class="label label-default lw-posa">4</span>
<img src="/static/image/4.jpg" alt="">
</div>
<p class="lw-hot-title">Spring Boot 3.0 M1 发布</p>
<p class="lw-hot-info"><i class="fa-solid fa-fire-flame-curved"></i> 23132 </p>
</a>
</li>
<li>
<a href="#">
<!--/*@thymesVar id="hots" type="java.util.List<cc.bnblogs.pojo.Article>"*/-->
<li th:each="hot,it:${hots}">
<a th:href="@{/{id}.html(id=${hot.id})}" target="_blank">
<div class="lw-hot-img">
<span class="label label-default lw-posa">5</span>
<img src="/static/image/5.jpg" alt="">
</div>
<p class="lw-hot-title">异步上传文件显示进度条</p>
<p class="lw-hot-info"><i class="fa-solid fa-fire-flame-curved"></i> 12322 </p>
<span class="label label-danger lw-posa" th:if="${it.index eq 0}">1</span>
<span class="label label-warning lw-posa" th:if="${it.index eq 1}">2</span>
<span class="label label-info lw-posa" th:if="${it.index eq 2}">3</span>
<span class="label label-default lw-posa" th:if="${it.index > 2}"
th:text="${it.index+1}"></span>
<img th:src="${@defaultImages.cover(hot.cover)}" alt="">
</div>
<p class="lw-hot-title" th:text="${hot.title}"></p>
<p class="lw-hot-info"><i class="fa fa-eye lw-mr5"></i>
<th:block th:text="${hot.views}"></th:block>
</p>
</a>
</li>
</ul>
</div>
<div class="lw-right-item lw-tag-cloud">
<h4><i class="fa fa-tags lw-mr5" aria-hidden="true"></i>标签云</h4>
<a href="https://www.kevinlu98.cn/tag/freewind/" title="freewind">
freewind</a>
<a href="https://www.kevinlu98.cn/tag/typecho/" title="typecho">
typecho</a>
<a href="https://www.kevinlu98.cn/tag/%E6%8F%92%E4%BB%B6/" title="插件">
插件</a>
<a href="https://www.kevinlu98.cn/tag/emlog/" title="emlog">
emlog</a>
<a href="https://www.kevinlu98.cn/tag/java/" title="java">
java</a>
<a href="https://www.kevinlu98.cn/tag/%E4%B8%BB%E9%A2%98/" title="主题">
主题</a>
<a href="https://www.kevinlu98.cn/tag/%E8%87%AA%E7%94%B1%E4%B9%8B%E9%A3%8E/" title="自由之风">
自由之风</a>
<a href="https://www.kevinlu98.cn/tag/%E5%9B%BE%E5%BA%8A/" title="图床">
图床</a>
<a href="https://www.kevinlu98.cn/tag/%E5%86%B7%E6%96%87%E5%9B%BE%E5%BA%8A/" title="冷文图床">
冷文图床</a>
<a href="https://www.kevinlu98.cn/tag/markdown/" title="markdown">
markdown</a>
<a href="https://www.kevinlu98.cn/tag/gitee/" title="gitee">
gitee</a>
<a href="https://www.kevinlu98.cn/tag/springboot/" title="springboot">
springboot</a>
<a href="https://www.kevinlu98.cn/tag/linux/" title="linux">
linux</a>
<a href="https://www.kevinlu98.cn/tag/mac/" title="mac">
mac</a>
<a href="https://www.kevinlu98.cn/tag/%E5%AD%A6%E4%B9%A0/" title="学习">
学习</a>
<a href="https://www.kevinlu98.cn/tag/python/" title="python">
python</a>
<a href="https://www.kevinlu98.cn/tag/conda/" title="conda">
conda</a>
<a href="https://www.kevinlu98.cn/tag/%E7%9B%B8%E5%86%8C/" title="相册">
相册</a>
<a href="https://www.kevinlu98.cn/tag/jsDelivr/" title="jsDelivr">
jsDelivr</a>
<a href="https://www.kevinlu98.cn/tag/cdn/" title="cdn">
cdn</a>
<a href="https://www.kevinlu98.cn/tag/codemirror/" title="codemirror">
codemirror</a>
<a href="https://www.kevinlu98.cn/tag/freedom/" title="freedom">
freedom</a>
<a href="https://www.kevinlu98.cn/tag/%E8%85%BE%E8%AE%AFcos/" title="腾讯cos">
腾讯cos</a>
<a href="https://www.kevinlu98.cn/tag/cos/" title="cos">
cos</a>
<a href="https://www.kevinlu98.cn/tag/%E7%A7%81%E4%BA%BA%E5%9B%BE%E5%BA%8A/" title="私人图床">
私人图床</a>
<a href="https://www.kevinlu98.cn/tag/%E6%AC%A2%E8%BF%8E%E9%A1%B5/" title="欢迎页">
欢迎页</a>
<a href="https://www.kevinlu98.cn/tag/%E7%99%BB%E5%BD%95%E6%B3%A8%E5%86%8C/" title="登录注册">
登录注册</a>
<a href="https://www.kevinlu98.cn/tag/%E6%95%99%E7%A8%8B%E4%B8%8B%E8%BD%BD/" title="教程下载">
教程下载</a>
<a href="https://www.kevinlu98.cn/tag/itjc8/" title="itjc8">
itjc8</a>
<a href="https://www.kevinlu98.cn/tag/%E8%99%9A%E6%8B%9F%E6%9C%BA/" title="虚拟机">
虚拟机</a>
<!--/*@thymesVar id="tags" type="java.util.List<cc.bnblogs.pojo.Tag>"*/-->
<a th:each="tag:${tags}" th:href="@{/tag/{id}.html(id=${tag.id})}" th:title="${tag.name}"
th:text="${tag.name}"></a>
</div>
</th:block>
<div class="lw-right-item" id="toc-parent" th:if="${article.type eq T(cc.bnblogs.pojo.Article).TYPE_ARTICLE}">
<h4><i class="fa fa-bars lw-mr5">文章目录</i></h4>
<ul id="article-toc"></ul>
</div>
</div>
</div>
<th:block th:fragment="footer">
<div id="right-bottom-bar">
<a id="to-top" href="javascript:void(0)"><i class="fa fa-arrow-up"></i></a>
<a target="_blank"
th:href="${T(java.lang.String).format('tencent://message/?uin=%s&amp;Site=&amp;menu=yes',@webSite.qq)}"><i
class="fa fa-qq"></i></a>
</div>
<div class="lw-friend-link">
<div class="lw-container">
<h2>友情链接</h2>
<a href="">冷文学习者</a>
<a href="">冷文博客</a>
<a href="">冷文聊编程</a>
<a href="">GetHub</a>
<a href="">CSDN</a>
<a href="">百度一下</a>
<a href="">新浪微博</a>
<a href="">谷歌搜索</a>
<a href="">知乎</a>
<a href="">掘金</a>
<!--/*@thymesVar id="friends" type="java.util.List<cc.bnblogs.pojo.Friends>"*/-->
<a th:each="friend:${friends}" target="_blank" th:href="${friend.link}" th:text="${friend.title}"></a>
</div>
</div>
<footer>
<p>冷文学习者 版权所有 <span class="lw-mr5"></span>Copyright © www.kevinlu98.cn All Rights Reserved.</p>
<p>备案号:陕ICP备19024566-1号 京公网安备 11011402012109号</p>
</footer>
<footer th:utext="${@webSite.footer}"></footer>
<div class="lw-mask" id="lw-search-box">
<div class="lw-search-conetnt">
<a href="javascript:void(0)" class="lw-search-close lw-posa"><i class="fa fa-close"></i></a>
<div class="lw-search-input lw-posr">
<form action="" method="post">
<input type="text" placeholder="请输入搜索关键字...">
<form th:action="@{/search.html}" method="get">
<input type="text" required name="keyword" placeholder="请输入搜索关键字...">
<button class="lw-posa"><i class="fa fa-search lw-mr5"></i>搜索</button>
</form>
</div>
<p>推荐关键字:
<a href="javascript:void (0)">独立下载</a>
<a href="javascript:void (0)">评论通知</a>
<a href="javascript:void (0)">点赞</a>
<a href="javascript:void (0)">非插件</a>
<a href="javascript:void (0)">tp5</a>
<a href="javascript:void (0)">ajax</a>
<a href="javascript:void (0)">json</a>
<a href="javascript:void (0)">IO模型</a>
<a href="javascript:void (0)">跨域</a>
<a href="javascript:void (0)">javascript</a>
<a href="javascript:void (0)">springboot</a>
<a href="javascript:void (0)">视频剪辑</a>
<a href="javascript:void (0)">后期</a>
<a href="javascript:void (0)">个人随笔</a>
<a class="lw-mr5" th:each="keyword:${keywords}" th:href="@{/search.html(keyword=${keyword})}"
th:text="${keyword}" th:title="${keyword}"></a>
</p>
</div>
</div>
<script src="/static/plugin/jquery/jquery-3.5.1.min.js"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="/static/plugin/bootstrap/js/bootstrap.min.js"></script>
<script src="/static/plugin/swiper-bundle/swiper-bundle.min.js"></script>
<script src="/static/js/main.js"></script>
</th:block>
<script src="/static/plugin/prism/prism.js"></script>
<script>
$(function () {
// h1-h6缩进
let offset = [10, 25, 40, 55, 70, 85]
let hTag = $('#lw-article-content .title-toc')
// 最多支持h6标签
let hMax = 6;
hTag.each((i, ele) => {
hMax = Math.min(ele.tagName.charAt(1), hMax)
})
for (let i = 0; i < offset.length; i++) {
offset[i] -= (hMax - 1) * 10
}
hTag.each((index, element) => {
let level = element.tagName.charAt(1);
let left = offset[level - 1];
$('#article-toc').append(`<li><a style="padding-left: ${left}px;" href="javascript:void(0);" data-id="${$(element).attr("id")}">${'- ' + $(element).text()}</a></li>`)
})
})
</script>
<script>
$(function () {
$(window).scroll(function () {
let toTop = $(window).scrollTop(); // 距离页面顶端的高度
let height = $(window).height(); // 窗口高度
// 判断滚动条高度大于屏幕高度一半时展示到顶部的按钮
if (toTop > height / 2) {
$('#to-top').stop().animate({
opacity: 1
}, 500);
} else {
$('#to-top').stop().animate({
opacity: 0
}, 500);
}
// 回到页面顶端
$('#to-top').on('click', function () {
$('body,html').stop().animate({
scrollTop: 0
})
})
// 目录浮动
$(window).scroll(function () {
let toTop = $(window).scrollTop()
let tagCloud = $('.lw-right-item.lw-tag-cloud');
// 标签云底部距离顶部的距离
let tagBottom = tagCloud.offset().top + tagCloud.height()
// 滚动条滚动的高度大于标签云的底部-10时进行浮动
if (toTop > tagBottom - 10) {
// toc-fixed控制目录是否浮动
$('#toc-parent').addClass('toc-fixed')
} else {
$('#toc-parent').removeClass('toc-fixed')
}
})
$('#article-toc').on('click', 'li a', function () {
let id = $(this).data('id');
$('body,html').stop().animate({
scrollTop: $(`#${id}`).offset().top
})
})
})
})
</script>
</body>
</html>
Loading…
Cancel
Save