基于SSM的多文档编辑器(文档编辑/插件管理)

JAVA多文档编辑器

前言:当前版本的文档编辑器实现了文档编辑时常用的插件支持;文档管理;编辑器插件管理;用户设置等功能。其他优化功能后期支持继续扩展。该系统可以作为课设、毕设使用,也可以单独使用项目的SSM框架。

系统介绍

    该系统实现一个B/S架构、自定义高亮显示方案的多文本编辑器,主要包括文档编辑,编辑器设置,插件管理三个模块,主要功能是对文档的添加修改,对文档进行样式的选定,以及对编辑器插件的管理。

相关技术

    系统后台使用SSM核心技术框架,数据库为MySql,前端页面集成JQuery+Bootstrap实现。部署简单,tomcat容器即可。

系统设计

    对于系统应用者,即系统的访问者来说,我们采用B/S的接入方式,可以进行文档的编辑、删除、分享等操作,并且为他们提供个性化的内容与服务。

架构模型

本系统采用:模型—视图—控制器(Model-View-Controller,MVC)处理模型。
  1. 模型架构

在这里插入图片描述

  1. 处理流程
    这是系统处理架构图

功能模块

  主要实现了文档管理、编辑器设置、插件管理、用户管理,登录/登出等功能模块。具体模块划分见业务模块图:

功能模块划分

系统截图

  1. 登录界面系统登录界面
  2. 文档管理已保存文档管理
  3. 文档编辑/编辑器设置文档编辑
  4. 插件管理插件管理
  5. 用户管理用户信息管理

部分源码

代码结构

后端代码结构

主要代码

  1. 用户管理API
package com.smwx.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.smwx.domain.TUser;
import com.smwx.service.IUserService;
import com.smwx.utils.PageBean;

@Controller
@RequestMapping("user")
public class UserController {

    @Autowired
    private IUserService iUserService;
    
    /**
     * 用户管理列表
     * @author lzj
     * @return
     */
    @RequestMapping("index")
    public String index(ModelMap mp,PageBean pageBean){
        pageBean = iUserService.findByPageBean(pageBean);
        mp.put("pageBean", pageBean);
        return "jsp/sys/user_index";
    }
    
    /**
     * 根据id删除一条求用户记录
     * @author lzj
     * @param id
     * @return
     */
    @RequestMapping("deleteUser")
    @ResponseBody
    public Boolean deleteDocType(String id ){
        boolean bool = iUserService.deleteUser(Integer.parseInt(id));
        return bool;
    }
    /**
     * @description: 编辑用户时回显用户信息
     * @author lzj
     * @date 2018年3月19日 下午10:30:25
     * @return String
     */
    @RequestMapping("viewUser")
    @ResponseBody
    public TUser viewUser(String id){
        TUser user = iUserService.findById(Integer.parseInt(id));
        return user;
    }
    /**
     * @description: 更新用户记录
     * @author lzj
     * @date 2018年3月20日 上午10:00:02
     * @return boolean
     */
    @RequestMapping("updateUser")
    @ResponseBody
    public boolean updateUser(TUser tUser){
        boolean result = iUserService.updateUser(tUser);
        if(result){
            return true;
        }else{
            return false;
        }
    }
    /**
     * 验证账号是否重复
     * @description: 更新用户记录
     * @author lzj
     * @return boolean
     */
    @RequestMapping("findIsReAccouont")
    @ResponseBody
    public boolean findIsReAccouont(String account){
    	boolean bool = iUserService.findIsReAccouont(account);
    	return bool;
    }
    /**
     * 保存注册用户
     * @description: 更新用户记录
     * @author lzj
     * @return boolean
     */
    @RequestMapping("saveUser")
    @ResponseBody
    public boolean saveUser(TUser tuser){
    	boolean bool = iUserService.saveUser(tuser);
    	return bool;
    }
    /**
	 * 登陆
	 * @author lzj
	 * @return
	 */
	@RequestMapping("loginOn")
	@ResponseBody
	public boolean loginOn(TUser tuser,HttpServletRequest request){
		boolean bool = iUserService.loginOn(tuser,request);
		return bool;
	}
}

  1. 文档编辑
package com.smwx.controller;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.gson.Gson;
import com.smwx.domain.DDoc;
import com.smwx.service.IDocService;
import com.smwx.service.IEdSetService;
import com.smwx.vo.TreeVo;
/**
 * 编辑器设置控制层
 * @author lzj
 *
 */
