添加 MarkDown 支持 + 更新配套教程

This commit is contained in:
Veal98 2021-05-06 21:59:59 +08:00
parent 7d94e21ba0
commit 13af3d7302
15 changed files with 130 additions and 73 deletions

View File

@ -10,11 +10,12 @@
<div align="center">
[![star](https://gitee.com/veal98/Echo/badge/star.svg?theme=dark)](https://gitee.com/veal98/Echo/stargazers)
[![fork](https://gitee.com/veal98/Echo/badge/fork.svg?theme=dark)](https://gitee.com/veal98/Echo/members)
[![GitHub stars](https://img.shields.io/github/stars/Veal98/Echo?logo=github)](https://github.com/Veal98/Echo/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/Veal98/Echo?logo=github)](https://github.com/Veal98/Echo/network)
[![version](https://img.shields.io/badge/version-1.0-brightgreen)]()
[![version](https://img.shields.io/badge/version-2.0-brightgreen)]()
<a href="#-微信交流群"><img src="https://img.shields.io/badge/交流-微信群-orange" alt="交流群"></a>
<a href="#-配套教程"><img src="https://img.shields.io/badge/配套教程-公众号飞天小牛肉-blueviolet" alt="配套教程"></a>
@ -22,7 +23,7 @@
</div>
> 项目上线到服务器之后可能会出现各种各样的 BUG比如 Elasticsearch 服务启动失败导致搜索模块不可用,但是在本地运行是完全没问题的,所以各位小伙伴可以放心下载部署
> 云服务器到期了,暂时不准备续费,未上手的小伙伴可以看下面的界面展示了解本项目,所有代码在我本机上都是正常运行的,各位可以参考配套教程自己拉下去部署,并欢迎加群讨论技术问题
## 📚 项目简介
@ -33,22 +34,10 @@ Echo 是一套前后端不分离的开源社区系统,基于目前主流 Java
- Gitee[https://gitee.com/veal98/Echo](https://gitee.com/veal98/Echo)Gitee 官方推荐项目)
- Github[https://github.com/Veal98/Echo](https://github.com/Veal98/Echo)
**在线体验**:项目已经部署到<u>腾讯云</u>服务器,各位小伙伴们可直接线上体验:[http://1.15.127.74/](http://1.15.127.74/)。已内置三种不同身份的用户:
> **各位请不要修改这三种内置角色的密码**,默认注册的用户是普通用户,您修改了密码后其他小伙伴就没法体验管理员和版主角色了。若想要测试修改密码功能,可以自己重新注册个用户,注意填写真实邮箱,否则无法接收激活邮件并激活角色。感谢各位的配合 ~
>
> 另外,为防止**恶意修改密码**行为,若遇上管理员和版主角色登录失败的情况,可以下方扫码关注公众号【飞天小牛肉】回复 `备用角色` 获取**备用登录用户名和密码**。
| | username | password | 特殊权限 |
| :------: | :------: | :------: | :----------------: |
| 管理员 | admin | admin | 数据统计、删除帖子 |
| 版主 | master | master | 置顶帖子、加精帖子 |
| 普通用户 | user | user | |
**文档地址**:文档通过 <u>Docsify + Github/Gitee Pages</u> 生成
- Github Pages[https://veal98.github.io/Echo](https://veal98.github.io/Echo)
- Gitee Pages[https://veal98.gitee.io/echo](https://veal98.gitee.io/echo)
- Github Pages[https://veal98.github.io/Echo](https://veal98.github.io/Echo)
## 📖 配套教程
@ -77,7 +66,7 @@ Echo 是一套前后端不分离的开源社区系统,基于目前主流 Java
- [Echo 的发帖操作是怎么做的](https://mp.weixin.qq.com/s/OsCd3Pcl6iq-0znh7PL3lg)
- [Echo 的帖子列表与分页是怎么做的](https://mp.weixin.qq.com/s/R5CtsXaS9hIOOePxQZcZhg)
- [Echo 的评论是如何显示的](https://mp.weixin.qq.com/s/0avudnypPu3EewzoU3sEwA)
- Echo 的评论发表与回复是怎么做的
- [Echo 的发布评论是怎么做的](https://mp.weixin.qq.com/s/S5bNpzuZFga2u15ik2t2iQ)
- Echo 的私信列表与详情页是怎么做的
- Echo 的发送私信是怎么做的
- Echo 的点赞模块是怎么做的

View File

@ -7,22 +7,10 @@ Echo 是一套前后端不分离的开源社区系统,基于目前主流 Java
- Gitee[https://gitee.com/veal98/Echo](https://gitee.com/veal98/Echo)Gitee 官方推荐项目)
- Github[https://github.com/Veal98/Echo](https://github.com/Veal98/Echo)
**在线体验**:项目已经部署到<u>腾讯云</u>服务器,各位小伙伴们可直接线上体验:[http://1.15.127.74/](http://1.15.127.74/)。已内置三种不同身份的用户:
> **各位请不要修改这三种内置角色的密码**,默认注册的用户是普通用户,您修改了密码后其他小伙伴就没法体验管理员和版主角色了。若想要测试修改密码功能,可以自己重新注册个用户,注意填写真实邮箱,否则无法接收激活邮件并激活角色。感谢各位的配合 ~
>
> 另外,为防止**恶意修改密码**行为,若遇上管理员和版主角色登录失败的情况,可以下方扫码关注公众号【飞天小牛肉】回复 `备用角色` 获取**备用登录用户名和密码**。
| | username | password | 特殊权限 |
| :------: | :------: | :------: | :----------------: |
| 管理员 | admin | admin | 数据统计、删除帖子 |
| 版主 | master | master | 置顶帖子、加精帖子 |
| 普通用户 | user | user | |
**文档地址**:文档通过 <u>Docsify + Github/Gitee Pages</u> 生成
- Github Pages[https://veal98.github.io/Echo](https://veal98.github.io/Echo)
- Gitee Pages[https://veal98.gitee.io/echo](https://veal98.gitee.io/echo)
- Github Pages[https://veal98.github.io/Echo](https://veal98.github.io/Echo)
## 📖 配套教程
@ -51,7 +39,7 @@ Echo 是一套前后端不分离的开源社区系统,基于目前主流 Java
- [Echo 的发帖操作是怎么做的](https://mp.weixin.qq.com/s/OsCd3Pcl6iq-0znh7PL3lg)
- [Echo 的帖子列表与分页是怎么做的](https://mp.weixin.qq.com/s/R5CtsXaS9hIOOePxQZcZhg)
- [Echo 的评论是如何显示的](https://mp.weixin.qq.com/s/0avudnypPu3EewzoU3sEwA)
- Echo 的评论发表与回复是怎么做的
- [Echo 的发布评论是怎么做的](https://mp.weixin.qq.com/s/S5bNpzuZFga2u15ik2t2iQ)
- Echo 的私信列表与详情页是怎么做的
- Echo 的发送私信是怎么做的
- Echo 的点赞模块是怎么做的

View File

@ -1,6 +1,6 @@
![Logo](https://gitee.com/veal98/images/raw/master/img/20210211175136.png)
# Echo <small>1.0</small>
# Echo <small>2.0</small>
> 🦄 开源社区系统

View File

@ -45,6 +45,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm
"/user/setting",
"/user/upload",
"/discuss/add",
"/discuss/publish",
"/comment/add/**",
"/letter/**",
"/notice/**",
@ -119,5 +120,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm
// Security 底层会默认拦截 /logout 请求进行退出处理
// 此处赋予它一个根本不存在的退出路径使得程序能够执行到我们自己编写的退出代码
http.logout().logoutUrl("/securitylogout");
http.headers().frameOptions().sameOrigin();
}
}

View File

@ -6,6 +6,7 @@ import com.greate.community.controller.interceptor.MessageInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
@ -23,17 +24,25 @@ public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private DataInterceptor dataInterceptor;
// 对除静态资源外所有路径进行拦截
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 对除静态资源外所有路径进行拦截
registry.addInterceptor(loginTicketInterceptor)
.excludePathPatterns("/css/**", "/js/**", "/img/**", "/editor-md/**");
.excludePathPatterns("/css/**", "/js/**", "/img/**", "/editor-md/**", "/editor-md-upload/**");
registry.addInterceptor(messageInterceptor)
.excludePathPatterns("/css/**", "/js/**", "/img/**", "/editor-md/**");
.excludePathPatterns("/css/**", "/js/**", "/img/**", "/editor-md/**", "/editor-md-upload/**");
registry.addInterceptor(dataInterceptor)
.excludePathPatterns("/css/**", "/js/**", "/img/**", "/editor-md/**");
.excludePathPatterns("/css/**", "/js/**", "/img/**", "/editor-md/**", "/editor-md-upload/**");
}
// 配置虚拟路径映射访问
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry){
// System.getProperty("user.dir") 获取程序的当前路径
String path = System.getProperty("user.dir")+"\\src\\main\\resources\\static\\editor-md-upload\\";
registry.addResourceHandler("/editor-md-upload/**").addResourceLocations("file:" + path);
}
}

View File

@ -10,13 +10,21 @@ import com.greate.community.util.CommunityConstant;
import com.greate.community.util.CommunityUtil;
import com.greate.community.util.HostHolder;
import com.greate.community.util.RedisKeyUtil;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
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.util.HtmlUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.*;
/**
@ -47,6 +55,30 @@ public class DiscussPostController implements CommunityConstant {
@Autowired
private RedisTemplate redisTemplate;
// 网站域名
@Value("${community.path.domain}")
private String domain;
// 项目名(访问路径)
@Value("${server.servlet.context-path}")
private String contextPath;
@Value("${qiniu.key.access}")
private String accessKey;
@Value("${qiniu.key.secret}")
private String secretKey;
@Value("${qiniu.bucket.header.name}")
private String headerBucketName;
@Value("${qiniu.bucket.header.url}")
private String headerBucketUrl;
// editorMd 图片上传地址
@Value("${community.path.editormdUploadPath}")
private String editormdUploadPath;
/**
* 进入帖子发布页
* @return
@ -58,13 +90,37 @@ public class DiscussPostController implements CommunityConstant {
/**
* markdown 图片上传
* 功能尚未完成
* @param file
* @return
*/
@PostMapping("/uploadMdPic")
@ResponseBody
public String uploadMdPic() {
return null;
public String uploadMdPic(@RequestParam(value = "editormd-image-file", required = false) MultipartFile file) {
String url = null; // 图片访问地址
try {
// 获取上传文件的名称
String trueFileName = file.getOriginalFilename();
String suffix = trueFileName.substring(trueFileName.lastIndexOf("."));
String fileName = CommunityUtil.generateUUID() + suffix;
// 图片存储路径
File dest = new File(editormdUploadPath + "/" + fileName);
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
// 保存图片到存储路径
file.transferTo(dest);
// 图片访问地址
url = domain + contextPath + "/editor-md-upload/" + fileName;
} catch (Exception e) {
e.printStackTrace();
return CommunityUtil.getEditorMdJSONString(0, "上传失败", url);
}
return CommunityUtil.getEditorMdJSONString(1, "上传成功", url);
}
/**

View File

@ -76,15 +76,15 @@ public class UserController implements CommunityConstant {
public String getSettingPage(Model model) {
// 生成上传文件的名称
String fileName = CommunityUtil.generateUUID();
model.addAttribute("fileName", fileName);
// 设置响应信息(qiniu 的规定写法)
StringMap policy = new StringMap();
policy.put("returnBody", CommunityUtil.getJSONString(0));
// 生成上传到 qiniu 的凭证(qiniu 的规定写法)
Auth auth = Auth.create(accessKey, secretKey);
String uploadToken = auth.uploadToken(headerBucketName, fileName, 3600, policy);
model.addAttribute("uploadToken", uploadToken);
model.addAttribute("fileName", fileName);
return "/site/setting";
}

View File

@ -60,6 +60,15 @@ public class CommunityUtil {
return getJSONString(code, null, null);
}
// editor.md 要求返回的 JSON 字符串格式
public static String getEditorMdJSONString(int success, String message, String url) {
JSONObject json = new JSONObject();
json.put("success", success);
json.put("message", message);
json.put("url", url);
return json.toJSONString();
}
/**
* 测试
* @param args

View File

@ -6,6 +6,8 @@ server.servlet.context-path =
# 网站域名
community.path.domain = http://localhost:8080
# Editor.Md 图片上传路径
community.path.editormdUploadPath = E:/GreateCommunity/src/main/resources/static/editor-md-upload
# Thymeleaf
spring.thymeleaf.cache=false

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

View File

@ -84,11 +84,13 @@
<!-- <button type="button" class="btn btn-primary btn-sm position-absolute rt-0"-->
<!-- data-toggle="modal" data-target="#publishModal"-->
<!-- th:if="${loginUser != null}"><i class="bi bi-plus-square"></i> 我要发布</button>-->
<a class="bi bi-plus-square" th:href="@{/discuss/publish}">
<button type="button" class="btn btn-primary btn-sm position-absolute rt-0"
data-toggle="modal"
th:if="${loginUser != null}"><i class="bi bi-plus-square"></i> 我要发布</button>
<a th:href="@{/discuss/publish}" th:if="${loginUser != null}">
<button type="button" class="btn btn-primary btn-sm position-absolute rt-0">
<i class="bi bi-plus-square"></i> 我要发布
</button>
</a>
</div>
<!-- 弹出框 -->
<!-- <div class="modal fade" id="publishModal" tabindex="-1" role="dialog" aria-labelledby="publishModalLabel" aria-hidden="true">-->

View File

@ -9,6 +9,8 @@
<link rel="stylesheet" type="text/css" th:href="@{/css/global.css}" />
<link rel="stylesheet" type="text/css" th:href="@{/css/discuss-detail.css}" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.3.0/font/bootstrap-icons.css">
<link rel="stylesheet" type="text/css" th:href="@{/editor-md/css/editormd.css}" />
<title>Echo - 帖子详情</title>
</head>
<body>
@ -210,7 +212,7 @@
tex: true, // 默认不解析
flowChart: true, // 默认不解析
sequenceDiagram: true, // 默认不解析
codeFold: true,
codeFold: true
})
})
</script>

View File

@ -20,15 +20,17 @@
<div id="layout">
<header>
<div class="form-group">
<input type="text" class="form-control" id="recipient-name" placeholder="输入文章标题..."
style = "font-size: 24px; font-weight: 500;">
<input type="text" class="form-control" style = "font-size: 24px; font-weight: 500;"
id="recipient-name" placeholder="输入文章标题..." required>
</div>
</header>
<div id="test-editormd">
<textarea class="form-control" id="message-text" style="display:none;">[TOC]
<textarea class="form-control" id="message-text" style="display:none;">
#### Disabled options
#### Welcome to Echo
> Examples
- TeX (Based on KaTeX);
- Emoji;
@ -38,18 +40,11 @@
#### Editor.md directory
editor.md/
lib/
css/
scss/
tests/
fonts/
images/
plugins/
examples/
languages/
editormd.js
...
```java
public static void main(String[] args) {
System.out.println("Hello World!");
}
```
```html
&lt;!-- English --&gt;
@ -106,18 +101,20 @@
/**上传图片相关配置如下*/
imageUpload : true,
imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
imageUploadURL : "/discuss/uploadMdPic",//注意你后端的上传图片服务地址
imageUploadURL : CONTEXT_PATH + "/discuss/uploadMdPic",// 后端上传图片的服务地址
onload : function() {
//console.log('onload', this);
//this.fullscreen();
//this.unwatch();
//this.watch().fullscreen();
//this.setMarkdown("#PHP");
//this.width("100%");
//this.height(480);
//this.resize("100%", 640);
}
});
/*
// or
testEditor = editormd({
id : "test-editormd",
width : "90%",
height : 640,
path : "../lib/"
});
*/
});
</script>