111.【金橘社区1.0】

(一)、SpringBoot整合SpringSecurity

金橘社区官网: http://www.jsxs1.cn/
Gitee仓库地址: https://gitee.com/lwt121788/ckqn

1.导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.7</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.jsxs</groupId>
    <artifactId>Kumquat</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Kumquat</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--web 依赖   -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--测试启动类  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--     JDBC驱动器   -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--mysql连接驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>
        <!--自动生成代码依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>1.5.22</version>
        </dependency>
        <!--     thymeleaf   -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <version>2.7.7</version>
        </dependency>
        <!--   lombok     -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--    JSON-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.26</version>
        </dependency>
        <!--SpringSecurity -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.thymeleaf.extras/thymeleaf-extras-springsecurity4 -->
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity5</artifactId>
            <version>3.0.4.RELEASE</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <skip>true</skip>
            </configuration>
        </plugin>
        </plugins>
    </build>
</project>

2.数据库

CREATE DATABASE CQAN;
USE CQAN;

# 用户表

CREATE TABLE `ckqn_user` (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '自增id',
  `uid` varchar(200) NOT NULL COMMENT '用户编号',
  `role_id` int(10) NOT NULL COMMENT '角色编号',
  `username` varchar(100) NOT NULL COMMENT '用户名',
  `password` varchar(200) NOT NULL COMMENT '密码',
  `avatar` varchar(500) NOT NULL DEFAULT '/images/avatar/avatar-1.jpg' COMMENT '头像',
  `login_date` datetime NOT NULL COMMENT '登录时间',
  `gmt_create` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=840 DEFAULT CHARSET=utf8;
# 用户角色

CREATE TABLE `ckqn_user_role` (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '角色编号',
  `name` varchar(200) NOT NULL COMMENT '角色名称',
  `description` varchar(500) NOT NULL DEFAULT '无描述...' COMMENT '角色描述',
  `gmt_create` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

3.登入表单

       <form th:action="@{/code}" method="post">
          <div class="inputBox">
            <input type="text" placeholder="账户ID" name="username" id="name" required onblur="a1()" onkeyup="this.value=this.value.replace(/\s+/g,'')">
            <i id="username" style="z-index: 9999"></i>

          </div>
          <div class="inputBox">
            <input type="password" placeholder="密码" name="password" required onkeyup="this.value=this.value.replace(/\s+/g,'')">

          </div>
          <div class="inputBox">
            <input type="submit" value="登录">
          </div>
          <p class="forget">忘记密码?<a href="#">
            点击这里
          </a></p>
          <p class="forget">没有账户?<a href="#">
            注册
          </a></p>
        </form>

4. 添加配置类 SecurityConfig

package com.jsxs.kumquat.config;

import com.jsxs.kumquat.service.impl.CkqnUserServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @Author Jsxs
 * @Date 2023/4/10 20:56
 * @PackageName:com.jsxs.kumquat.config
 * @ClassName: SecurityConfig
 * @Description: TODO  授权文件
 * @Version 1.0
 */
@EnableWebSecurity
@Configuration
@Component
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    
    //  调用的是业务实现类
    @Resource
    private CkqnUserServiceImpl ckqnUserService;

    // 密码加密方式
    @Bean
    public PasswordEncoder passwordEncoder() {
    
    
        return new BCryptPasswordEncoder();
    }

    /**
     * 认证
     *
     * @param http
     * @throws Exception permitAll -> 无条件访问
     *                   authenticated -> 需要认证才能访问, /* 除了无条件的,其他都加上锁
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    
    
        //  首页所有人可以访问,但是功能页只有对应有权限的人才能访问
        http.authorizeRequests()
                .antMatchers("/", "/index.html", "/login.html", "/mainMenu.html", "/JsxsRoad.html", "/recommendedArticles.html", "/code", "/a3").permitAll()
                .antMatchers("/*").authenticated();
        super.configure(http);
        http.formLogin().loginPage("/login.html");

        // 登录配置
        http.formLogin()
                .usernameParameter("username") // 这个参数必须为username (约定大于配置)
                .passwordParameter("password") // 这个参数必须为password (约定大于配置)
                .loginPage("/login.html")  //登入页面是哪个?
                .loginProcessingUrl("/code") // 点击提交的时候跳转到哪里?
                .defaultSuccessUrl("/"); // 密码验证通过后我们跳转到哪里?
       
        // 注销配置
        http.headers().contentTypeOptions().disable();
        http.headers().frameOptions().disable(); // 图片跨域
        http.csrf().disable();//关闭csrf功能:跨站请求伪造,默认只能通过post方式提交logout请求(ajax如果要使用一定开启)
        http.logout().logoutSuccessUrl("/");
    }

    /**
     * 
     * @param auth
     * @throws Exception userDetailsService-》对哪个业务进行操作,passwordEncoder-》密码加密方式
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    
    
        auth.userDetailsService(ckqnUserService).passwordEncoder(passwordEncoder());
    }

    /**
     * 
     * @param web
     * @throws Exception 对静态资源不拦截: static目录可以省略
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
    
    
        web.ignoring().antMatchers("/css/**", "/assets/**", "/plugins/**", "/img/**", "/editor.md/**", "/Jquery/**", "/layui/**", "/qrcode/**");
    }

}

5.接口实现类 CkqnUserServiceImpl

CkqnUserServiceImpl

package com.jsxs.kumquat.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jsxs.kumquat.pojo.CkqnUser;
import com.jsxs.kumquat.mapper.CkqnUserMapper;
import com.jsxs.kumquat.pojo.CkqnUserRole;
import com.jsxs.kumquat.service.CkqnUserRoleService;
import com.jsxs.kumquat.service.CkqnUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 吉士先生
 * @since 2023-04-09
 * TODO 这里需要继承一个接口: UserDetailsService
 */
@Service
public class CkqnUserServiceImpl extends ServiceImpl<CkqnUserMapper, CkqnUser> implements CkqnUserService, UserDetailsService {
    
    
    // 1. 业务层接口
    @Resource
    CkqnUserService userService;
    // 2. 认证角色层接口
    @Resource
    CkqnUserRoleService roleService;
    // 3.session
    @Resource
    HttpSession session;

    /**
     * TODO 用户逻辑和认证
     *
     * @param uid
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String uid) throws UsernameNotFoundException {
    
    
        // 4. 通过用户名查询用户
        CkqnUser user = userService.getOne(new QueryWrapper<CkqnUser>().eq("uid", uid));

        // 5. 查询到的角色放入session
        session.setAttribute("loginUser", user);

        // 7.创建一个新的UserDetails对象,最后验证登陆的需要
        UserDetails userDetails = null;
        if (user != null) {
    
    
            System.out.println("未加密:" + user.getPassword());
            // 8.加密密码
            String BCryptPassword = new BCryptPasswordEncoder().encode(user.getPassword());
            // 登录后会将登录密码进行加密,然后比对数据库中的密码,数据库密码需要加密存储!
//            String password = user.getPassword();

            // 9. 创建一个集合来存放权限
            Collection<GrantedAuthority> authorities = getAuthorities(user);
            /**
             * TODO 实例化UserDetails对象
             * uid-> 前端username框传过来的数据
             * BCryptPassword-> 加密后的密码
             * authorities -》 认证列表
             */
            userDetails = new org.springframework.security.core.userdetails.User(uid, BCryptPassword,
                    true,
                    true,
                    true,
                    true, authorities);
        }
        return userDetails;
    }

    /**
     * @param user ->实体类
     * @return
     */
    private Collection<GrantedAuthority> getAuthorities(CkqnUser user) {
    
    
        List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
        // 1. 通过用户的第三个字段roleID再另一个表中查找数据据
        CkqnUserRole role = roleService.getById(user.getRoleId());
        // 2. 注意:这里每个权限前面都要加ROLE_。否在最后验证不会通过
        authList.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));
        return authList;
    }
}

两张表
在这里插入图片描述

6.前端认证问题

xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
sec:authorize="!isAuthenticated()" 没有被认证就是显示
sec:authorize="isAuthenticated()" 认证了才被显示

(二)、SpringBoot整合Ajax

1.登入表单

       <form th:action="@{/code}" method="post">
          <div class="inputBox">
            <input type="text" placeholder="账户ID" name="username" id="name" required onblur="a1()" onkeyup="this.value=this.value.replace(/\s+/g,'')">
            <--*******id 为username, 上面id为name-->
            <i id="username" style="z-index: 9999"></i>

          </div>
          <div class="inputBox">
            <input type="password" placeholder="密码" name="password" required onkeyup="this.value=this.value.replace(/\s+/g,'')">

          </div>
          <div class="inputBox">
            <input type="submit" value="登录">
          </div>
          <p class="forget">忘记密码?<a href="#">
            点击这里
          </a></p>
          <p class="forget">没有账户?<a href="#">
            注册
          </a></p>
        </form>

2. JavaScript

 // AJAX  -js
<script src="Jquery/jquery-3.6.1.js"></script> 
  function a1(){
    $.post({
      url:"http://localhost:8080/a3",
      data:{
   
   'name':$("#name").val()},
      success:function(data){
        if(data.toString()=='OK'){
          $("#username").css("color","green");
        }else{
          $("#username").css("color","red");
        }
        $("#username").html(data);
      }
    });
  }
  function a2(){
    $.post({
      url: "http://localhost:8080/a3",
      data: {
   
   'pwd': $("#pwd").val()},
      success: function (data) {
        if (data.toString()=='OK') {
          $("#userpwd").css("color", "green");
        } else {
          $("#userpwd").css("color", "red");
        }
        $("#userpwd").html(data);
      }
    });
  }

(三)、SpringBoot整合editor.md

前提需要我们导入editor.md的插件文件
在这里插入图片描述