@Controller
@RequestMapping("edset")
public class EdSetController {
	@Autowired
	private IEdSetService edSetService;
	@Autowired
	private IDocService docService;
	/**
	 * 编辑器主页面
	 * @author lzj
	 * @param mp
	 * @return
	 */
	@RequestMapping("index")
	public String index(ModelMap mp){
		TreeVo treeVo = edSetService.findTreeAll();
		mp.put("treeVo", new Gson().toJson(treeVo));
		return "jsp/ed/ed_index";
	}
	/**
	 * 根据文档和文档类型
	 * 查询对应的编辑器和文档内容
	 * @author lzj
	 * @return
	 */
	@RequestMapping("findByDocAndEd")
	@ResponseBody
	public DDoc findByDocAndEd(Integer docTypeId,Integer docId){
		DDoc doc = edSetService.findByDocAndEd(docTypeId,docId);
		return doc;
	}
	/**
	 * 
	 * @author lzj
	 * @return
	 */
	@RequestMapping("saveEdSet")
	@ResponseBody
	public boolean saveEdSet(DDoc doc,HttpServletRequest request){
		boolean bool = docService.updateDoc(doc, request);
		return bool;
	}
}

  1. 插件管理
package com.smwx.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.gson.Gson;
import com.smwx.domain.DDocType;
import com.smwx.domain.DDocTypePlug;
import com.smwx.domain.DPlugIn;
import com.smwx.service.IDocTypePlugService;
import com.smwx.service.IDocTypeService;
import com.smwx.service.IPlugInService;
import com.smwx.utils.PageBean;

@Controller
@RequestMapping("pi")
public class PlugInController {

    @Autowired
    private IPlugInService iPlugInService;
    @Autowired
    private IDocTypeService iDocTypeService;
    @Autowired
    private IDocTypePlugService iDocTypePlugService;
    
