111.【金橘社区1.0】(一)

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 111.【金橘社区1.0】

111.【金橘社区1.0】

金橘社区1.0版本

(一)、SpringBoot整合SpringSecurity

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

Gitee仓库地址: https://gitee.com/lwt121788/ckqn

1.导入依赖

我们使用Mybatis-plu自动生成代码: 在Mapper层没有注解。所以我们需要自己加

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

2.数据库

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

3.登入表单

<form th:action="@{/code}" method="post">
          <div class="inputBox">
            <input type="text" placeholder="账户ID" name="username" id="name" required onblur="a1()" onkeyup="this.value=this.value.replace(/\s+/g,'')">
            <i id="username" style="z-index: 9999"></i>
          </div>
          <div class="inputBox">
            <input type="password" placeholder="密码" name="password" required onkeyup="this.value=this.value.replace(/\s+/g,'')">
          </div>
          <div class="inputBox">
            <input type="submit" value="登录">
          </div>
          <p class="forget">忘记密码?<a href="#">
            点击这里
          </a></p>
          <p class="forget">没有账户?<a href="#">
            注册
          </a></p>
        </form>

4. 添加配置类 SecurityConfig

package com.jsxs.kumquat.config;
import com.jsxs.kumquat.service.impl.CkqnUserServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
 * @Author Jsxs
 * @Date 2023/4/10 20:56
 * @PackageName:com.jsxs.kumquat.config
 * @ClassName: SecurityConfig
 * @Description: TODO  授权文件
 * @Version 1.0
 */
@EnableWebSecurity
@Configuration
@Component
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //  调用的是业务实现类
    @Resource
    private CkqnUserServiceImpl ckqnUserService;
    // 密码加密方式
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    /**
     * 认证
     *
     * @param http
     * @throws Exception permitAll -> 无条件访问
     *                   authenticated -> 需要认证才能访问, /* 除了无条件的,其他都加上锁
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //  首页所有人可以访问,但是功能页只有对应有权限的人才能访问
        http.authorizeRequests()
                .antMatchers("/", "/index.html", "/login.html", "/mainMenu.html", "/JsxsRoad.html", "/recommendedArticles.html", "/code", "/a3").permitAll()
                .antMatchers("/*").authenticated();
        super.configure(http);
        http.formLogin().loginPage("/login.html");
        // 登录配置
        http.formLogin()
                .usernameParameter("username") // 这个参数必须为username (约定大于配置)
                .passwordParameter("password") // 这个参数必须为password (约定大于配置)
                .loginPage("/login.html")  //登入页面是哪个?
                .loginProcessingUrl("/code") // 点击提交的时候跳转到哪里?
                .defaultSuccessUrl("/"); // 密码验证通过后我们跳转到哪里?
        // 注销配置
        http.headers().contentTypeOptions().disable();
        http.headers().frameOptions().disable(); // 图片跨域
        http.csrf().disable();//关闭csrf功能:跨站请求伪造,默认只能通过post方式提交logout请求(ajax如果要使用一定开启)
        http.logout().logoutSuccessUrl("/");
    }
    /**
     * 
     * @param auth
     * @throws Exception userDetailsService-》对哪个业务进行操作,passwordEncoder-》密码加密方式
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(ckqnUserService).passwordEncoder(passwordEncoder());
    }
    /**
     * 
     * @param web
     * @throws Exception 对静态资源不拦截: static目录可以省略
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/css/**", "/assets/**", "/plugins/**", "/img/**", "/editor.md/**", "/Jquery/**", "/layui/**", "/qrcode/**");
    }
}

5.接口实现类 CkqnUserServiceImpl

CkqnUserServiceImpl

package com.jsxs.kumquat.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jsxs.kumquat.pojo.CkqnUser;
import com.jsxs.kumquat.mapper.CkqnUserMapper;
import com.jsxs.kumquat.pojo.CkqnUserRole;
import com.jsxs.kumquat.service.CkqnUserRoleService;
import com.jsxs.kumquat.service.CkqnUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 吉士先生
 * @since 2023-04-09
 * TODO 这里需要继承一个接口: UserDetailsService
 */