1.编写页面

(1).前端页面

引入文件

 	<link rel="stylesheet" href="{/editor.md/examples/css/style.css" th:href="@{/editor.md/examples/css/style.css/}">
    <link rel="stylesheet" href="/editor.md/css/editormd.css" th:href="@{/editor.md/css/editormd.css}"/>
    <link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon"/>
    <script src="Jquery/jquery-3.6.1.js"></script>

在这里编写文件

        <div id="test-editormd">
            <textarea style="display:none;" name="content"></textarea>
        </div>

配置JS

<script src="/editor.md/examplesjs/jquery.min.js" th:src="@{/editor.md/examples/js/jquery.min.js}"></script>
<script src="/editor.md/editormd.js" th:src="@{/editor.md/editormd.js}"></script>
<script type="text/javascript">
    var testEditor;

    $(function () {
      
      

        $.get('/editor.md/examples/test.md', function (md) {
      
      
        //  这里的第一个参数,指的是:"编写页面的id": 第二个参数是: "配置" 
            testEditor = editormd("test-editormd", {
      
      
                width: "100%",  // 1.宽度
                height: "750px", // 2.高度
                path: '/editor.md/lib/', //3.配置文件 
                theme: "dark", //4.主题
                markdown:'#欢迎您来到金橘社区!!', //5.默认编辑页面
                // previewTheme: "dark",
                editorTheme: "pastel-on-dark", // 6.编辑页面主题
                imageUpload: true,   //7.文件上传
                imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"],  
                imageUploadURL: "/article/image/upload",  //8.图片上传URL
                toolbarIcons: function () {
      
       //9.组件
                    return ["undo", "redo", "|", "bold", "del", "italic", "quote", "ucwords", "uppercase", "lowercase", "|", "h1", "h2", "h3", "h4", "h5", "h6", "|", "list-ul", "list-ol", "hr", "|", "link", "reference-link", "image", "code", "preformatted-text", "code-block", "table", "datetime", "emoji", "html-entities", "pagebreak", "|", "goto-line", "watch", "preview", "fullscreen", "clear", "search", "|", "help", "info", "||", "publish"];
                },

                toolbarIconTexts: {
      
       //10.自定义发布按钮的组件
                    publish: "<span bgcolor='gray' style='font-family: 微软雅黑;font-weight: bold;color: #00FF00'>发布</span>"
                },

                toolbarHandlers: {
      
       //11. 提交文章上传的路径
                    publish: function (cm, icon, cursor, selection) {
      
      
                        mdEditorForm.method = "post";
                        mdEditorForm.action = "/article/publish";//提交至服务器的路径
                        mdEditorForm.submit();
                    }
                }
            });
        });
    });
</script>

全部文档信息

<!DOCTYPE html>
<html lang="zh" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
    <meta charset="utf-8"/>
    <title>金橘社区-文章编写</title>
    <link rel="stylesheet" href="{/editor.md/examples/css/style.css" th:href="@{/editor.md/examples/css/style.css/}">
    <link rel="stylesheet" href="/editor.md/css/editormd.css" th:href="@{/editor.md/css/editormd.css}"/>
    <link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon"/>
    <link rel="stylesheet" href="layui/css/layui.css" media="all">
    <script src="layui/layui.js" charset="utf-8"></script>
    <script src="Jquery/jquery-3.6.1.js"></script>
    <style>
        * {
      
      
            margin: 0;
            padding: 0;
        }

        .top-search {
      
      
            width: 680px;
            height: 45px;
            margin: 30px auto;

        }

        .search-box {
      
      
            display: flex;
            position: relative;
        }

        .search-left {
      
      
            width: 545px;
            height: 45px;
            border: 2px solid rgb(196, 199, 206);
            border-top-left-radius: 10px;
            border-bottom-left-radius: 10px;
            outline-color: rgb(242, 78, 130);
        }

        .icon-xiangji {
      
      
            position: absolute;
            right: 150px;
            top: 12px;
            font-size: 24px;
            color: rgb(196, 199, 206);
        }

        .search-right {
      
      
            color: #fff;
            font-size: 18px;
            width: 110px;
            height: 49px;
            border: 0px;
            border-top-right-radius: 10px;
            border-bottom-right-radius: 10px;
            background-color: rgb(242, 78, 130);
        }

        #su:hover {
      
      
            background: #14dc99;
        }
    </style>
</head>
<body>
<form name="mdEditorForm" method="post">
<div class="top-search" style="margin-top: 13px;">
    <button type="button" class="layui-btn layui-btn-primary1 layui-btn-lg" style="margin-top: 7px;margin-left: -1200px;"
            onclick="document.location.href='MyArticals.html'"><i class="layui-icon layui-icon-return"
                                                                  style="font-size: 20px; color: #1E9FFF;"></i><i
            style="color: #0e0c0d;font-family: 微软雅黑;font-weight: bold" onclick="return confirm('您还未保存,如果直接退出将不会保存数据。您确定直接退出?')">文章管理</i></button>
    <div class="search-box" style="    top: -45px;">
        <input type="text" name="title" class="search-left" placeholder="     请 输 入 文 章 标 题" required
               style="font-size: 20px;font-family: 微软雅黑;font-weight: bold;"
               onkeyup="this.value=this.value.replace(/\s+/g,'')"
        value="【无标题】">
        <span class="iconfont icon-xiangji"></span>
    </div>
    <ul sec:authorize="!isAuthenticated()" class="layui-nav" lay-bar="disabled" style="width: 40px; height: 0px;margin-left: 863px;margin-top: -100px;z-index: 9999">
        <li  class="layui-nav-item" lay-unselect="">
            <a href="javascript:;"><img src="/img/login.png" tppabs="http://t.cn/RCzsdCq" class="layui-nav-img" onclick="document.location.href='login.html'"></a>
            <dl class="layui-nav-child">
                <dd><a href="javascript:;" onclick="document.location.href='login.html'">登入</a></dd>
            </dl>
        </li>
    </ul>
    <ul sec:authorize="hasRole('ROLE_A')" class="layui-nav" lay-bar="disabled" style="width: 40px; height: 0px;margin-left: 863px;margin-top: -100px;z-index: 9999">
        <li  class="layui-nav-item" lay-unselect="">
            <a href="javascript:;"><img src="/img/user.jpg" tppabs="http://t.cn/RCzsdCq" class="layui-nav-img" onclick="document.location.href='#'"></a>
            <dl class="layui-nav-child">
                <dd><a href="javascript:;">个人中心</a></dd>
                <dd><a href="javascript:;" th:href="@{/login.html}">切换账号</a></dd>
                <dd><a href="javascript:;" th:href="@{/logout}">注销</a></dd>
            </dl>
        </li>
    </ul>
    <ul class="layui-nav" lay-bar="disabled" style="width: 40px; height: 0px;margin-left: 863px;margin-top: -100px;z-index: 9999">
        <li sec:authorize="hasRole('ROLE_B')" class="layui-nav-item" lay-unselect="">
            <a href="javascript:;"><img src="/img/user2.jpg" tppabs="http://t.cn/RCzsdCq" class="layui-nav-img" onclick="document.location.href='#'"></a>
            <dl class="layui-nav-child">
                <dd><a href="javascript:;">个人中心</a></dd>
                <dd><a href="javascript:;" onclick="document.location.href='login.html'">切换账号</a></dd>
                <dd><a href="javascript:;" th:href="@{/logout}">注销</a></dd>
            </dl>
        </li>
    </ul>
</div>
<div id="layout" style="margin-top: -41px;">
    <header>
    </header>
        <div id="test-editormd">
            <textarea style="display:none;" name="content"></textarea>
        </div>

</div>
</form>
<script src="/editor.md/examplesjs/jquery.min.js" th:src="@{/editor.md/examples/js/jquery.min.js}"></script>
<script src="/editor.md/editormd.js" th:src="@{/editor.md/editormd.js}"></script>
<script type="text/javascript">
    var testEditor;

    $(function () {
      
      

        $.get('/editor.md/examples/test.md', function (md) {
      
      
            testEditor = editormd("test-editormd", {
      
      
                width: "100%",
                height: "750px",
                path: '/editor.md/lib/',
                theme: "dark",
                markdown:'#欢迎您来到金橘社区!!',
                // previewTheme: "dark",
                editorTheme: "pastel-on-dark",
                imageUpload: true,
                imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
                imageUploadURL: "/article/image/upload",
                toolbarIcons: function () {
      
      
                    return ["undo", "redo", "|", "bold", "del", "italic", "quote", "ucwords", "uppercase", "lowercase", "|", "h1", "h2", "h3", "h4", "h5", "h6", "|", "list-ul", "list-ol", "hr", "|", "link", "reference-link", "image", "code", "preformatted-text", "code-block", "table", "datetime", "emoji", "html-entities", "pagebreak", "|", "goto-line", "watch", "preview", "fullscreen", "clear", "search", "|", "help", "info", "||", "publish"];
                },

                toolbarIconTexts: {
      
      
                    publish: "<span bgcolor='gray' style='font-family: 微软雅黑;font-weight: bold;color: #00FF00'>发布</span>"
                },

                toolbarHandlers: {
      
      
                    publish: function (cm, icon, cursor, selection) {
      
      
                        mdEditorForm.method = "post";
                        mdEditorForm.action = "/article/publish";//提交至服务器的路径
                        mdEditorForm.submit();
                    }
                }
            });
        });
    });
</script>
</body>
</html>

(2).后端页面

工具类

package com.jsxs.kumquat.utils;

/**
 * @Author Jsxs
 * @Date 2023/4/11 15:50
 * @PackageName:com.jsxs.kumquat.utils
 * @ClassName: FileUtils
 * @Description: TODO
 * @Version 1.0
 */

