1.前提准备
去wangEditor 官网地址下载对应js,css等文件,或者查看使用说明
2.前端功能
信息编辑
创建wangeditor.html文件,进行信息编辑
<!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>信息编辑</title>
<link href="style.css" rel="stylesheet">
<style>
html,
body {
background-color: #fff;
height: 100%;
/*overflow: hidden;*/
color: #333;
}
#top-container {
border-bottom: 1px solid #e8e8e8;
padding-left: 30px;
height: 50px;
}
#editor-toolbar {
width: 100%;
background-color: #FCFCFC;
margin: 0 auto;
}
#content {
height: calc(100% - 40px);
background-color: rgb(245, 245, 245);
overflow-y: auto;
position: relative;
}
#editor-container {
width: 700px;
margin: 30px auto 150px auto;
background-color: #fff;
padding: 20px 50px 50px 50px;
border: 1px solid #e8e8e8;
box-shadow: 0 2px 10px rgb(0 0 0 / 12%);
}
#title-container {
padding: 20px 0;
border-bottom: 1px solid #e8e8e8;
}
#title-container input {
font-size: 30px;
border: 0;
outline: none;
width: 100%;
line-height: 1;
text-align: center; /* 文字居中 */
padding: 5px; /* 增加一些内边距 */
}
#editor-text-area {
min-height: 900px;
margin-top: 20px;
}
.slefbutton:hover {
background-color: #2b7ccd;
}
.slefbutton {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
outline: 0;
border: 0;
padding: 10px 15px;
color: #ffffff;
border-radius: 10px;
width: 100px;
cursor: pointer;
font-size: 20px;
-webkit-transition-duration: 0.25s;
transition-duration: 0.25s;
background-color: #0ea05d;
}
</style>
</head>
<body>
<div id="top-container">
<!-- <p>-->
<!-- <a href="./index.html"><< 返回 Back to demo</a>-->
<!-- </p>-->
<div class="dialog-footer" style="border-bottom: solid 1px #e7e7e7;text-align: center;" >
<button id="btnconfirm" class="slefbutton" type="button" onclick="finished()">确认</button>
<button id="btncancel" class="slefbutton" type="button" style="margin-left: 5%;margin-bottom: 10px;" onclick="cancel()">取消</button>
</div>
</div>
<div>
<div style="border-bottom: 1px solid #e8e8e8;">
<div id="editor-toolbar"></div>
</div>
<div id="content">
<div id="editor-container">
<div id="title-container">
<input placeholder="标题信息...">
</div>
<div id="editor-text-area"></div>
</div>
</div>
</div>
<script src="index.js"></script>
<script src="../../../scripts/lib/js/jquery-1.11.0.js"></script>
<script src="../../../scripts/lib/encrypt/base64.js"></script>
<script src="../../../scripts/lib/encrypt/des.js"></script>
<script>
//取URL参数
QueryString = function (item, href) {
var str = location.search;
if (arguments.length == 2) str = href;
var svalue = str.match(new RegExp("[\?\&]" + item + "=([^\&]*)(\&?)", "i"));
return svalue ? unescape(svalue[1]) : svalue;
}
var title = escape(QueryString("title"));
var content = escape(QueryString("contentUrl2"));
if (content && content != 'undefined') {
content = decodeURIComponent(content);
// console.log(content);
}else{
content = "";
}
window.onload = function () {
if (title && title != 'undefined') {
var data = decodeURIComponent(title);
// console.log(data);
$("#title-container input").val(data);
}
if (content && content != 'undefined') {
fetchData(content).then(data => {
// console.log(data);
editor.setHtml(data);
//editor.getEditableContainer().outerHTML = data;
});
// editor.getEditableContainer().outerHTML = content;
}
}
async function fetchData(content){
try {
const response = await fetch(content);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.text(); // 或者 response.json() 等,取决于响应内容的类型
// console.log(data);
return data;
} catch (error) {
console.error('There was a problem fetching the data:', error);
}
}
const E = window.wangEditor
encodeImgPath = function(imgPath) {
var token = {
expiresTime: new Date().getTime() + 10 * 1000,
validate: true
}
token = new MyDes().strEnc(JSON.stringify(token), 'my');
return imgPath + "?rt=" + token
}
// 切换语言
const LANG = location.href.indexOf('lang=en') > 0 ? 'en' : 'zh-CN'
E.i18nChangeLanguage(LANG)
let dataObj = {};
finished= function (){
if(confirm("是否确认保存当前页面内容?")){
dataObj = {};
console.log(editor.getHtml());
console.log(editor.getText());
console.log(editor.getEditableContainer().outerHTML);
let html = editor.getEditableContainer().outerHTML;
let html2 = editor.getHtml();
// console.log("finishe: "+html);
let obj = {};
obj.title = $("#title-container input").val();
obj.content = html;
obj.content2 = html2;
dataObj.content = obj.content;
dataObj.content2 = obj.content2;
dataObj.title = obj.title.trim();
$.ajax({
url: ms.commonServiceUrl+"mymsg/addMsg",
type: 'POST',
data: JSON.stringify(obj),
contentType: 'application/json;charset=UTF-8',
dataType: 'json',
success: function (data) {
if (data.result) {
console.info(data.contentUrl);
console.info(data.contentUrl2);
dataObj.contentUrl = data.contentUrl;
dataObj.contentUrl2 = data.contentUrl2;
dataObj.summary = data.summary;
if (window.CloseOwnerWindow) return window.CloseOwnerWindow({ action: "ok"});
else window.close();
} else {
alert(data?.messages[0]?.content);
return;
}
},
});
}
}
cancel = function (){
if(confirm("信息未保存,确认关闭当前页面?")){
dataObj = {};
if (window.CloseOwnerWindow) return window.CloseOwnerWindow({ action: "cancel"});
else window.close();
}
}
getData = function () {
return dataObj;
};
function convertImageToBase64(url, callback) {
fetch(url)
.then(response => response.blob())
.then(blob => {
const reader = new FileReader();
reader.onload = e => callback(e.target.result);
reader.readAsDataURL(blob);
});
}
const editorConfig = {
// placeholder: 'Type here...',
scroll: false, // 禁止编辑器滚动
MENU_CONF: {
fontFamily: {
fontFamilyList: [
'新宋体'
]
},
uploadImage: {
fieldName: 'your-fileName',
base64LimitSize: 10 * 1024 * 1024, // 10M 以下插入 base64
server: '图片文件上传地址',
timeout: 5 * 1000, // 5s
headers: { Accept: 'text/x-json' },
maxFileSize: 10 * 1024 * 1024, // 10M
// base64LimitSize: 5 * 1024, // insert base64 format, if file's size less than 5kb
onBeforeUpload(file) {
console.log('onBeforeUpload', file)
return file // will upload this file
// return false // prevent upload
},
onProgress(progress) {
console.log('onProgress', progress)
},
onSuccess(file, res) {
console.log('onSuccess', file, res)
},
onFailed(file, res) {
// res = window.JSON.parse(res);
if (res.jsonResult) {
res = new Base64().decode(res.jsonResult);
res = window.JSON.parse(res);
}
alert(res.returnMsg)
console.log('onFailed', file, res)
},
onError(file, err, res) {
alert(err.message)
console.error('onError', file, err, res)
},
customInsert(res, insertFn) {
console.log('customInsert', res)
if (res.jsonResult) {
res = new Base64().decode(res.jsonResult);
res = window.JSON.parse(res);
}
for (let i = 0; i < res.lstDocument.length; i++) {
let filePath = encodeURI(res.lstDocument[i].filePath)
filePath = encodeImgPath(filePath)
let url = filePath;
if (!url) throw new Error(`Image url is empty`)
console.log('Your image url ', url)
convertImageToBase64(url, base64 => {
console.log(base64); // 输出图片的Base64编码
console.log('Your image base64 ', base64)
insertFn(base64, "", "")
});
console.log('Your image url ', url)
// insertFn(url, "", "")
}
},
}
},
onChange(editor) {
console.log(editor.getHtml())
}
}
// 先创建 editor
const editor = E.createEditor({
selector: '#editor-text-area',
content: [],
// html: '',
config: editorConfig,
})
// 创建 toolbar
const toolbar = E.createToolbar({
editor,
selector: '#editor-toolbar',
config: {
excludeKeys: ['fullScreen','group-video','fontFamily','insertLink'],
}
})
// 点击空白处 focus 编辑器
document.getElementById('editor-text-area').addEventListener('click', e => {
if (e.target.id === 'editor-text-area') {
editor.blur()
editor.focus(true) // focus 到末尾
}
})
</script>
</body>
</html>
PC信息展示
创建wangeditorShow.html文件,进行信息展示
<!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>信息预览</title>
<link href="showStyle.css" rel="stylesheet">
<style>
#editor-text-area img{
display: inline !important;
max-width: 100%;
}
</style>
</head>
<body>
<div id="content">
<div id="editor-container">
<div id="title-container">
<input readonly="readonly">
</div>
<div class="title-span">
<span id="info_author"></span>
<span id="info_dept" style="color: #38388f;"></span>
<span id="info_date"></span>
</div>
<div id="editor-text-area"></div>
<div class="title-span">
<span id="info_readNum">阅读 0</span>
</div>
</div>
</div>
<script src="index.js"></script>
<script src="../../../scripts/lib/js/jquery-1.11.0.js"></script>
<script src="../../../scripts/lib/encrypt/base64.js"></script>
<script src="../../../scripts/lib/encrypt/des.js"></script>
<script>
//取URL参数
QueryString = function (item, href) {
var str = location.search;
if (arguments.length == 2) str = href;
var svalue = str.match(new RegExp("[\?\&]" + item + "=([^\&]*)(\&?)", "i"));
return svalue ? unescape(svalue[1]) : svalue;
}
var id = escape(QueryString("id"));
var title = escape(QueryString("title"));
var content = escape(QueryString("contentUrl"));
if (content && content != 'undefined') {
content = decodeURIComponent(content);
}else{
content = "";
}
window.onload = function () {
if(id && id != 'null' && id != 'undefined'){
$.ajax({
url: ms.commonServiceUrl+"mymsg/getMsgInfoById?data="+id,
type: 'POST',
contentType: 'application/json;charset=UTF-8',
dataType: 'json',
success: function (data) {
if (data.result && data.responseObjects.length >0) {
let obj = data.responseObjects[0];
if (obj.title) {
$("#title-container input").val(obj.title);
}
if (obj.personName) {
$("#info_author").text(obj.personName);
}
if (obj.deptName) {
$("#info_dept").text(obj.deptName);
}
if (obj.createdDate) {
$("#info_date").text(obj.createdDate);
}
if(obj.readNum){
$("#info_readNum").text("阅读 "+obj.readNum);
}
if (obj.contentUrl) {
fetchData(obj.contentUrl).then(data => {
$("#editor-text-area").html(data);
});
}
} else {
}
},
});
}else{
if (title && title != 'null' && title != 'undefined') {
var data = decodeURIComponent(title);
$("#title-container input").val(data);
}
if (content && content != 'null' && content != 'undefined') {
fetchData(content).then(data => {
$("#editor-text-area").html(data);
});
}
}
}
async function fetchData(content){
try {
const response = await fetch(content);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.text(); // 或者 response.json() 等,取决于响应内容的类型
return data;
} catch (error) {
console.error('There was a problem fetching the data:', error);
}
}
</script>
</body>
</html>
移动端展示
创建wangeditorShow.vue文件
<template>
<div id="content">
<div id="editor-container">
<div id="title-container">
<input readonly="readonly">
</div>
<div class="title-span">
<span id="info_author"></span>
<span id="info_dept" style="color: #38388f;"></span>
<span id="info_date"></span>
</div>
<div id="editor-text-area"></div>
<div class="title-span">
<span id="info_readNum">阅读 0</span>
</div>
</div>
</div>
</template>
<script>
import {wfi} from "../scripts/framework/FrameworkInfo_index";
//引入jquery
import $ from 'jquery';
import http from "../scripts/framework/FrameworkInfo_http";
export default {
data() {
return {
id: null,
title: null,
content: null,
}
},
computed: {
},
methods: {
async fetchData(content){
try {
const response = await fetch(content);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.text(); // 或者 response.json() 等,取决于响应内容的类型
return data;
} catch (error) {
console.error('There was a problem fetching the data:', error);
}
}
},
mounted() {
this.id = this.$route.query.id;
if(!this.id){
// this.id = "13a2fdbb-7123-4002-bf7a-d7d231b8240f";
wfi.utils.showErrorMsg('信息ID为空,请联系管理员排查!')
return
}
if(this.id && this.id != 'null' && this.id != 'undefined'){
let msSvsFullName = wfi.constants.msServiceNameMap['system'];
http.post(`/${msSvsFullName}/mymsg/getMsgInfoById`,{data:this.id}).then(resp => {
if (resp.status == 200 && resp.data.result && resp.data.responseObjects.length >0) {
console.info(resp.data.responseObjects[0]);
let obj = resp.data.responseObjects[0];
if (obj.title) {
$("#title-container input").val(obj.title.trim());
}
if (obj.personName) {
$("#info_author").text(obj.personName);
}
if (obj.deptName) {
$("#info_dept").text(obj.deptName);
}
if (obj.createdDate) {
$("#info_date").text(obj.createdDate);
}
if(obj.readNum){
$("#info_readNum").text("阅读 "+obj.readNum);
}
if (obj.contentUrl) {
let url = obj.contentUrl;
this.fetchData(url).then(data => {
$("#editor-text-area").html(data);
});
}
}
}).catch(e => {
wfi.commonMethods.commonErrorHandle(e)
});
}
}
}
</script>
<style scoped src="../assets/css/showStyle.css">
//<style scoped >
//@import url('../assets/css/showStyle.css');
</style>
3.后端功能
创建一个VO对象接收前台信息
public class MsgVo implements Serializable {
private String title;
private String content;
private String content2;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getContent2() {
return content2;
}
public void setContent2(String content2) {
this.content2 = content2;
}
}
创建一个Controller与前台交互
@RequestMapping("/mymsg")
@RestController
public class AddMsgController {
private static final Log log = LogFactory.getLog(AddMsgController.class);
@PostMapping("/addMsg")
public void addMsg(HttpServletRequest request, HttpServletResponse response, @RequestBody MsgVo msgVo){
log.info("信息发布");
MsgInfoServiceRequest serviceRequest = new MsgInfoServiceRequest();
MsgInfoDto dto = new MsgInfoDto();
dto.setContent(msgVo.getContent());
dto.setContent2(msgVo.getContent2());
serviceRequest.setQueryObject(dto);
serviceRequest.setClient(ServiceUtils.getDefaultClient());
serviceRequest.setMethod("saveInfo");
MsgInfoServiceResponse response1 = CommonFun.commonExcuteXfire(serviceRequest);
try {
response.getWriter().write(JsonUtils.encode(response1));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@PostMapping("/getMsgInfoById")
public void getMsgInfoById(HttpServletRequest request, HttpServletResponse response){
String id = request.getParameter("data");
MsgInfoServiceRequest serviceRequest = new MsgInfoServiceRequest();
MsgInfoDto dto = new MsgInfoDto();
dto.setId(id);
serviceRequest.setQueryObject(dto);
serviceRequest.setClient(ServiceUtils.getDefaultClient());
serviceRequest.setMethod("getMsgInfoById");
MsgInfoServiceResponse response1 = CommonFun.commonExcuteXfire(serviceRequest);
try {
response.getWriter().write(JsonUtils.encode(response1));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
}
}
创建ServiceImpl实现类,进行具体实现
@Service
public class MsgInfoServiceImpl {
public void saveInfo(MsgInfoServiceRequest request, MsgInfoServiceResponse response) {
MsgInfoDto queryObject = request.getQueryObject();
String content = queryObject.getContent();
String content2 = queryObject.getContent2();
// 获取临时目录的路径
String tempDir = System.getProperty("java.io.tmpdir");
File imageDir = new File(tempDir);
if (!imageDir.exists()) {
imageDir.mkdir();
}
String uuid = UUID.randomUUID().toString();
String uuid2 = UUID.randomUUID().toString();
String path = tempDir + "/" + uuid + ".txt"; //
String path2 = tempDir + "/" + uuid2 + ".txt"; //
File txt = new File(path);
File txt2 = new File(path2);
try {
FileOutputStream fileOutputStream = new FileOutputStream(txt);
PrintStream printStream = new PrintStream(fileOutputStream);
// 转码,转化为utf-8
String htmls = new String(content.getBytes("utf-8"), "utf-8");
printStream.println(htmls);
fileOutputStream.flush();
printStream.flush();
fileOutputStream.close();
printStream.close();
String contentUrl = StaticFileUtils.getINSTANCE().uploadFileByHttp("msg", txt);
response.setContentUrl(contentUrl);
Document doc = Jsoup.parse(content2);
String summary = doc.text();
if(StringUtils.isNotBlank(summary) && summary.length() >20){
summary = summary.substring(0, 20);
}
FileOutputStream fileOutputStream2 = new FileOutputStream(txt2);
PrintStream printStream2 = new PrintStream(fileOutputStream2);
String htmls2 = new String(content2.getBytes("utf-8"), "utf-8");
printStream2.println(htmls2);
fileOutputStream2.flush();
printStream2.flush();
fileOutputStream2.close();
printStream2.close();
String contentUrl2 = StaticFileUtils.getINSTANCE().uploadFileByHttp("msg", txt2);
response.setContentUrl2(contentUrl2);
response.setSummary(summary);
} catch (IOException e) {
genError(response, e.getMessage());
response.setResult(false);
return;
} finally {
txt.delete();
txt2.delete();
}
ServiceUtils.genDefaultSuccussMsg(request, response);
}
public void getMsgInfoById(MsgInfoServiceRequest request, MsgInfoServiceResponse response) {
MsgInfoDto queryObject = request.getQueryObject();
String id = queryObject.getId();
MsgInfoEntity po = myToolDao.getById(MsgInfoEntity.class, id);
if ("finish".equals(po.getFlowStatus())) {
po.setReadNum(IntegerUtils.add(po.getReadNum(), 1));
myToolDao.update(po);
}
List<MsgInfoDto> dtos = new ArrayList();
dtos.add((MsgInfoDto) Po2DtoCopyTool.po2dto(po));
response.setResponseObject(dtos.get(0));
response.setResponseObjects(dtos);
}
}
部分代码省略,主要知道大概思路即可,知道主要实现步骤,剩下的配套代码结合自己使用的架子,进行修改补充