@Service
public class CkqnUserServiceImpl extends ServiceImpl<CkqnUserMapper, CkqnUser> implements CkqnUserService, UserDetailsService {
    // 1. 业务层接口
    @Resource
    CkqnUserService userService;
    // 2. 认证角色层接口
    @Resource
    CkqnUserRoleService roleService;
    // 3.session
    @Resource
    HttpSession session;
    /**
     * TODO 用户逻辑和认证
     *
     * @param uid
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String uid) throws UsernameNotFoundException {
        // 4. 通过用户名查询用户
        CkqnUser user = userService.getOne(new QueryWrapper<CkqnUser>().eq("uid", uid));
        // 5. 查询到的角色放入session
        session.setAttribute("loginUser", user);
        // 7.创建一个新的UserDetails对象,最后验证登陆的需要
        UserDetails userDetails = null;
        if (user != null) {
            System.out.println("未加密:" + user.getPassword());
            // 8.加密密码
            String BCryptPassword = new BCryptPasswordEncoder().encode(user.getPassword());
            // 登录后会将登录密码进行加密,然后比对数据库中的密码,数据库密码需要加密存储!
//            String password = user.getPassword();
            // 9. 创建一个集合来存放权限
            Collection<GrantedAuthority> authorities = getAuthorities(user);
            /**
             * TODO 实例化UserDetails对象
             * uid-> 前端username框传过来的数据
             * BCryptPassword-> 加密后的密码
             * authorities -》 认证列表
             */
            userDetails = new org.springframework.security.core.userdetails.User(uid, BCryptPassword,
                    true,
                    true,
                    true,
                    true, authorities);
        }
        return userDetails;
    }
    /**
     * @param user ->实体类
     * @return
     */
    private Collection<GrantedAuthority> getAuthorities(CkqnUser user) {
        List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
        // 1. 通过用户的第三个字段roleID再另一个表中查找数据据
        CkqnUserRole role = roleService.getById(user.getRoleId());
        // 2. 注意:这里每个权限前面都要加ROLE_。否在最后验证不会通过
        authList.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));
        return authList;
    }
}

两张表

6.前端认证问题

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

(二)、SpringBoot整合Ajax

1.登入表单

<form th:action="@{/code}" method="post">
          <div class="inputBox">
            <input type="text" placeholder="账户ID" name="username" id="name" required onblur="a1()" onkeyup="this.value=this.value.replace(/\s+/g,'')">
            <--*******id 为username, 上面id为name-->
            <i id="username" style="z-index: 9999"></i>
          </div>
          <div class="inputBox">
            <input type="password" placeholder="密码" name="password" required onkeyup="this.value=this.value.replace(/\s+/g,'')">
          </div>
          <div class="inputBox">
            <input type="submit" value="登录">
          </div>
          <p class="forget">忘记密码?<a href="#">
            点击这里
          </a></p>
          <p class="forget">没有账户?<a href="#">
            注册
          </a></p>
        </form>

2. JavaScript

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

(三)、SpringBoot整合editor.md

前提需要我们导入editor.md的插件文件

1.编写页面

(1).前端页面

引入文件

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

在这里编写文件

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

配置JS

<script src="/editor.md/examplesjs/jquery.min.js" th:src="@{/editor.md/examples/js/jquery.min.js}"></script>
<script src="/editor.md/editormd.js" th:src="@{/editor.md/editormd.js}"></script>
<script type="text/javascript">
    var testEditor;
    $(function () {
        $.get('/editor.md/examples/test.md', function (md) {
        //  这里的第一个参数,指的是:"编写页面的id": 第二个参数是: "配置" 
            testEditor = editormd("test-editormd", {
                width: "100%",  // 1.宽度
                height: "750px", // 2.高度
                path: '/editor.md/lib/', //3.配置文件 
                theme: "dark", //4.主题
                markdown:'#欢迎您来到金橘社区!!', //5.默认编辑页面
                // previewTheme: "dark",
                editorTheme: "pastel-on-dark", // 6.编辑页面主题
                imageUpload: true,   //7.文件上传
                imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"],  
                imageUploadURL: "/article/image/upload",  //8.图片上传URL
                toolbarIcons: function () { //9.组件
                    return ["undo", "redo", "|", "bold", "del", "italic", "quote", "ucwords", "uppercase", "lowercase", "|", "h1", "h2", "h3", "h4", "h5", "h6", "|", "list-ul", "list-ol", "hr", "|", "link", "reference-link", "image", "code", "preformatted-text", "code-block", "table", "datetime", "emoji", "html-entities", "pagebreak", "|", "goto-line", "watch", "preview", "fullscreen", "clear", "search", "|", "help", "info", "||", "publish"];
                },
                toolbarIconTexts: { //10.自定义发布按钮的组件
                    publish: "<span bgcolor='gray' style='font-family: 微软雅黑;font-weight: bold;color: #00FF00'>发布</span>"
                },
                toolbarHandlers: { //11. 提交文章上传的路径
                    publish: function (cm, icon, cursor, selection) {
                        mdEditorForm.method = "post";
                        mdEditorForm.action = "/article/publish";//提交至服务器的路径
                        mdEditorForm.submit();
                    }
                }
            });
        });
    });