import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

/**
 * 文件上传工具类
 */
public class FileUtils {
    
    

    private static final String prePath = System.getProperty("user.dir") + "/src/main/resources/static/upload/";

    /**
     * 上传文件
     * @param file
     * @return 返回文件路径(以相对路径放回)
     */
    public static String uploadFile(MultipartFile file) {
    
    
        if(file.isEmpty()) {
    
    
            return "";
        }
        // 获取原文件名
        String originFileName = file.getOriginalFilename();
        // 我们通过UUID 来重新重组文件名
        String uid = UUID.randomUUID().toString();
        assert originFileName != null;
        String suffix = originFileName.substring(originFileName.lastIndexOf('.') + 1);
        String path = prePath + uid + "." + suffix;

        String returnPath = "/upload/" + uid + "." + suffix;
        File newFile = new File(path);
        if(newFile.getParentFile() != null && !newFile.getParentFile().exists()) {
    
    
            System.out.println("创建目录ing");
            // 上面的 newFile.getParentFile() 已经保证了不为null.
            if(newFile.getParentFile().mkdirs()) {
    
    
                System.out.println("创建目录成功");
            }else {
    
    
                System.out.println("创建目录失败");
                return "";
            }
        }
        try {
    
    
            file.transferTo(newFile);
        } catch (IOException e) {
    
    
            e.printStackTrace();
            return "";
        }
        return returnPath;
    }

}

文件上传

package com.jsxs.kumquat.controller;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jsxs.kumquat.pojo.CkqnBlog;
import com.jsxs.kumquat.pojo.CkqnUser;
import com.jsxs.kumquat.service.CkqnBlogService;
import com.jsxs.kumquat.utils.FileUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.UUID;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author 吉士先生
 * @since 2023-04-09
 */
@Controller
@RequestMapping("/article")
public class CkqnBlogController {
    
    
    @Resource
    CkqnBlogService ckqnBlogService;
    @Resource
    HttpSession session;
    // 文章上传
    @RequestMapping("/publish")
    public String publishArticle(CkqnBlog article) {
    
    
        CkqnUser user = (CkqnUser) session.getAttribute("loginUser");
        // 1.作者信息
        article.setAuthorId(user.getUid());
        article.setAuthorName(user.getUsername());
        article.setAuthorAvatar(user.getAvatar());
        // 2.博客ID
        String replace = UUID.randomUUID().toString().replace("-", "");
        article.setBid(replace);
        if (article.getTitle() == null) {
    
    
            System.out.println("标题为空?????????");
        }
        boolean res = ckqnBlogService.save(article);
        if (res) {
    
    
            return "tipSuccess";
        }
        return "tipFalse";
    }
    // 图片上传
    @RequestMapping("/image/upload")
    @ResponseBody
    public JSONObject imageUpload(@RequestParam("editormd-image-file") MultipartFile image) {
    
    
        JSONObject jsonObject = new JSONObject();
        if (image != null) {
    
    
            String path = FileUtils.uploadFile(image);
//            回调给 editor
            System.out.println(path);
            jsonObject.put("url", path);
            jsonObject.put("success", 1);
            jsonObject.put("message", "upload success!");
            return jsonObject;
        }
        jsonObject.put("success", 0);
        jsonObject.put("message", "upload error!");
        return jsonObject;
    }

    //  1.一篇详细文章
    @RequestMapping("/get/{id}")
    public ModelAndView getArticleById(@PathVariable(name = "id") int id) {
    
    
        ModelAndView modelAndView = new ModelAndView();
        CkqnBlog article = ckqnBlogService.getById(id);

        modelAndView.setViewName("WriteCenter/article");
        if (article == null) {
    
    
            modelAndView.addObject("article", new CkqnBlog());
        }
        modelAndView.addObject("article", article);
        return modelAndView;
    }

2.修改文件

(1).前端页面

需要引入数据

	<link rel="stylesheet"  th:href="@{/editor.md/examples/css/style.css/}">
  <link rel="stylesheet"  th:href="@{/editor.md/css/editormd.css}"/>
  <link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon"/>
  <script th:src="@{/Jquery/jquery-3.6.1.js}"></script>

被修改页面的展示

    <div class="col-md-12 mb-3">
      <div id="blog-content">
        <textarea required name="content" th:text="${blog.getContent()}" id="content" style="display:none;" rows="3" class="form-control"> </textarea>
      </div>
    </div>

js

<script th:src="@{/editor.md/examples/js/jquery.min.js}"></script>
<script th:src="@{/editor.md/editormd.js}"></script>
<script type="text/javascript">
  var testEditor;
  $(function() {
      
      
    testEditor = editormd("blog-content", {
      
      
      width : "100%", //1.
      height : "750px", //2.
      syncScrolling : "single", //3.单页
        path: '/editor.md/lib/', //4.路径
        theme: "dark", //5.黑暗主题
        previewTheme: "gary",
        editorTheme: "pastel-on-dark",
        imageUpload: true, //6.文件上传
        imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
        imageUploadURL: "/article/image/upload",  //7.文件上传对象
      onload : function() {
      
      
        console.log('onload', this);
      },
        toolbarIcons: function () {
      
      
          return ["undo", "redo", "|", "bold", "del", "italic", "quote", "ucwords", "uppercase", "lowercase", "|", "h1", "h2", "h3", "h4", "h5", "h6", "|", "list-ul", "list-ol", "hr", "|", "link", "reference-link", "image", "code", "preformatted-text", "code-block", "table", "datetime", "emoji", "html-entities", "pagebreak", "|", "goto-line", "watch", "preview", "fullscreen", "clear", "search", "|", "help", "info", "||", "publish"];
        },

        toolbarIconTexts: {
      
        //8. 提交修改的按钮
          publish: "<span bgcolor='gray' style='color: #00FF00;font-weight: bold;font-family: 微软雅黑'>提交修改</span>"
        },

        toolbarHandlers: {
      
       //9.修改文章的路径
          publish: function (cm, icon, cursor, selection) {
      
      
            mdEditorForm.method = "post";
            mdEditorForm.action = "/article/toupdate";//提交至服务器的路径
            mdEditorForm.submit();
          }
        },
      onfullscreen : function() {
      
      
        console.log("onfullscreen");
        document.getElementsByClassName("navbar")[0].style.display="none";
      },
      onfullscreenExit : function() {
      
      
        console.log("onfullscreenExit");
        document.getElementsByClassName("navbar")[0].style.display="";
      }
      });
    });
</script>

全部前端

<!DOCTYPE html>
<html lang="zh" xmlns:sec="http://www.thymeleaf.org/extras/spring-security" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="utf-8"/>
  <title>金橘社区-文章修改</title>
  <link rel="stylesheet"  th:href="@{/editor.md/examples/css/style.css/}">
  <link rel="stylesheet"  th:href="@{/editor.md/css/editormd.css}"/>
  <link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon"/>
  <link rel="stylesheet" th:href="@{/layui/css/layui.css}" media="all">
  <script th:src="@{/layui/layui.js}" charset="utf-8"></script>
  <script th:src="@{/Jquery/jquery-3.6.1.js}"></script>
  <style>
    * {
      
      
      margin: 0;
      padding: 0;
    }

    .top-search {
      
      
      width: 680px;
      height: 45px;
      margin: 30px auto;

    }

    .search-box {
      
      
      display: flex;
      position: relative;
    }

    .search-left {
      
      
      width: 545px;
      height: 45px;
      border: 2px solid rgb(196, 199, 206);
      border-top-left-radius: 10px;
      border-bottom-left-radius: 10px;
      outline-color: rgb(242, 78, 130);
    }

    .icon-xiangji {
      
      
      position: absolute;
      right: 150px;
      top: 12px;
      font-size: 24px;
      color: rgb(196, 199, 206);
    }

    .search-right {
      
      
      color: #fff;
      font-size: 18px;
      width: 110px;
      height: 49px;
      border: 0px;
      border-top-right-radius: 10px;
      border-bottom-right-radius: 10px;
      background-color: rgb(242, 78, 130);
    }

    #su:hover {
      
      
      background: #14dc99;
    }

  </style>
</head>
<body>
<form name="mdEditorForm" method="post">
  <!-- 隐藏域 uid -->
  <input type="hidden" name="bid" th:value="${blog.getBid()}">
  <div class="top-search" style="margin-top: 13px;">
    <a type="button" class="layui-btn layui-btn-primary1 layui-btn-lg" style="margin-top: 7px;margin-left: -1200px;"
            th:href="@{/MyArticals.html}"><i class="layui-icon layui-icon-return"
                                             style="font-size: 20px; color: #1E9FFF;"></i><i
            style="color: #0e0c0d;font-family: 微软雅黑;font-weight: bold" onclick="return confirm('您还未保存更改数据,如果直接退出将不会保存更改的数据。您确定直接退出?')">文章管理</i></a>
    <div class="search-box" style="    top: -45px;">
