> 文章列表 > 111.【金橘社区1.0】

111.【金橘社区1.0】

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.导入依赖

<?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 {//  调用的是业务实现类@Resourceprivate CkqnUserServiceImpl ckqnUserService;// 密码加密方式@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}/*** 认证** @param http* @throws Exception permitAll -> 无条件访问*                   authenticated -> 需要认证才能访问, /* 除了无条件的,其他都加上锁*/@Overrideprotected 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-》密码加密方式*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(ckqnUserService).passwordEncoder(passwordEncoder());}/*** * @param web* @throws Exception 对静态资源不拦截: static目录可以省略*/@Overridepublic 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. 业务层接口@ResourceCkqnUserService userService;// 2. 认证角色层接口@ResourceCkqnUserRoleService roleService;// 3.session@ResourceHttpSession session;/*** TODO 用户逻辑和认证** @param uid* @return* @throws UsernameNotFoundException*/@Overridepublic UserDetails loadUserByUsername(String uid) throws UsernameNotFoundException {// 4. 通过用户名查询用户CkqnUser user = userService.getOne(new QueryWrapper<CkqnUser>().eq("uid", uid));// 5. 查询到的角色放入sessionsession.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】

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】

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.图片上传URLtoolbarIcons: 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><istyle="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="     请 输 入 文 章 标 题" requiredstyle="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 {@ResourceCkqnBlogService ckqnBlogService;@ResourceHttpSession 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.博客IDString 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")@ResponseBodypublic JSONObject imageUpload(@RequestParam("editormd-image-file") MultipartFile image) {JSONObject jsonObject = new JSONObject();if (image != null) {String path = FileUtils.uploadFile(image);
//            回调给 editorSystem.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><istyle="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="     请 输 入 文 章 标 题" requiredstyle="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 {@ResourceCkqnBlogService ckqnBlogService;@ResourceHttpSession 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.博客IDString 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")@ResponseBodypublic JSONObject imageUpload(@RequestParam("editormd-image-file") MultipartFile image) {JSONObject jsonObject = new JSONObject();if (image != null) {String path = FileUtils.uploadFile(image);
//            回调给 editorSystem.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<>();//  查询uidCkqnBlog 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><istyle="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 neededfunction 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() {// Updatedfor (var i = 0; i < particles.length; i++) {particles[i].update();}// Remove dead particlesfor (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; //msthis.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 propertiesthis.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 {@ResourceCkqnBlogService ckqnBlogService;@ResourceHttpSession 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.博客IDString 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")@ResponseBodypublic JSONObject imageUpload(@RequestParam("editormd-image-file") MultipartFile image) {JSONObject jsonObject = new JSONObject();if (image != null) {String path = FileUtils.uploadFile(image);
//            回调给 editorSystem.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<>();//  查询uidCkqnBlog 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】

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

111.【金橘社区1.0】

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】

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】

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>

111.【金橘社区1.0】

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.valuewindow.location.href = `https://www.baidu.com/s?wd=${e}`console.log("fsfs",e)}
</script></html>

111.【金橘社区1.0】

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>

111.【金橘社区1.0】

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 neededfunction 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() {// Updatedfor (var i = 0; i < particles.length; i++) {particles[i].update();
}// Remove dead particlesfor (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; //msthis.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 propertiesthis.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>

111.【金橘社区1.0】

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

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

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

111.【金橘社区1.0】

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

111.【金橘社区1.0】

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

111.【金橘社区1.0】

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>

111.【金橘社区1.0】

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>

111.【金橘社区1.0】

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

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