</script>

全部文档信息

<!DOCTYPE html>
<html lang="zh" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
    <meta charset="utf-8"/>
    <title>金橘社区-文章编写</title>
    <link rel="stylesheet" href="{/editor.md/examples/css/style.css" th:href="@{/editor.md/examples/css/style.css/}">
    <link rel="stylesheet" href="/editor.md/css/editormd.css" th:href="@{/editor.md/css/editormd.css}"/>
    <link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon"/>
    <link rel="stylesheet" href="layui/css/layui.css" media="all">
    <script src="layui/layui.js" charset="utf-8"></script>
    <script src="Jquery/jquery-3.6.1.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .top-search {
            width: 680px;
            height: 45px;
            margin: 30px auto;
        }
        .search-box {
            display: flex;
            position: relative;
        }
        .search-left {
            width: 545px;
            height: 45px;
            border: 2px solid rgb(196, 199, 206);
            border-top-left-radius: 10px;
            border-bottom-left-radius: 10px;
            outline-color: rgb(242, 78, 130);
        }
        .icon-xiangji {
            position: absolute;
            right: 150px;
            top: 12px;
            font-size: 24px;
            color: rgb(196, 199, 206);
        }
        .search-right {
            color: #fff;
            font-size: 18px;
            width: 110px;
            height: 49px;
            border: 0px;
            border-top-right-radius: 10px;
            border-bottom-right-radius: 10px;
            background-color: rgb(242, 78, 130);
        }
        #su:hover {
            background: #14dc99;
        }
    </style>
</head>
<body>
<form name="mdEditorForm" method="post">
<div class="top-search" style="margin-top: 13px;">
    <button type="button" class="layui-btn layui-btn-primary1 layui-btn-lg" style="margin-top: 7px;margin-left: -1200px;"
            onclick="document.location.href='MyArticals.html'"><i class="layui-icon layui-icon-return"
                                                                  style="font-size: 20px; color: #1E9FFF;"></i><i
            style="color: #0e0c0d;font-family: 微软雅黑;font-weight: bold" onclick="return confirm('您还未保存,如果直接退出将不会保存数据。您确定直接退出?')">文章管理</i></button>
    <div class="search-box" style="    top: -45px;">
        <input type="text" name="title" class="search-left" placeholder="     请 输 入 文 章 标 题" required
               style="font-size: 20px;font-family: 微软雅黑;font-weight: bold;"
               onkeyup="this.value=this.value.replace(/\s+/g,'')"
        value="【无标题】">
        <span class="iconfont icon-xiangji"></span>
    </div>
    <ul sec:authorize="!isAuthenticated()" class="layui-nav" lay-bar="disabled" style="width: 40px; height: 0px;margin-left: 863px;margin-top: -100px;z-index: 9999">
        <li  class="layui-nav-item" lay-unselect="">
            <a href="javascript:;"><img src="/img/login.png" tppabs="http://t.cn/RCzsdCq" class="layui-nav-img" onclick="document.location.href='login.html'"></a>
            <dl class="layui-nav-child">
                <dd><a href="javascript:;" onclick="document.location.href='login.html'">登入</a></dd>
            </dl>
        </li>
    </ul>
    <ul sec:authorize="hasRole('ROLE_A')" class="layui-nav" lay-bar="disabled" style="width: 40px; height: 0px;margin-left: 863px;margin-top: -100px;z-index: 9999">
        <li  class="layui-nav-item" lay-unselect="">
            <a href="javascript:;"><img src="/img/user.jpg" tppabs="http://t.cn/RCzsdCq" class="layui-nav-img" onclick="document.location.href='#'"></a>
            <dl class="layui-nav-child">
                <dd><a href="javascript:;">个人中心</a></dd>
                <dd><a href="javascript:;" th:href="@{/login.html}">切换账号</a></dd>
                <dd><a href="javascript:;" th:href="@{/logout}">注销</a></dd>
            </dl>
        </li>
    </ul>
    <ul class="layui-nav" lay-bar="disabled" style="width: 40px; height: 0px;margin-left: 863px;margin-top: -100px;z-index: 9999">
        <li sec:authorize="hasRole('ROLE_B')" class="layui-nav-item" lay-unselect="">
            <a href="javascript:;"><img src="/img/user2.jpg" tppabs="http://t.cn/RCzsdCq" class="layui-nav-img" onclick="document.location.href='#'"></a>
            <dl class="layui-nav-child">
                <dd><a href="javascript:;">个人中心</a></dd>
                <dd><a href="javascript:;" onclick="document.location.href='login.html'">切换账号</a></dd>
                <dd><a href="javascript:;" th:href="@{/logout}">注销</a></dd>
            </dl>
        </li>
    </ul>