<!--      标题-->
      <input type="text" name="title" class="search-left" placeholder="     请 输 入 文 章 标 题" required
             style="font-size: 20px;font-family: 微软雅黑;font-weight: bold;"
             onkeyup="this.value=this.value.replace(/\s+/g,'')"
             th:value="${blog.title}">
      <span class="iconfont icon-xiangji"></span>
    </div>
    <ul class="layui-nav" lay-bar="disabled" style="width: 40px; height: 0px;margin-left: 863px;margin-top: -100px;z-index: 9999">
      <li sec:authorize="!isAuthenticated()" class="layui-nav-item" lay-unselect="">
        <a href="javascript:;"><img src="/img/login.png" tppabs="http://t.cn/RCzsdCq" class="layui-nav-img" onclick="document.location.href='login.html'"></a>
        <dl class="layui-nav-child">
          <dd><a href="javascript:;" onclick="document.location.href='login.html'">登入</a></dd>
        </dl>
      </li>
    </ul>
    <ul class="layui-nav" lay-bar="disabled" style="width: 40px; height: 0px;margin-left: 863px;margin-top: -100px;z-index: 9999">
      <li sec:authorize="isAuthenticated()" class="layui-nav-item" lay-unselect="">
        <a href="javascript:;"><img src="/img/user.jpg" tppabs="http://t.cn/RCzsdCq" class="layui-nav-img" onclick="document.location.href='#'"></a>
        <dl class="layui-nav-child">
          <dd><a href="javascript:;">个人中心</a></dd>
          <dd><a href="javascript:;" th:href="@{/login.html}">切换账号</a></dd>
          <dd><a href="javascript:;" th:href="@{/logout}">注销</a></dd>
        </dl>
      </li>
    </ul>
  </div>
  <div id="layout" style="margin-top: -41px;">
    <header>
    </header>
    <div class="col-md-12 mb-3">
      <div id="blog-content">
        <textarea required name="content" th:text="${blog.getContent()}" id="content" style="display:none;" rows="3" class="form-control"> </textarea>
      </div>
    </div>
  </div>
  </div>
</form>
<script th:src="@{/editor.md/examples/js/jquery.min.js}"></script>
<script th:src="@{/editor.md/editormd.js}"></script>
<script type="text/javascript">
  var testEditor;
  $(function() {
      
      
    testEditor = editormd("blog-content", {
      
      
      width : "100%",
      height : "750px",
      syncScrolling : "single",
        path: '/editor.md/lib/',
        theme: "dark",
        previewTheme: "gary",
        editorTheme: "pastel-on-dark",
        imageUpload: true,
        imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
        imageUploadURL: "/article/image/upload",
      onload : function() {
      
      
        console.log('onload', this);
      },
        toolbarIcons: function () {
      
      
          return ["undo", "redo", "|", "bold", "del", "italic", "quote", "ucwords", "uppercase", "lowercase", "|", "h1", "h2", "h3", "h4", "h5", "h6", "|", "list-ul", "list-ol", "hr", "|", "link", "reference-link", "image", "code", "preformatted-text", "code-block", "table", "datetime", "emoji", "html-entities", "pagebreak", "|", "goto-line", "watch", "preview", "fullscreen", "clear", "search", "|", "help", "info", "||", "publish"];
        },

        toolbarIconTexts: {
      
      
          publish: "<span bgcolor='gray' style='color: #00FF00;font-weight: bold;font-family: 微软雅黑'>提交修改</span>"
        },

        toolbarHandlers: {
      
      
          publish: function (cm, icon, cursor, selection) {
      
      
            mdEditorForm.method = "post";
            mdEditorForm.action = "/article/toupdate";//提交至服务器的路径
            mdEditorForm.submit();
          }
        },
      onfullscreen : function() {
      
      
        console.log("onfullscreen");
        document.getElementsByClassName("navbar")[0].style.display="none";
      },
      onfullscreenExit : function() {
      
      
        console.log("onfullscreenExit");
        document.getElementsByClassName("navbar")[0].style.display="";
      }
      });
    });
</script>
</body>
</html>

(2).后端页面

package com.jsxs.kumquat.controller;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jsxs.kumquat.pojo.CkqnBlog;
import com.jsxs.kumquat.pojo.CkqnUser;
import com.jsxs.kumquat.service.CkqnBlogService;
import com.jsxs.kumquat.utils.FileUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.UUID;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author 吉士先生
 * @since 2023-04-09
 */
@Controller
@RequestMapping("/article")
public class CkqnBlogController {
    
    
    @Resource
    CkqnBlogService ckqnBlogService;
    @Resource
    HttpSession session;
    // 文章上传
    @RequestMapping("/publish")
    public String publishArticle(CkqnBlog article) {
    
    
        CkqnUser user = (CkqnUser) session.getAttribute("loginUser");
        // 1.作者信息
        article.setAuthorId(user.getUid());
        article.setAuthorName(user.getUsername());
        article.setAuthorAvatar(user.getAvatar());
        // 2.博客ID
        String replace = UUID.randomUUID().toString().replace("-", "");
        article.setBid(replace);
        if (article.getTitle() == null) {
    
    
            System.out.println("标题为空?????????");
        }
        boolean res = ckqnBlogService.save(article);
        if (res) {
    
    
            return "tipSuccess";
        }
        return "tipFalse";
    }
    // 文件上传
    @RequestMapping("/image/upload")
    @ResponseBody
    public JSONObject imageUpload(@RequestParam("editormd-image-file") MultipartFile image) {
    
    
        JSONObject jsonObject = new JSONObject();
        if (image != null) {
    
    
            String path = FileUtils.uploadFile(image);
//            回调给 editor
            System.out.println(path);
            jsonObject.put("url", path);
            jsonObject.put("success", 1);
            jsonObject.put("message", "upload success!");
            return jsonObject;
        }
        jsonObject.put("success", 0);
        jsonObject.put("message", "upload error!");
        return jsonObject;
    }

    //  1.一篇详细文章
    @RequestMapping("/get/{id}")
    public ModelAndView getArticleById(@PathVariable(name = "id") int id) {
    
    
        ModelAndView modelAndView = new ModelAndView();
        CkqnBlog article = ckqnBlogService.getById(id);

        modelAndView.setViewName("WriteCenter/article");
        if (article == null) {
    
    
            modelAndView.addObject("article", new CkqnBlog());
        }
        modelAndView.addObject("article", article);
        return modelAndView;
    }

    // 开始修改
    @RequestMapping("/update/editor/{authorId}/{bid}")
    public String updateArticleByUser(@PathVariable("authorId") String authorId, @PathVariable("bid") String bid, Model model) {
    
    
//        CkqnUser user = (CkqnUser)session.getAttribute("loginUser");
        QueryWrapper<CkqnBlog> wrapper = new QueryWrapper<>();
        //  查询uid
        CkqnBlog blog = ckqnBlogService.getOne(wrapper.eq("bid", bid));
        System.out.println(authorId + " " + bid);
        // 2.查询作者
        if (!blog.getAuthorId().equals(authorId)) {
    
    
            System.out.println("对不起,你在非法编辑");
            //  直接注销账号
            return "redirect:/index.html";
        }
        // 3. 存放文章
        model.addAttribute("blog", blog);
        //  4.没有重定向
        return "WriteCenter/update";
    }

    //    修改的操作
    @PostMapping("/toupdate")
    public String editor(CkqnBlog blog) {
    
    
        QueryWrapper<CkqnBlog> wrapper = new QueryWrapper<>();
        System.out.println(blog);
        CkqnBlog queryBlog = ckqnBlogService.getOne(wrapper.eq("bid", blog.getBid()));
        queryBlog.setTitle(blog.getTitle());
        queryBlog.setCategoryId(blog.getCategoryId());
        queryBlog.setContent(blog.getContent());
        boolean b = ckqnBlogService.updateById(queryBlog);
        if (b) {
    
    
            return "tipSuccess";
        }
        return "tipFalse";

    }
}


3.文章展示

(1).前端页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
    <meta charset="UTF-8">
    <title>金橘社区-文章展示</title>
    <link rel="stylesheet" th:href="@{/editor.md/css/examples/style.css}" />
    <link rel="stylesheet" th:href="@{/editor.md/css/editormd.css}" />
    <link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon" />
    <script th:src="@{/Jquery/jquery-3.6.1.js}"></script>
    <link rel="stylesheet" th:href="@{/css/commons.css}">
    <link rel="stylesheet" th:href="@{/css/blog_detail.css}">
    <link rel="stylesheet" th:href="@{/layui/css/layui.css}" media="all">
    <style>
        .arrow{
      
      
            border: 9px solid transparent;
            border-bottom-color: #3DA0DB;
            width: 0px;
            height: 0px;
            top:0px
        }
        .stick{
      
      
            width: 8px;
            height: 14px;
            border-radius: 1px;
            background-color: #3DA0DB;
            top:15px;
        }
        #back_top div{
      
      
            position: absolute;
            margin: auto;
            right: 0px;
            left: 0px;
        }
        #back_top{
      
      
            background-color: #dddddd;
            height: 38px;
            width: 38px;
            border-radius: 3px;
            display: block;
            cursor: pointer;
            position: fixed;
            right: 50px;
            bottom: 100px;
            display: none;
        }
    </style>
</head>
<body>
<div class="top-search" style="margin-top: 12px;">
    <a type="button" class="layui-btn layui-btn-primary1 layui-btn-lg" style="margin-top: 42px;margin-left: 1px;"
           th:href="@{/MyArticals.html}" ><i class="layui-icon layui-icon-return"
                                                                  style="font-size: 20px; color: #1E9FFF;"></i><i
            style="color: #0e0c0d;font-family: 微软雅黑;font-weight: bold">文章管理</i></a>
</div>
<span class="js-cursor-container"></span>
<div id="article"></div>
<div id="back_top">
    <div class="arrow"></div>
    <div class="stick"></div>
</div>
<!-- .container 作为页面的版心 -->
<div class="container">
    <!-- 左侧个人信息 -->
    <div class="left">
        <!-- 整个用户信息区 -->
        <div class="card">
            <img  th:src="@{/img/login.png}" alt="">
            <h3 th:text="${article.getAuthorName()}"></h3>
            <a href="#">github 地址</a>
            <div class="counter">
                <span>文章</span>
                <span>分类</span>
            </div>
            <div class="counter">
                <span>X</span>
                <span>X</span>
            </div>
        </div>
    </div>
    <!-- 右侧内容详情 -->
    <div class="right" style="overflow: auto">
        <!-- 包裹整个博客的内容详情 -->
        <div class="blog-content">
            <h3 style="color: #e8136f" th:text="${article.title}"></h3>
            <div class="date" th:text="${#dates.format(article.getGmtCreate(),'yyyy-MM-dd HH:mm:ss')}"></div>
