添加 MarkDown 支持 + 更新配套教程
This commit is contained in:
parent
7d94e21ba0
commit
13af3d7302
21
README.md
21
README.md
@ -10,11 +10,12 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
|
||||
[](https://gitee.com/veal98/Echo/stargazers)
|
||||
[](https://gitee.com/veal98/Echo/members)
|
||||
[](https://github.com/Veal98/Echo/stargazers)
|
||||
[](https://github.com/Veal98/Echo/network)
|
||||
[]()
|
||||
[]()
|
||||
|
||||
<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 的点赞模块是怎么做的
|
||||
|
@ -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 的点赞模块是怎么做的
|
||||
|
@ -1,6 +1,6 @@
|
||||

|
||||
|
||||
# Echo <small>1.0</small>
|
||||
# Echo <small>2.0</small>
|
||||
|
||||
> 🦄 开源社区系统
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 |
@ -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">-->
|
||||
|
@ -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>
|
||||
@ -57,7 +59,7 @@
|
||||
</div>
|
||||
<!-- 正文 -->
|
||||
<div class="mt-4 mb-3 content" id="md-content">
|
||||
<textarea style="display:none;" th:utext="${post.content}"> </textarea>
|
||||
<textarea style="display:none;" th:utext="${post.content}"></textarea>
|
||||
</div>
|
||||
|
||||
<!--<div class="mt-4 mb-3 content" id = "md-content" ></div>-->
|
||||
@ -210,7 +212,7 @@
|
||||
tex: true, // 默认不解析
|
||||
flowChart: true, // 默认不解析
|
||||
sequenceDiagram: true, // 默认不解析
|
||||
codeFold: true,
|
||||
codeFold: true
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
@ -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
|
||||
<!-- English -->
|
||||
@ -101,23 +96,25 @@
|
||||
height : 640,
|
||||
syncScrolling : "single",
|
||||
path : "../editor-md/lib/",
|
||||
saveHTMLToTextarea : true, // 这个配置,方便post提交表单
|
||||
saveHTMLToTextarea : true, // 这个配置,方便 post 提交表单
|
||||
|
||||
/**上传图片相关配置如下*/
|
||||
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>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user