</div>
<div id="layout" style="margin-top: -41px;">
    <header>
    </header>
        <div id="test-editormd">
            <textarea style="display:none;" name="content"></textarea>
        </div>
</div>
</form>
<script src="/editor.md/examplesjs/jquery.min.js" th:src="@{/editor.md/examples/js/jquery.min.js}"></script>
<script src="/editor.md/editormd.js" th:src="@{/editor.md/editormd.js}"></script>
<script type="text/javascript">
    var testEditor;
    $(function () {
        $.get('/editor.md/examples/test.md', function (md) {
            testEditor = editormd("test-editormd", {
                width: "100%",
                height: "750px",
                path: '/editor.md/lib/',
                theme: "dark",
                markdown:'#欢迎您来到金橘社区!!',
                // previewTheme: "dark",
                editorTheme: "pastel-on-dark",
                imageUpload: true,
                imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
                imageUploadURL: "/article/image/upload",
                toolbarIcons: function () {
                    return ["undo", "redo", "|", "bold", "del", "italic", "quote", "ucwords", "uppercase", "lowercase", "|", "h1", "h2", "h3", "h4", "h5", "h6", "|", "list-ul", "list-ol", "hr", "|", "link", "reference-link", "image", "code", "preformatted-text", "code-block", "table", "datetime", "emoji", "html-entities", "pagebreak", "|", "goto-line", "watch", "preview", "fullscreen", "clear", "search", "|", "help", "info", "||", "publish"];
                },
                toolbarIconTexts: {
                    publish: "<span bgcolor='gray' style='font-family: 微软雅黑;font-weight: bold;color: #00FF00'>发布</span>"
                },
                toolbarHandlers: {
                    publish: function (cm, icon, cursor, selection) {
                        mdEditorForm.method = "post";
                        mdEditorForm.action = "/article/publish";//提交至服务器的路径
                        mdEditorForm.submit();
                    }
                }
            });
        });
    });
</script>
</body>
</html>

相关文章
|
前端开发 JavaScript
111.【金橘社区1.0】(二)
111.【金橘社区1.0】
53 0
|
前端开发
111.【金橘社区1.0】(五)
111.【金橘社区1.0】
75 0
|
前端开发
111.【金橘社区1.0】(六)
111.【金橘社区1.0】
59 0
|
5月前
|
Linux 开发者
Linux底层驱动社区饮水机系统详解
在Linux驱动开发中,入门时通常会关注驱动程序的三大核心步骤:入口函数、出口函数和声明许可证。这些步骤构成了驱动程序的基本结构,是驱动与内核交互的基础。下面是对这三个步骤的简要说明:
|
SQL JavaScript 前端开发
111.【金橘社区1.0】(四)
111.【金橘社区1.0】
51 0
|
前端开发
111.【金橘社区1.0】(三)
111.【金橘社区1.0】
48 0
|
开发者
我和社区的2022
简述我和社区一路走来的点点滴滴
我和社区的2022
|
数据安全/隐私保护 Docker 容器
JetLinks 社区版安装
JetLinks 社区版安装
562 0
|
Cloud Native 数据可视化 关系型数据库
训练营 | 如何成为一名开源社区贡献者?
「云原生应用插件扩展训练营」由阿里云云原生团队围绕 KubeVela、OpenYurt、Koordinator、OpenKruise、Fluid 等云原生开源项目打造,为了帮助更多开发者感受开源社区的魅力,了解如何更快地参与社区贡献。
训练营 | 如何成为一名开源社区贡献者?
|
云计算 开发者
阿里云社区
学习阿里云