<!--            <h2 style="align-content: center" th:text="${article.authorName}"></h2>-->
    <div id="layout">
    <div id="test-editormd">
                <textarea style="display:none;" th:text="${article.content}"></textarea>
    </div>
</div>
</div>
</div>
</div>
<script th:src="@{/editor.md/examples/js/jquery.min.js}"></script>
<script th:src="@{/editor.md/lib/marked.min.js}"></script>
<script th:src="@{/editor.md/lib/prettify.min.js}"></script>
<script th:src="@{/editor.md/lib/raphael.min.js}"></script>
<script th:src="@{/editor.md/lib/underscore.min.js}"></script>
<script th:src="@{/editor.md/lib/sequence-diagram.min.js}"></script>
<script th:src="@{/editor.md/lib/flowchart.min.js}"></script>
<script th:src="@{/editor.md/lib/jquery.flowchart.min.js}"></script>
<script th:src="@{/editor.md/editormd.js}"></script>
<script type="text/javascript">

    var testEditor;

    $(function () {
      
      
        testEditor = editormd.markdownToHTML("test-editormd", {
      
      
            width: "90%",
            height: 700,
            path: "/editor.md/lib/",
            preview: true,
            watch: true,
            editor: false,

        })
    })
    ! function (e, t, a) {
      
      
        function r() {
      
      
            for (var e = 0; e < s.length; e++) s[e].alpha <= 0 ? (t.body.removeChild(s[e].el), s.splice(e, 1)) : (s[
                e].y--, s[e].scale += .004, s[e].alpha -= .013, s[e].el.style.cssText = "left:" + s[e].x +
                "px;top:" + s[e].y + "px;opacity:" + s[e].alpha + ";transform:scale(" + s[e].scale + "," + s[e]
                    .scale + ") rotate(45deg);background:" + s[e].color + ";z-index:99999");
            requestAnimationFrame(r)
        }

        function n() {
      
      
            var t = "function" == typeof e.onclick && e.onclick;
            e.onclick = function (e) {
      
      
                t && t(), o(e)
            }
        }

        function o(e) {
      
      
            var a = t.createElement("div");
            a.className = "heart", s.push({
      
      
                el: a,
                x: e.clientX - 5,
                y: e.clientY - 5,
                scale: 1,
                alpha: 1,
                color: c()
            }), t.body.appendChild(a)
        }

        function i(e) {
      
      
            var a = t.createElement("style");
            a.type = "text/css";
            try {
      
      
                a.appendChild(t.createTextNode(e))
            } catch (t) {
      
      
                a.styleSheet.cssText = e
            }
            t.getElementsByTagName("head")[0].appendChild(a)
        }

        function c() {
      
      
            return "rgb(" + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + "," + ~~(255 * Math
                .random()) + ")"
        }
        var s = [];
        e.requestAnimationFrame = e.requestAnimationFrame || e.webkitRequestAnimationFrame || e
            .mozRequestAnimationFrame || e.oRequestAnimationFrame || e.msRequestAnimationFrame || function (e) {
      
      
            setTimeout(e, 1e3 / 60)
        }, i(
            ".heart{width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 50%;-moz-border-radius: 50%;position: fixed;}.heart:after{top: -5px;}.heart:before{left: -5px;}"
        ), n(), r()
    }(window, document);

    //-----------------------------
    (function fairyDustCursor() {
      
      

        var possibleColors = ["#D61C59", "#E7D84B", "#1B8798"]
        var width = window.innerWidth;
        var height = window.innerHeight;
        var cursor = {
      
       x: width / 2, y: width / 2 };
        var particles = [];

        function init() {
      
      
            bindEvents();
            loop();
        }

        // Bind events that are needed
        function bindEvents() {
      
      
            document.addEventListener('mousemove', onMouseMove);
            window.addEventListener('resize', onWindowResize);
        }

        function onWindowResize(e) {
      
      
            width = window.innerWidth;
            height = window.innerHeight;
        }

        function onMouseMove(e) {
      
      
            cursor.x = e.clientX;
            cursor.y = e.clientY;

            addParticle(cursor.x, cursor.y, possibleColors[Math.floor(Math.random() * possibleColors.length)]);
        }

        function addParticle(x, y, color) {
      
      
            var particle = new Particle();
            particle.init(x, y, color);
            particles.push(particle);
        }

        function updateParticles() {
      
      

            // Updated
            for (var i = 0; i < particles.length; i++) {
      
      
                particles[i].update();
            }

            // Remove dead particles
            for (var i = particles.length - 1; i >= 0; i--) {
      
      
                if (particles[i].lifeSpan < 0) {
      
      
                    particles[i].die();
                    particles.splice(i, 1);
                }
            }

        }

        function loop() {
      
      
            requestAnimationFrame(loop);
            updateParticles();
        }

        /**
         * Particles
         */

        function Particle() {
      
      

            this.character = "*";
            this.lifeSpan = 120; //ms
            this.initialStyles = {
      
      
                "position": "fixed",
                "display": "inline-block",
                "top": "0px",
                "left": "0px",
                "pointerEvents": "none",
                "touch-action": "none",
                "z-index": "10000000",
                "fontSize": "25px",
                "will-change": "transform"
            };

            // Init, and set properties
            this.init = function (x, y, color) {
      
      

                this.velocity = {
      
      
                    x: (Math.random() < 0.5 ? -1 : 1) * (Math.random() / 2),
                    y: 1
                };

                this.position = {
      
       x: x + 10, y: y + 10 };
                this.initialStyles.color = color;

                this.element = document.createElement('span');
                this.element.innerHTML = this.character;
                applyProperties(this.element, this.initialStyles);
                this.update();

                document.querySelector('.js-cursor-container').appendChild(this.element);
            };

            this.update = function () {
      
      
                this.position.x += this.velocity.x;
                this.position.y += this.velocity.y;
                this.lifeSpan--;

                this.element.style.transform = "translate3d(" + this.position.x + "px," + this.position.y + "px, 0) scale(" + (this.lifeSpan / 120) + ")";
            }

            this.die = function () {
      
      
                this.element.parentNode.removeChild(this.element);
            }

        }

        /**
         * Utils
         */

        // Applies css `properties` to an element.
        function applyProperties(target, properties) {
      
      
            for (var key in properties) {
      
      
                target.style[key] = properties[key];
            }
        }

        if (!('ontouchstart' in window || navigator.msMaxTouchPoints)) init();
    })();
    $(function(){
      
      

        $(window).scroll(function(){
      
        //只要窗口滚动,就触发下面代码

            var scrollt = document.documentElement.scrollTop + document.body.scrollTop; //获取滚动后的高度

            if( scrollt >200 ){
      
        //判断滚动后高度超过200px,就显示

                $("#back_top").fadeIn(400); //淡入

            }else{
      
      

                $("#back_top").stop().fadeOut(400); //如果返回或者没有超过,就淡出.必须加上stop()停止之前动画,否则会出现闪动

            }

        });

        $("#back_top").click(function(){
      
       //当点击标签的时候,使用animate在200毫秒的时间内,滚到顶部

            $("html,body").animate({
      
      scrollTop:"0px"},200);

        });

    });

</script>
</body>
</html>

(2).后端页面

package com.jsxs.kumquat.controller;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jsxs.kumquat.pojo.CkqnBlog;
import com.jsxs.kumquat.pojo.CkqnUser;
import com.jsxs.kumquat.service.CkqnBlogService;
import com.jsxs.kumquat.utils.FileUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.UUID;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author 吉士先生
 * @since 2023-04-09
 */
@Controller
@RequestMapping("/article")
public class CkqnBlogController {
    
    
    @Resource
    CkqnBlogService ckqnBlogService;
    @Resource
    HttpSession session;
    // 文章上传
    @RequestMapping("/publish")
    public String publishArticle(CkqnBlog article) {
    
    
        CkqnUser user = (CkqnUser) session.getAttribute("loginUser");
        // 1.作者信息
        article.setAuthorId(user.getUid());
        article.setAuthorName(user.getUsername());
        article.setAuthorAvatar(user.getAvatar());
        // 2.博客ID
        String replace = UUID.randomUUID().toString().replace("-", "");
        article.setBid(replace);
        if (article.getTitle() == null) {
    
    
            System.out.println("标题为空?????????");
        }
        boolean res = ckqnBlogService.save(article);
        if (res) {
    
    
            return "tipSuccess";
        }
        return "tipFalse";
    }
    // 文件上传
    @RequestMapping("/image/upload")
    @ResponseBody
    public JSONObject imageUpload(@RequestParam("editormd-image-file") MultipartFile image) {
    
    
        JSONObject jsonObject = new JSONObject();
        if (image != null) {
    
    
            String path = FileUtils.uploadFile(image);
//            回调给 editor
            System.out.println(path);
            jsonObject.put("url", path);
            jsonObject.put("success", 1);
            jsonObject.put("message", "upload success!");
            return jsonObject;
        }
        jsonObject.put("success", 0);
        jsonObject.put("message", "upload error!");
        return jsonObject;
    }

    //  1.一篇详细文章
    @RequestMapping("/get/{id}")
    public ModelAndView getArticleById(@PathVariable(name = "id") int id) {
    
    
        ModelAndView modelAndView = new ModelAndView();
        CkqnBlog article = ckqnBlogService.getById(id);

        modelAndView.setViewName("WriteCenter/article");
        if (article == null) {
    
    
            modelAndView.addObject("article", new CkqnBlog());
        }
        modelAndView.addObject("article", article);
        return modelAndView;
    }

