111.【金橘社区1.0】

金橘社区1.0版本

  • (一)、SpringBoot整合SpringSecurity
    • 1.导入依赖
    • 2.数据库
    • 3.登入表单
    • 4. 添加配置类 SecurityConfig
    • 5.接口实现类 CkqnUserServiceImpl
    • 6.前端认证问题
  • (二)、SpringBoot整合Ajax
    • 1.登入表单
    • 2. JavaScript
  • (三)、SpringBoot整合editor.md
    • 1.编写页面
        • (1).前端页面
        • (2).后端页面
    • 2.修改文件
        • (1).前端页面
        • (2).后端页面
    • 3.文章展示
        • (1).前端页面
        • (2).后端页面
    • 4.Aax 密码验证
  • (三)、知识点新发现
    • 1. template包中创建包静态资源路径一样.
    • 2. SpringBoot自定义400、500错误。只需要在template包下创建error包即可。
    • 3. 加入我们要使用mybatis-plus那么条件构造其实际上就是对SQL的拼接操作。构造器的泛型是: 实体类
    • 4.我们在验证登入操作的时候,只需要根据username进行判断即可,因为这样可以减少对数据库的一次访问
  • (四)、金橘社区前端设计
    • 1. 渐变动态背景CSS .
    • 2. sleep() 休眠的工具类
    • 3. 利用JS页面的跳转,我们一定要用异步跳转
    • 4. 好看的动态背景推荐
    • 6. 炫酷的搜索框
    • 7. 返回顶部
    • 8. 特效烟花点击
    • 9. 前端引入 markdown编辑器 ---- 一定要和html处于同级目录下.
    • 10. 百度搜索框
    • 11. 二维码弹窗!!!!!
    • 12. 文本框不能为空格的属性,一个属性就可以

(一)、SpringBoot整合SpringSecurity

金橘社区官网: http://www.jsxs1.cn/

1.导入依赖


<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.0modelVersion>
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.7.7version>
        <relativePath/> 
    parent>
    <groupId>com.jsxsgroupId>
    <artifactId>KumquatartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <name>Kumquatname>
    <description>Demo project for Spring Bootdescription>
    <properties>
        <java.version>1.8java.version>
    properties>
    <dependencies>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-jdbcartifactId>
        dependency>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.6version>
        dependency>
        
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
        dependency>
        
        <dependency>
            <groupId>com.baomidougroupId>
            <artifactId>mybatis-plus-boot-starterartifactId>
            <version>3.0.5version>
        dependency>
        
        <dependency>
            <groupId>com.baomidougroupId>
            <artifactId>mybatis-plus-generatorartifactId>
            <version>3.3.2version>
        dependency>
        <dependency>
            <groupId>org.apache.velocitygroupId>
            <artifactId>velocity-engine-coreartifactId>
            <version>2.2version>
        dependency>
        <dependency>
            <groupId>io.swaggergroupId>
            <artifactId>swagger-annotationsartifactId>
            <version>1.5.22version>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-thymeleafartifactId>
            <version>2.7.7version>
        dependency>
        
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
        dependency>
        
        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>fastjsonartifactId>
            <version>2.0.26version>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-securityartifactId>
        dependency>
        
        <dependency>
            <groupId>org.thymeleaf.extrasgroupId>
            <artifactId>thymeleaf-extras-springsecurity5artifactId>
            <version>3.0.4.RELEASEversion>
        dependency>

    dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
            <plugin>
            <artifactId>maven-surefire-pluginartifactId>
            <configuration>
                <skip>trueskip>
            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;

/**
 * 

* 服务实现类 *

* * @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; } }

两张表
111.【金橘社区1.0】_第1张图片

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的插件文件
111.【金橘社区1.0】_第2张图片

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: "发布"
                },

                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: "发布"
                },

                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;

/**
 * 

* 前端控制器 *

* * @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: "提交修改"
        },

        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">
  
  <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: "提交修改"
        },

        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;

/**
 * 

* 前端控制器 *

* * @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>

<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>Xspan>
                <span>Xspan>
            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>

    <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;

/**
 * 

* 前端控制器 *

* * @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包中创建包静态资源路径一样.

111.【金橘社区1.0】_第3张图片

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

111.【金橘社区1.0】_第4张图片

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;
    }

111.【金橘社区1.0】_第5张图片

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>

111.【金橘社区1.0】_第6张图片

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>登录:微信公众号AlbertYangtitle>
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>

111.【金橘社区1.0】_第7张图片

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>doctitle>
  <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("

xxxxxxxxxx

"
) } })
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>

111.【金橘社区1.0】_第8张图片

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项目中。安装一个压缩包

111.【金橘社区1.0】_第9张图片

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

111.【金橘社区1.0】_第10张图片

    <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>

111.【金橘社区1.0】_第11张图片

111.【金橘社区1.0】_第12张图片

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>Serachtitle>
  <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>

111.【金橘社区1.0】_第13张图片

11. 二维码弹窗!!!

DOCTYPE html>
<html>
<head>
  <title>test1title>
  <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>

111.【金橘社区1.0】_第14张图片

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

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

你可能感兴趣的:(mybatis,java,spring,boot)