    /**
     * @description 插件列表
     * @author lzj
     * @date 2018年3月22日 上午11:35:15
     * @return String
     */
    @RequestMapping("index")
    public String index(ModelMap mp,PageBean pageBean){
        pageBean = iPlugInService.findByPageBean(pageBean);
        mp.put("pageBean", pageBean);
        return "jsp/pi/pi_index";
    }
    /**
     * @description 插件安装请求,首次页面访问
     * @author lzj
     * @date 2018年3月24日 下午2:44:23
     * @return String
     */
    @RequestMapping("grant")
    public String grant(ModelMap mp,PageBean pageBean, String id){
        //存放系统中所有文档类型集合
        List<DDocType> typeList = new ArrayList<>();
        //存放指定文档类型关联的插件
        List<DPlugIn> plugList = new ArrayList<>();
        //查询所有的文档类型
        typeList = iDocTypeService.findAll();
        //查询到所有的内置插件
        pageBean = iPlugInService.findByPageBean(pageBean);
        List<DPlugIn> content = new ArrayList<>();
        //获取插件分页列表
        content = (List<DPlugIn>) pageBean.getContent();
        //插件类型ID为空时,首次进入该页面
        if(id == null){
            plugList = iPlugInService.findByDocType(typeList.get(0).getDocTypeId());
        }else{//插件类型ID为不为空时
            plugList = iPlugInService.findByDocType(Integer.valueOf(id));
            for(int i=0; i<typeList.size(); i++){
                if(typeList.get(i).getDocTypeId() == Integer.valueOf(id)){
                    typeList.get(i).setIsSelected("yes");   
                }
            }
        }
        for(int i=0; i<plugList.size();i++){
            for(int j=0; j<content.size(); j++){
                if(plugList.get(i).getPlugInId() == content.get(j).getPlugInId() ){
                    content.get(j).setIsChecked("yes");
                }
            }
        }
        pageBean.setContent(content);
        mp.put("pageBean", pageBean);
        mp.put("docTypes", typeList);
        return "jsp/pi/pi_grant";
    }
    /**
     * @description 插件安装请求,通过选择文档类型时,请求插件列表
     * @author lzj
     * @date 2018年3月29日 下午9:01:08
     * @return Map<String,Object>
     */
    @RequestMapping("grantWith")
    @ResponseBody
    public Map<String, Object> grantWith(PageBean pageBean, String id){
        //存放系统中所有文档类型集合
        List<DDocType> typeList = new ArrayList<>();
        //存放指定文档类型关联的插件
        List<DPlugIn> plugList = new ArrayList<>();
        //查询所有的文档类型
        typeList = iDocTypeService.findAll();
        //查询到所有的内置插件
        pageBean = iPlugInService.findByPageBean(pageBean);
        List<DPlugIn> content = new ArrayList<>();
        //获取插件分页列表
        content = (List<DPlugIn>) pageBean.getContent();
        plugList = iPlugInService.findByDocType(Integer.valueOf(id));
        for(int i=0; i<typeList.size(); i++){
            if(typeList.get(i).getDocTypeId() == Integer.valueOf(id)){
                typeList.get(i).setIsSelected("yes");   
            }
        }
        for(int i=0; i<plugList.size();i++){
            for(int j=0; j<content.size(); j++){
                if(plugList.get(i).getPlugInId() == content.get(j).getPlugInId() ){
                    content.get(j).setIsChecked("yes");
                }
            }
        }
        pageBean.setContent(content);
        Map<String, Object> map = new HashMap<>();
        map.put("pageBean", pageBean);
        map.put("docTypes", typeList);
        Gson gson = new Gson();
        return map;
    }
    /**
     * @description 保存插件记录
     * @author lzj
     * @date 2018年3月22日 下午1:26:05
     * @return boolean
     */
    @RequestMapping("savePlugIn")
    @ResponseBody
    public boolean savePlugIn(DPlugIn dPlugIn){
        boolean bool = iPlugInService.savePlugIn(dPlugIn);
        return bool;
    }
    /**
     * @description 根据id删除指定的插件
     * @author lzj
     * @date 2018年3月22日 下午1:40:32
     * @return boolean
     */
    @RequestMapping("deletePlugIn")
    @ResponseBody
    public boolean deletePlugIn(String id){
        boolean bool = iPlugInService.deletePlugIn(Integer.valueOf(id));
        return bool;
    }
    /**
     * @description 安装插件
     * @author lzj
     * @date 2018年4月1日 上午9:58:16
     * @return boolean
     */
    @RequestMapping("install")
    @ResponseBody
    public boolean install(DDocTypePlug dDocTypePlug){
        boolean bool = iDocTypePlugService.saveDocTypePlug(dDocTypePlug);
        return bool;
    }
    /**
     * @description 卸载文档类型指定的插件
     * @author lzj
     * @date 2018年4月1日 上午10:02:43
     * @return String
     */
    @RequestMapping("unInstall")
    @ResponseBody
    public String unInstall(DDocTypePlug dDocTypePlug){
        boolean bool = iDocTypePlugService.deleteByDocTypeAndPlugIn(dDocTypePlug);
        if(bool){//卸载成功
            return "success";
        }else{//卸载失败,插件未安装
            return "not exist";
        }
    }
}

  1. 登录页面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
			+ path + "/";
%>
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <!-- Meta, title, CSS, favicons, etc. -->
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>文档管理系统</title>

  
	<!-- Bootstrap -->
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <!-- Font Awesome -->
    <link href="css/font-awesome.min.css" rel="stylesheet">
    <!-- NProgress -->
    <link href="css/nprogress.css" rel="stylesheet">
 	<!-- Animate.css -->
    <link href="css/animate.min.css" rel="stylesheet">
    <!-- Custom Theme Style -->
    <link href="css/custom.min.css" rel="stylesheet">
  </head>

  <body class="login">
    <div>
      <a class="hiddenanchor" id="signup"></a>
      <a class="hiddenanchor" id="signin"></a>

      <div class="login_wrapper">
        <div class="animate form login_form">
          <section class="login_content">
            <form>
              <h1>Welcome Login</h1>
              <div>
                <input id="loginAcc" type="text" class="form-control" placeholder="Username" required="" />
              </div>
              <div>
                <input id="loginPass" type="password" class="form-control" placeholder="Password" required="" />
              </div>
              <div>
                <a id="login" class="btn btn-default submit" href="javaScript:void(0)">Log in</a>
                <a class="reset_pass" href="#">Lost your password?</a>
              </div>

              <div class="clearfix"></div>

              <div class="separator">
                <p class="change_link">New to site?
                  <a href="#signup" class="to_register"> Create Account </a>
                </p>

                <div class="clearfix"></div>
                <br />

                <div>
                  <h1><i class="fa fa-paw"></i> North University of China!</h1>
                  <p>©2018 Code2Life. Software School of North University of China</p>
                </div>
              </div>
            </form>
          </section>
        </div>

        <div id="register" class="animate form registration_form">
          <section class="login_content">
            <form id="createAccont">
              <h1>Create Account</h1>
              <div>
                <input id="createAcc" type="text" class="form-control" placeholder="Account" required="" />
              </div>
              <div>
                <input id="createPass" type="password" class="form-control" placeholder="Password" required="" />
              </div>
              <div>
                <input id="createPassAgain" type="password" class="form-control" placeholder="Password again" required="" />
              </div>
              <div>
                <input id="createUser" type="text" class="form-control" placeholder="Username" required="" />
              </div>
              <div>
                <input id="createTele" type="number" class="form-control" placeholder="Telephone" required="" />
              </div>
              <div>
                <a id="submit" class="btn btn-default submit" href="javaScript:void(0)">Submit</a>
              </div>

              <div class="clearfix"></div>

              <div class="separator">
                <p class="change_link">Already a member ?
                  <a href="#signin" class="to_register"> Log in </a>
                </p>

                <div class="clearfix"></div>
                <br />

                <div>
                  <h1><i class="fa fa-paw"></i> North University of China!</h1>
                  <p>©2018 lzj. Software School of North University of China</p>
                </div>
              </div>
            </form>
          </section>
        </div>
      </div>
    </div>