    // 开始修改
    @RequestMapping("/update/editor/{authorId}/{bid}")
    public String updateArticleByUser(@PathVariable("authorId") String authorId, @PathVariable("bid") String bid, Model model) {
    
    
//        CkqnUser user = (CkqnUser)session.getAttribute("loginUser");
        QueryWrapper<CkqnBlog> wrapper = new QueryWrapper<>();
        //  查询uid
        CkqnBlog blog = ckqnBlogService.getOne(wrapper.eq("bid", bid));
        System.out.println(authorId + " " + bid);
        // 2.查询作者
        if (!blog.getAuthorId().equals(authorId)) {
    
    
            System.out.println("对不起,你在非法编辑");
            //  直接注销账号
            return "redirect:/index.html";
        }
        // 3. 存放文章
        model.addAttribute("blog", blog);
        //  4.没有重定向
        return "WriteCenter/update";
    }

}

4.Aax 密码验证

需要引入js- 一个都不能变,注意路径

    <link rel="stylesheet" th:href="@{/editor.md/css/examples/style.css}" />
    <link rel="stylesheet" th:href="@{/editor.md/css/editormd.css}" />
    <link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon" />
    <script th:src="@{/Jquery/jquery-3.6.1.js}"></script>
    
<script th:src="@{/editor.md/examples/js/jquery.min.js}"></script>
<script th:src="@{/editor.md/lib/marked.min.js}"></script>
<script th:src="@{/editor.md/lib/prettify.min.js}"></script>
<script th:src="@{/editor.md/lib/raphael.min.js}"></script>
<script th:src="@{/editor.md/lib/underscore.min.js}"></script>
<script th:src="@{/editor.md/lib/sequence-diagram.min.js}"></script>
<script th:src="@{/editor.md/lib/flowchart.min.js}"></script>
<script th:src="@{/editor.md/lib/jquery.flowchart.min.js}"></script>
<script th:src="@{/editor.md/editormd.js}"></script>

文章主题部分

    <div id="test-editormd">
                <textarea style="display:none;" th:text="${article.content}"></textarea>
    </div>

JS

<script type="text/javascript">

    var testEditor;

    $(function () {
      
      
        testEditor = editormd.markdownToHTML("test-editormd", {
      
      
            width: "90%",
            height: 700,
            path: "/editor.md/lib/",
            preview: true,
            watch: true,
            editor: false,

        })
    })
    ! function (e, t, a) {
      
      
        function r() {
      
      
            for (var e = 0; e < s.length; e++) s[e].alpha <= 0 ? (t.body.removeChild(s[e].el), s.splice(e, 1)) : (s[
                e].y--, s[e].scale += .004, s[e].alpha -= .013, s[e].el.style.cssText = "left:" + s[e].x +
                "px;top:" + s[e].y + "px;opacity:" + s[e].alpha + ";transform:scale(" + s[e].scale + "," + s[e]
                    .scale + ") rotate(45deg);background:" + s[e].color + ";z-index:99999");
            requestAnimationFrame(r)
        }

        function n() {
      
      
            var t = "function" == typeof e.onclick && e.onclick;
            e.onclick = function (e) {
      
      
                t && t(), o(e)
            }
        }

        function o(e) {
      
      
            var a = t.createElement("div");
            a.className = "heart", s.push({
      
      
                el: a,
                x: e.clientX - 5,
                y: e.clientY - 5,
                scale: 1,
                alpha: 1,
                color: c()
            }), t.body.appendChild(a)
        }

        function i(e) {
      
      
            var a = t.createElement("style");
            a.type = "text/css";
            try {
      
      
                a.appendChild(t.createTextNode(e))
            } catch (t) {
      
      
                a.styleSheet.cssText = e
            }
            t.getElementsByTagName("head")[0].appendChild(a)
        }

        function c() {
      
      
            return "rgb(" + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + "," + ~~(255 * Math
                .random()) + ")"
        }
        var s = [];
        e.requestAnimationFrame = e.requestAnimationFrame || e.webkitRequestAnimationFrame || e
            .mozRequestAnimationFrame || e.oRequestAnimationFrame || e.msRequestAnimationFrame || function (e) {
      
      
            setTimeout(e, 1e3 / 60)
        }, i(
            ".heart{width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 50%;-moz-border-radius: 50%;position: fixed;}.heart:after{top: -5px;}.heart:before{left: -5px;}"
        ), n(), r()
    }(window, document);
    </script>

全体文章

package com.jsxs.kumquat.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author Jsxs
 * @Date 2023/4/10 17:07
 * @PackageName:com.jsxs.kumquat.controller
 * @ClassName: AjaxController
 * @Description: TODO
 * @Version 1.0
 */

@RestController
public class AjaxController {
    
    
    @RequestMapping("/a3")
    public String a3(String name,String pwd){
    
    
        String msg="";
        System.out.println(name);
        System.out.println(pwd);
        if (name!=null){
    
    
            if ("吉士先生".equals(name)){
    
    
                msg="OK";
            }else {
    
    
                msg="Error";
            }
        }
        if (pwd!=null){
    
    
            if ("121788".equals(pwd)){
    
    
                msg="OK";
            }else {
    
    
                msg="Error";
            }
        }
        return msg;
    }
}

以上可以实现异步登入判断

(三)、知识点新发现

1. template包中创建包静态资源路径一样.

在这里插入图片描述

2. SpringBoot自定义400、500错误。只需要在template包下创建error包即可。

在这里插入图片描述

3. 加入我们要使用mybatis-plus那么条件构造其实际上就是对SQL的拼接操作。构造器的泛型是: 实体类

    //1. 通过账户UserUid进行查找用户
    @RequestMapping("/code")
    public String SelectByUserUid(){
    
    
        // 1.定义条件构造器-> 这里的泛型是实体类
        QueryWrapper<CkqnUser> wrapper = new QueryWrapper<>();
        wrapper.eq("uid","root");
        CkqnUser one = ckqnUserService.getOne(wrapper.eq("uid", "root"));
        return ""+one;
    }

在这里插入图片描述