<!-- jQuery -->
<script src="js/jquery.min.js"></script>
<script src="js/layer/layer.js"></script>
<script type="text/javascript">
//登陆
$("#login").click(function(){
	if(''!=$("#loginAcc").val().trim() && ''!=$("#loginPass").val().trim()){
		$.ajax({
			type : "POST",
			url : "user/loginOn.do",
			data : getParam('login'),
			dataType : "json",
			success : function(result) {
				if(result){
					window.location.href="menu/home.do";
				}else{
					layer.alert("登录名或密码错误!",{icon:2});
				}
			}
		}) 
	}else{
		layer.msg("账号密码不能为空!",{icon:2})
	}
})
//创建用户
$("#submit").click(function(){
	var obj = verification();
	if(obj.flag){
		layer.msg(obj.msg,{icon:2})
	}else{
		$.ajax({
			type : "POST",
			url : "user/saveUser.do",
			data : getParam('create'),
			dataType : "json",
			success : function(result) {
				if(result){
					layer.msg("创建成功!",{icon:1});
					setTimeout(function () {
						window.location.href="login.do#signin";
				   }, 500);
				}else{
					layer.msg("创建失败!",{icon:2});
				}
			}
		}) 
	}
})
//创建用户验证
function verification(){
	var flag = false,msg='';
	if(!flag){
		$("#createAccont").find("input").each(function(){
			if(''==$(this).val().trim()){
				flag = true;
				msg = "请将信息填写完整!";
				return false;
			}
		})
	}
	if(!flag){
		if($("#createPass").val().trim()!=$("#createPassAgain").val().trim()){
			flag = true;
			msg = "两次密码不一致,请重新输入!";
		}
	}
	if(!flag){
	var account = $("#createAcc").val().trim();
		$.ajax({
			type : "POST",
			url : "user/findIsReAccouont.do",
			data : "account="+account,
			async:false,
			dataType : "json",
			success : function(result) {
				if(result){
					flag = true;
					msg = "账号重复请重新输入!";
				}
			}
		}) 
	}
	return {flag:flag,msg:msg};
}

//获取填写信息
function getParam(result){
	var longinParam = {
		userNum:$("#loginAcc").val(),
		password:$("#loginPass").val()
	}
	var createParam = {
		userName:$("#createUser").val(),
		userNum:$("#createAcc").val(),
		password:$("#createPass").val(),
		userContact:$("#createTele").val(),
	}
	if('login'==result){
		return longinParam;
	}else if('create'==result){
		return createParam;
	}
}
</script>
  </body>
</html>


最后

   这个系统本人自己开发,实现了基本的富文本编辑功能,可以供学习课设、毕设题目参考使用,后期根据需要还可以继续完善扩展。感兴趣可扫码关注咨询
   ![公众号二维码](https://img-blog.csdnimg.cn/382bda3ca7a5409ba8073792f151e6f8.jpeg#pic_center)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值