4.我们在验证登入操作的时候,只需要根据username进行判断即可,因为这样可以减少对数据库的一次访问

 //1. 通过账户UserUid进行查找用户 -> 可以减少对数据库的访问频次(可以减少对密码的查询)
    @PostMapping("/code")
    public String SelectByUserUid() throws Exception {
    
    
        // 1.定义条件构造器-> 这里的泛型是实体类
        QueryWrapper<CkqnUser> wrapper = new QueryWrapper<>();
        // 2.添加条件: 是否相等
        wrapper.eq("uid","root");
        // 3.执行查找数据的操作
        CkqnUser ckqnUser = ckqnUserService.getOne(wrapper.eq("uid", "root"));
        // 4.optional检测是否为空
        Optional<CkqnUser> optional = Optional.ofNullable(ckqnUser);
        // 5.假如为空直接抛出异常
        optional.orElseThrow(()->new Exception("非常抱歉出现了空指针异常!!"));
        // 6.查看密码
        String password = ckqnUser.getPassword();

        CkqnUser ckqnUser1 = ckqnUserService.getOne(wrapper.eq("password", password));
        if (ckqnUser1.equals(ckqnUser)){
    
    
            return "index";
        }else {
    
    
            return "login";
        }

(四)、金橘社区前端设计

金橘社区

1. 渐变动态背景CSS .

<style>
        body {
      
      
    margin: 0;
    padding: 0;

    height: 100vh;

    display: flex;
    justify-content: center;
    align-items: center;

    background: linear-gradient(135deg, #34ac40, #2c8ae8, #dc47cd, #e7e373);
    background-size: 500%;

    animation: bgAnimation 6s linear infinite;
}

h1 {
      
      
    color: white;
    letter-spacing: 5px;
}

@keyframes bgAnimation {
      
      
    0% {
      
      
        background-position: 0% 50%;
    }

    50% {
      
      
        background-position: 100% 50%;
    }

    100% {
      
      
        background-position: 0% 50%;
    }
}
    </style>

在这里插入图片描述

2. sleep() 休眠的工具类

    function sleep(numberMillis) {
    
    
        var now = new Date();
        var exitTime = now.getTime() + numberMillis;
        while (true) {
    
    
            now = new Date();
            if (now.getTime() > exitTime)
                return true;
        }
    }

3. 利用JS页面的跳转,我们一定要用异步跳转

 // 这里一定要异步对其进行跳转页面
                    setTimeout(()=>{
    
    
                        document.location.href="two.html"
                    },600)

4. 好看的动态背景推荐

css

/* 清除浏览器默认边距,
使边框和内边距的值包含在元素的width和height内 */

* {
    
    
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* 使用flex布局,让内容垂直和水平居中 */

section {
    
    
    /* 相对定位 */
    position: relative;
    overflow: hidden;
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    /* linear-gradient() 函数用于创建一个表示两种或多种颜色线性渐变的图片 */
    background: linear-gradient(to bottom, #f1f4f9, #dff1ff);
}

/* 背景颜色 */

section .color {
    
    
    /* 绝对定位 */
    position: absolute;
    /* 使用filter(滤镜) 属性,给图像设置高斯模糊*/
    filter: blur(200px);
}

/* :nth-child(n) 选择器匹配父元素中的第 n 个子元素 */

section .color:nth-child(1) {
    
    
    top: -350px;
    width: 600px;
    height: 600px;
    background: #ff359b;
}

section .color:nth-child(2) {
    
    
    bottom: -150px;
    left: 100px;
    width: 500px;
    height: 500px;
    background: #fffd87;
}

section .color:nth-child(3) {
    
    
    bottom: 50px;
    right: 100px;
    width: 500px;
    height: 500px;
    background: #00d2ff;
}

.box {
    
    
    position: relative;
}

/* 背景圆样式 */

.box .circle {
    
    
    position: absolute;
    background: rgba(255, 255, 255, 0.1);
    /* backdrop-filter属性为一个元素后面区域添加模糊效果 */
    backdrop-filter: blur(5px);
    box-shadow: 0 25px 45px rgba(0, 0, 0, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.5);
    border-right: 1px solid rgba(255, 255, 255, 0.2);
    border-bottom: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 50%;
    /* 使用filter(滤镜) 属性,改变颜色。
    hue-rotate(deg)  给图像应用色相旋转
    calc() 函数用于动态计算长度值
    var() 函数调用自定义的CSS属性值x*/
    filter: hue-rotate(calc(var(--x) * 70deg));
    /* 调用动画animate,需要10s完成动画,
    linear表示动画从头到尾的速度是相同的,
    infinite指定动画应该循环播放无限次*/
    animation: animate 10s linear infinite;
    /* 动态计算动画延迟几秒播放 */
    animation-delay: calc(var(--x) * -1s);
}

/* 背景圆动画 */

@keyframes animate {
    
    
    0%, 100%, {
    
    
        transform: translateY(-50px);
    }
    50% {
    
    
        transform: translateY(50px);
    }
}

.box .circle:nth-child(1) {
    
    
    top: -50px;
    right: -60px;
    width: 100px;
    height: 100px;
}

.box .circle:nth-child(2) {
    
    
    top: 150px;
    left: -100px;
    width: 120px;
    height: 120px;
    z-index: 2;
}

.box .circle:nth-child(3) {
    
    
    bottom: 50px;
    right: -60px;
    width: 80px;
    height: 80px;
    z-index: 2;
}

.box .circle:nth-child(4) {
    
    
    bottom: -80px;
    left: 100px;
    width: 60px;
    height: 60px;
}

.box .circle:nth-child(5) {
    
    
    top: -80px;
    left: 140px;
    width: 60px;
    height: 60px;
}

/* 登录框样式 */

.container {
    
    
    position: relative;
    width: 400px;
    min-height: 400px;
    background: rgba(255, 255, 255, 0.1);
    display: flex;
    justify-content: center;
    align-items: center;
    backdrop-filter: blur(5px);
    box-shadow: 0 25px 45px rgba(0, 0, 0, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.5);
    border-right: 1px solid rgba(255, 255, 255, 0.2);
    border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}

.form {
    
    
    position: relative;
    width: 100%;
    height: 100%;
    padding: 50px;
}

/* 登录标题样式 */

.form h2 {
    
    
    position: relative;
    color: #fff;
    font-size: 24px;
    font-weight: 600;
    letter-spacing: 5px;
    margin-bottom: 30px;
    cursor: pointer;
}

/* 登录标题的下划线样式 */

.form h2::before {
    
    
    content: "";
    position: absolute;
    left: 0;
    bottom: -10px;
    width: 0px;
    height: 3px;
    background: #fff;
    transition: 0.5s;
}

.form h2:hover:before {
    
    
    width: 53px;
}

.form .inputBox {
    
    
    width: 100%;
    margin-top: 20px;
}

/* 输入框样式 */

.form .inputBox input {
    
    
    width: 100%;
    padding: 10px 20px;
    background: rgba(255, 255, 255, 0.2);
    outline: none;
    border: none;
    border-radius: 30px;
    border: 1px solid rgba(255, 255, 255, 0.5);
    border-right: 1px solid rgba(255, 255, 255, 0.2);
    border-bottom: 1px solid rgba(255, 255, 255, 0.2);
    font-size: 16px;
    letter-spacing: 1px;
    color: #fff;
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
}

.form .inputBox input::placeholder {
    
    
    color: #fff;
}

/* 登录按钮样式 */

.form .inputBox input[type="submit"] {
    
    
    background: #fff;
    color: #666;
    max-width: 100px;
    margin-bottom: 20px;
    font-weight: 600;
    cursor: pointer;
}

.forget {
    
    
    margin-top: 6px;
    color: #fff;
    letter-spacing: 1px;
}

.forget a {
    
    
    color: #fff;
    font-weight: 600;
    text-decoration: none;
}

html

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 
    <link rel="stylesheet" href="style.css">
 
    <title>登录:微信公众号AlbertYang</title>
</head>
 
<body>
    <section>
        <!-- 背景颜色 -->
        <div class="color"></div>
        <div class="color"></div>
        <div class="color"></div>
        <div class="box">
            <!-- 背景圆 -->
            <div class="circle" style="--x:0"></div>
            <div class="circle" style="--x:1"></div>
            <div class="circle" style="--x:2"></div>
            <div class="circle" style="--x:3"></div>
            <div class="circle" style="--x:4"></div>
            <!-- 登录框 -->
            <div class="container">
                <div class="form">
                    <h2>登录</h2>
                    <form>
                        <div class="inputBox">
                            <input type="text" placeholder="姓名">
 
                        </div>
                        <div class="inputBox">
                            <input type="password" placeholder="密码">
 
                        </div>
                        <div class="inputBox">
                            <input type="submit" value="登录">
 
                        </div>
                        <p class="forget">忘记密码?<a href="#">
                                点击这里
                            </a></p>
                        <p class="forget">没有账户?<a href="#">
                                注册
                            </a></p>
                    </form>
                </div>
            </div>
        </div>
    </section>
</body>
 
</html>

在这里插入图片描述

6. 炫酷的搜索框

<!DOCTYPE html>
<html lang="en" dir="ltr">
 
<head>
    <meta charset="utf-8">
    <title> 搜索框 </title>
    <link rel="stylesheet" href="http://at.alicdn.com/t/font_1309180_m0vigzfu7y.css">
    <style type="text/css">
        .bod1 {
      
      
            /*background: -webkit-linear-gradient(to right, #f7797d, #FBD786, #C6FFDD);*/
            /*background-image: url(" 2558.jpg");*/
            /*background-size:cover;*/
            background: #aa4b6b;
            /* fallback for old browsers */
            background: -webkit-linear-gradient(to right, #3b8d99, #6b6b83, #aa4b6b);
            /* Chrome 10-25, Safari 5.1-6 */
            background: linear-gradient(to right, #3b8d99, #6b6b83, #aa4b6b);
            /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
 
 
        }
 
        .search-box {
      
      
            position: absolute;
            top: 10%;
            left: 60%;
            transform: translate(-10%, -50%);
            background: #FD2C6B;
            height: 40px;
            border-radius: 30px;
            /*圆角边框*/
            padding: 10px;
        }
 
        .search-box:hover>.search-text {
      
      
            width: 400px;
        }
 
        .search-box:hover>.search-btn {
      
      
            background: white;
            color: #26087b;
        }
 
        .search-btn {
      
      
 
            color: white;
            float: right;
            width: 40px;
            height: 40px;
            border-radius: 50%;
            background: #FD2C6B;
            display: flex;
            justify-content: center;
            align-items: center;
            transition: 0.5s;
        }
 
        .search-text {
      
      
            border: none;
            background: none;
            outline: none;
            float: left;
            padding: 0;
            color: white;
            font-size: 20px;
            font-family: "Microsoft YaHei UI Light";
            transition: 0.5s;
            line-height: 40px;
            width: 0px;
 
        }
    </style>
</head>
 
<body class="bod1">
    <div class="search-box">
        <input class="search-text" name="inputs" placeholder="在这里输入你想要搜的的东西" >
        <a class="search-btn" onclick="as()">
            <i class="iconfont iconchazhao"></i>
        </a>
    </div>
</body>
<script>
   function as() {
      
      
   let e = document.getElementsByClassName('search-text').inputs.value
   window.location.href = `https://www.baidu.com/s?wd=${ 
        e}`
    console.log("fsfs",e)
   }
</script>
 
</html>

在这里插入图片描述

7. 返回顶部

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>doc</title>
  <style>
    .arrow{
      
      
      border: 9px solid transparent;
      border-bottom-color: #3DA0DB;
      width: 0px;
      height: 0px;
      top:0px
    }
    .stick{
      
      
      width: 8px;
      height: 14px;
      border-radius: 1px;
      background-color: #3DA0DB;
      top:15px;
    }
    #back_top div{
      
      
      position: absolute;
      margin: auto;
      right: 0px;
      left: 0px;
    }
    #back_top{
      
      
      background-color: #dddddd;
      height: 38px;
      width: 38px;
      border-radius: 3px;
      display: block;
      cursor: pointer;
      position: fixed;
      right: 50px;
      bottom: 100px;
      display: none;
    }
  </style>
</head>
<body>




<div id="article"></div>
<div id="back_top">
  <div class="arrow"></div>
  <div class="stick"></div>
</div>

<script src="http://cdn.staticfile.org/jquery/1.11.1-rc2/jquery.min.js"></script>
<script>
  $(function(){
      
      
    for(var i =0 ;i <100;i++){
      
      
      $("#article").append("<p>xxxxxxxxxx<br></p>")
    }

  })
</script>
<script>
  $(function(){
      
      

    $(window).scroll(function(){
      
        //只要窗口滚动,就触发下面代码

      var scrollt = document.documentElement.scrollTop + document.body.scrollTop; //获取滚动后的高度

      if( scrollt >200 ){
      
        //判断滚动后高度超过200px,就显示

        $("#back_top").fadeIn(400); //淡入

      }else{
      
      

        $("#back_top").stop().fadeOut(400); //如果返回或者没有超过,就淡出.必须加上stop()停止之前动画,否则会出现闪动

      }

    });

    $("#back_top").click(function(){
      
       //当点击标签的时候,使用animate在200毫秒的时间内,滚到顶部

      $("html,body").animate({
      
      scrollTop:"0px"},200);

    });

  });
</script>
</body>
</html>

在这里插入图片描述

8. 特效烟花点击

<span class="js-cursor-container"></span>
<!-- 网页鼠标点击特效(爱心) -->
<script>
  ! function (e, t, a) {
      
      
  function r() {
      
      
    for (var e = 0; e < s.length; e++) s[e].alpha <= 0 ? (t.body.removeChild(s[e].el), s.splice(e, 1)) : (s[
            e].y--, s[e].scale += .004, s[e].alpha -= .013, s[e].el.style.cssText = "left:" + s[e].x +
            "px;top:" + s[e].y + "px;opacity:" + s[e].alpha + ";transform:scale(" + s[e].scale + "," + s[e]
                    .scale + ") rotate(45deg);background:" + s[e].color + ";z-index:99999");
    requestAnimationFrame(r)
  }

  function n() {
      
      
  var t = "function" == typeof e.onclick && e.onclick;
  e.onclick = function (e) {
      
      
  t && t(), o(e)
}
}

  function o(e) {
      
      
  var a = t.createElement("div");
  a.className = "heart", s.push({
      
      
  el: a,
  x: e.clientX - 5,
  y: e.clientY - 5,
  scale: 1,
  alpha: 1,
  color: c()
}), t.body.appendChild(a)
}

  function i(e) {
      
      
  var a = t.createElement("style");
  a.type = "text/css";
  try {
      
      
  a.appendChild(t.createTextNode(e))
} catch (t) {
      
      
  a.styleSheet.cssText = e
}
  t.getElementsByTagName("head")[0].appendChild(a)
}

  function c() {
      
      
  return "rgb(" + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + "," + ~~(255 * Math
  .random()) + ")"
}
  var s = [];
  e.requestAnimationFrame = e.requestAnimationFrame || e.webkitRequestAnimationFrame || e
  .mozRequestAnimationFrame || e.oRequestAnimationFrame || e.msRequestAnimationFrame || function (e) {
      
      
  setTimeout(e, 1e3 / 60)
}, i(
  ".heart{width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 50%;-moz-border-radius: 50%;position: fixed;}.heart:after{top: -5px;}.heart:before{left: -5px;}"
  ), n(), r()
}(window, document);

//-----------------------------
  (function fairyDustCursor() {
      
      

  var possibleColors = ["#D61C59", "#E7D84B", "#1B8798"]
  var width = window.innerWidth;
  var height = window.innerHeight;
  var cursor = {
      
       x: width / 2, y: width / 2 };
  var particles = [];

  function init() {
      
      
  bindEvents();
  loop();
}

  // Bind events that are needed
  function bindEvents() {
      
      
  document.addEventListener('mousemove', onMouseMove);
  window.addEventListener('resize', onWindowResize);
}

  function onWindowResize(e) {
      
      
  width = window.innerWidth;
  height = window.innerHeight;
}

  function onMouseMove(e) {
      
      
  cursor.x = e.clientX;
  cursor.y = e.clientY;

  addParticle(cursor.x, cursor.y, possibleColors[Math.floor(Math.random() * possibleColors.length)]);
}

  function addParticle(x, y, color) {
      
      
  var particle = new Particle();
  particle.init(x, y, color);
  particles.push(particle);
}

  function updateParticles() {
      
      

  // Updated
  for (var i = 0; i < particles.length; i++) {
      
      
  particles[i].update();
}

  // Remove dead particles
  for (var i = particles.length - 1; i >= 0; i--) {
      
      
  if (particles[i].lifeSpan < 0) {
      
      
  particles[i].die();
  particles.splice(i, 1);
}
}

}

  function loop() {
      
      
  requestAnimationFrame(loop);
  updateParticles();
}

  /**
   * Particles
   */

  function Particle() {
      
      

  this.character = "*";
  this.lifeSpan = 120; //ms
  this.initialStyles = {
      
      
  "position": "fixed",
  "display": "inline-block",
  "top": "0px",
  "left": "0px",
  "pointerEvents": "none",
  "touch-action": "none",
  "z-index": "10000000",
  "fontSize": "25px",
  "will-change": "transform"
};

  // Init, and set properties
  this.init = function (x, y, color) {
      
      

  this.velocity = {
      
      
  x: (Math.random() < 0.5 ? -1 : 1) * (Math.random() / 2),
  y: 1
};

  this.position = {
      
       x: x + 10, y: y + 10 };
  this.initialStyles.color = color;

  this.element = document.createElement('span');
  this.element.innerHTML = this.character;
  applyProperties(this.element, this.initialStyles);
  this.update();

  document.querySelector('.js-cursor-container').appendChild(this.element);
};

  this.update = function () {
      
      
  this.position.x += this.velocity.x;
  this.position.y += this.velocity.y;
  this.lifeSpan--;

  this.element.style.transform = "translate3d(" + this.position.x + "px," + this.position.y + "px, 0) scale(" + (this.lifeSpan / 120) + ")";
}

  this.die = function () {
      
      
  this.element.parentNode.removeChild(this.element);
}

}

  /**
   * Utils
   */

  // Applies css `properties` to an element.
  function applyProperties(target, properties) {
      
      
  for (var key in properties) {
      
      
  target.style[key] = properties[key];
}
}

  if (!('ontouchstart' in window || navigator.msMaxTouchPoints)) init();
})();
</script>

在这里插入图片描述

9. 前端引入 markdown编辑器 ---- 一定要和html处于同级目录下.

[Editor.md - 开源在线 Markdown 编辑器 (pandao.github.io)](https://pandao.github.io/editor.md/)

首先我们必须先要打开上面的网站: 然后点击安装下载: 就会跳转到一个Github项目中。安装一个压缩包

在这里插入图片描述

然后解压到我们的项目中:

在这里插入图片描述

    <link rel="stylesheet" href="editor.md/css/editormd.min.css">
    <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
    <script src="editor.md/lib/marked.min.js"></script>
    <script src="editor.md/lib/prettify.min.js"></script>
    <script src="editor.md/editormd.js"></script>
    <!-- 正文:  -->
<div id="editor">

</div>
<script>
    var editor = editormd("editor", {
      
      
        // 这里的尺寸必须在这里设置,设置样式会被 editormd 自动覆盖
        width: "100%",
        // 设置高度
        height: "500px",
        // 编辑器中初始内容
        markdown: "# 在这里写下一篇博客",
        // 指定插件路径
        path: "editor.md/lib/"
    });
</script>

在这里插入图片描述

在这里插入图片描述

10. 百度搜索框

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Serach</title>
  <style>
    * {
      
      
      margin: 0;
      padding: 0;
    }

    .top-search {
      
      
      width: 680px;
      height: 45px;
      margin: 30px auto;

    }

    .search-box {
      
      
      display: flex;
      position: relative;
    }

    .search-left {
      
      
      width: 545px;
      height: 45px;
      border: 2px solid rgb(196, 199, 206);
      border-top-left-radius: 10px;
      border-bottom-left-radius: 10px;
      outline-color: rgb(78, 110, 242);
    }

    .icon-xiangji {
      
      
      position: absolute;
      right: 150px;
      top: 12px;
      font-size: 24px;
      color: rgb(196, 199, 206);
    }

    .search-right {
      
      
      color: #fff;
      font-size: 18px;
      width: 110px;
      height: 49px;
      border: 0px;
      border-top-right-radius: 10px;
      border-bottom-right-radius: 10px;
      background-color: rgb(78, 110, 242);
    }
            #su:hover{
      
      
            background: #14dc99;
        }

  </style>
</head>
<body>
<form action="mainMenu.html">
<div class="top-img"></div>
<div class="top-search">
  <div class="search-box">
      <input type="text" name="search" class="search-left">
      <span class="iconfont icon-xiangji"></span>
      <input class="search-right" type="subbmit" name="btn" id="su" value='发表文章'>
  </div>
</div>
</form>
</body>
</html>

在这里插入图片描述

11. 二维码弹窗!!!

<!DOCTYPE html>
<html>
<head>
  <title>test1</title>
  <meta charset="UTF-8">
  <%--注意引用和地址--%>
  <script src="static/Jquery/jquery-3.6.1.js"></script>
  <script src="static/layui/layui.js" charset="utf-8"></script>
  <script src="https://static.runoob.com/assets/qrcode/qrcode.min.js"></script>
  <link rel="stylesheet" href="static/layui/css/layui.css"  media="all">
</head>
<body>

<div align="center">
  <button type="button" class="layui-btn layui-btn-normal layui-btn-radius" onclick="skipHandle()">预览</button>
</div>

<div id="code" style="display: none;">
  <div id="qrcode" style="margin-left: 75px;margin-top: 20px">
   <h1 style="color: #e8136f">你好</h1>
  </div>
</div>

<script>

  layui.use(['layer'], function () {
      
      
    var layer = layui.layer
  });

  // 设置要生成二维码的链接
  new QRCode(document.getElementById("qrcode"), {
      
      
    text: "https://img-home.csdnimg.cn/images/20230407093553.jpg", //设置二维码内容
    canvas: "table", //设置渲染方式
    width: 250,
    height: 250
  });

  //预览等弹出框
  function skipHandle() {
      
      
    layer.open({
      
      
      type: 1,
      title: "bug_producter的博客",//标题
      area: ['400px', '400px'],
      content: $('#code').html(),
    });
  }

</script>
</body>
</html>

在这里插入图片描述

12. 文本框不能为空格的属性,一个属性就可以

οnkeyup="this.value=this.value.replace(/\s+/g,'')"

猜你喜欢

转载自blog.csdn.net/qq_69683957/article/details/130074071