创欧科技 网站建设,wordpress 英文 企业网站模板,企业网站系统建设,以企业介绍为主做外贸网站好吗项目介绍
本项目借鉴了雀语的一些UI设计#xff0c;实现了文档在线管理的功能#xff0c;知识库可以对不同分类的文档建立不同的库#xff0c;知识库里面左边可以维护菜单菜单目录#xff0c;右边实现在线预览。该项目可以防止用户下载和复制文档#xff0c;只支持在线预…项目介绍
本项目借鉴了雀语的一些UI设计实现了文档在线管理的功能知识库可以对不同分类的文档建立不同的库知识库里面左边可以维护菜单菜单目录右边实现在线预览。该项目可以防止用户下载和复制文档只支持在线预览。
技术实现
文档上传的时候通过aspose把图片word和execel类型的文件转为pdf文件存储到nas前端预览使用pdf.js加载预览pdf文档
项目预览 开发介绍
目录维护
左侧菜单点击加号可以维护目录 前端代码
body classwhite-bgdiv classibox-contentform classform-horizontal m-t idform1input idid nameid typehidden /input idparentid nameparentid typehidden /input iddeletemark namedeletemark typehidden /input idcreatedate namecreatedate typehidden /input idcreateuserId namecreateuserId typehidden /input idcreateusername namecreateusername typehidden /input idmodifydate namemodifydate typehidden /input idmodifyuserid namemodifyuserid typehidden /input idmodifyusername namemodifyusername typehidden /div classrowdiv classcol-xs-12input typetext idname classform-control placeholder名称 //divdiv classcol-xs-12textarea idremark classform-control placeholder描述 stylewidth:100%;height:100px;/textarea/divdiv classcol-xs-12input typetext idsortcode classform-control placeholder序号 //divdiv classcol-xs-12textarea idkeywords classform-control placeholder关键词 stylewidth:100%;height:100px;/textarea/div/div/form/div
/body
后端代码 ApiOperation(value 保存, notes )PostMapping(value/Save)public Result Save(RequestBody String json) {DocmMenu model (DocmMenu) JSON.parseObject(json, DocmMenu.class);if(StrUtils.isBlank(model.getId())){model.setCreateuserid(admin);model.setDeletemark(new BigDecimal(0));model.setCreateusername(admin);model.setCreatedate(DateUtils.getNow());model.setId(UUID.randomUUID().toString());docmMenuService.add(model);}else {docmMenuService.update(model);}return Result.success(model,成功);} 文档维护
文档维护使用Dropzone实现前端文件上传支持历史版本管理。 前端代码
!DOCTYPE html
html
headtitle文档管理/titlemeta charsetutf-8meta nameviewport contentwidthdevice-width, initial-scale1.0link relshortcut icon hreffavicon.icolink href../css/bootstrap.min.css relstylesheetlink href../css/font-awesome.min.css relstylesheetlink href../css/plugins/jsTree/style.min.css relstylesheetlink href../css/plugins/bootstrap-table/bootstrap-table.min.css relstylesheetlink href../css/plugins/dropzone/dropzone.css relstylesheet typetext/css /!-- 全局js --script src../js/jquery.min.js/scriptscript src../js/bootstrap.min.js/scriptscript src../js/plugins/jsTree/jstree.min.js/scriptscript src../js/plugins/bootstrap-table/bootstrap-table.min.js/scriptscript src../js/plugins/layer/layer.min.js/scriptscript src../js/plugins/dropzone/dropzone.js/scriptscript src../js/bd-framework.js/script/head
body classwhite-bg
divtable idtable stylewidth:100%/tablediv idmain-container stylemargin-top: 10px;form action/ classdropzone enctypemultipart/form-data idmy-dropzonemethodpost/formtextarea idremark classform-control placeholder上传备注 stylewidth:100%;height:100px;/textareadiv!--上传按钮提供多张图片一次性上传的功能--button idsubmit-all classbtn btn-outline btn-default typesubmit 上传/button/div/div/div
scriptvar $table $(#table);$(function () {getFileList();})function getFileList() {$table.html();$.get(/api/Attachment/getList?businessidGetQuery(businessid), {}, function (result, resultState) {if (result.code 200) {if (result.data.length 0) {$table.append(tr styletext-align: center; vertical-align: middle; border-style:solid; border-width:1px; td styleborder-style:solid; border-width:1px;div stylepadding:10px;width:30px;序号/div/td td styleborder-style:solid; border-width:1px;div stylepadding:10px;width:100px;文件名称/div/td td styleborder-style:solid; border-width:1px;div stylepadding:10px;width:80px;上传人员/div/td td styleborder-style:solid; border-width:1px;div stylepadding:10px;width:100px;上传日期/div/td td styleborder-style:solid; border-width:1px;div stylepadding:10px;width:200px;备注/div/td td styleborder-style:solid; border-width:1px;div stylepadding:10px;width:50px;操作/div/td /tr);for (var i 0; i result.data.length; i) {if (result.data[i].EXTENSION ! pdf || (result.data[i].TMP_BUSINESSID || ) ) {$table.append(tr styleborder-style:solid; border-width:1px; td styleborder-style:solid; border-width:1px;text-align:center; (i 1) /td td styleborder-style:solid; border-width:1px; a onclickDownload(\ result.data[i].ID \) stylefloat: left hrefjavascript:void(0)u result.data[i].NAME /u/a /td td styleborder-style:solid; border-width:1px; result.data[i].CREATEUSERNAME /td td styleborder-style:solid; border-width:1px; result.data[i].CREATETIME /td td styleborder-style:solid; border-width:1px; (result.data[i].REMARK || ) /td td styleborder-style:solid; border-width:1px; div styleposition:relative;padding:10px; button typebutton onclickFileDelete(\ result.data[i].ID \) data-id result.data[i].ID 删除 /button /div /td /tr);}}}}})}function FileDelete(Id) {var index parent.layer.confirm(是否删除, {btn: [是, 否] //按钮}, function () {$.get(/api/Attachment/deleteByPDF, { id: Id }, function (result, resultState) {if (result.code 200) {parent.layer.msg(删除成功);getFileList();} else {parent.layer.msg(result.message);getFileList();}}, json);parent.layer.close(index);}, function () {parent.layer.close(index);});}function Download(Id) {window.open(/api/Attachment/downFile?id Id);};
/script
scriptvar loadIndex null;//Dropzone的初始化myDropzone为form的idDropzone.options.myDropzone {params: {businessid: GetQuery(businessid),filePath: DocM// 您可以在这里添加其他参数},//指定上传的路径url: /api/Attachment/uploadFilesToPDF,maxFiles: 1, // 用于限制此Dropzone将处理的最大文件数maxFilesize: 100, // MBacceptedFiles: .doc,.docx,.pdf,.PDF,.jpg,.JPG,.gif,.GIF,.png,.PNG,.bmp,.BMP, // 上传的类型dictDefaultMessage:div styletext-align: center; vertical-align: middle;padding-top:38px;span将文件拖拽到此处/span \span(或点击上传)/span/div,dictResponseError: Error while uploading file!,dictFileTooBig: 最大100M,//添加上传取消和删除预览的链接默认不添加addRemoveLinks: true,//关闭自动上传功能默认会true会自动上传//也就是添加一张图片向服务器发送一次请求autoProcessQueue: false,//允许上传多个uploadMultiple: false,//记得修改web.config 限制上传文件大小的节parallelUploads: 100,init: function () {var submitButton document.querySelector(#submit-all)myDropzone this; // closure//为上传按钮添加点击事件submitButton.addEventListener(click, function () {Dropzone.options.myDropzone.params.remark $(#remark).val();loadIndex parent.layer.load();//手动上传所有文件myDropzone.processQueue();});//当添加图片后的事件上传按钮恢复可用this.on(addedfile, function () {$(#submit-all).removeAttr(disabled);});//当上传完成后的事件接受的数据为JSON格式this.on(complete, function (data) {parent.layer.close(loadIndex);if (this.getUploadingFiles().length 0 this.getQueuedFiles().length 0) {var res eval(( data.xhr.responseText ));var msg;if (res.code 200) {msg 已成功上传;this.removeAllFiles();getFileList()}else {msg 上传失败失败的原因是 res.Message;}parent.layer.msg(msg);}});//删除文件的事件当上传的文件为空时使上传按钮不可用状态this.on(removedfile, function () {if (this.getAcceptedFiles().length 0) {$(#submit-all).attr(disabled, true);}});}};
/script/body
后端代码 CrossOriginApiOperation(value 文件上传并且转为PDF, notes )PostMapping(/uploadFileToPDF)public Result uploadFileToPDF(RequestBody byte[] fileByte,RequestParam(value fileName,required true) String fileName,RequestParam(value filePath,required true) String filePath,RequestParam(value area,required false) String area,RequestParam(value businessid,required false) String businessid,RequestParam(value tmp_businessid,required false) String tmp_businessid,RequestParam(value createUserId,required false) String createUserId,RequestParam(value createUserName,required false) String createUserName,RequestParam(value remark,required false) String remark) {try {String uuid UUID.randomUUID().toString();// 获取文件名String extension getFileExtension(fileName);String newFileName uuid . extension;DocM_Attachment attachment new DocM_Attachment();attachment.setBusinessid(businessid);attachment.setFilename(fileName);DateTimeFormatter fmt DateTimeFormatter.ofPattern(yyMMdd);String uploadPath filePath FileConnect LocalDate.now().format(fmt);attachment.setId(uuid);attachment.setCreateTime(DateUtils.getNow());attachment.setDirectory(uploadPath);attachment.setFilepath(uploadPath FileConnect newFileName);attachment.setFileSize(bytesToMegabytes((long)fileByte.length));attachment.setArea(area);attachment.setTmp_businessid(tmp_businessid);attachment.setExtension(extension);attachment.setCreateUserId(createUserId);attachment.setCreateUserName(createUserName);attachment.setRemark(remark);SmbFileUtils.save(fileByte,uploadPath,newFileName);InputStream inputStream new ByteArrayInputStream(fileByte);OutputStream pdfStream null;if(extension.equals(docx) || extension.equals(doc)){pdfStream doc2pdf(inputStream);}else if(extension.equals(png) || extension.equals(jpg) || extension.equals(gif)|| extension.equals(bmp)){pdfStream image2pdf(inputStream);}DocM_Attachment pdfAttachment new DocM_Attachment();BeanUtils.copyProperties(attachment,pdfAttachment);pdfAttachment.setId(UUID.randomUUID().toString());String newPdfFileName pdfAttachment.getId() .pdf;pdfAttachment.setFilepath(uploadPath FileConnect newPdfFileName);pdfAttachment.setArea(pdf);pdfAttachment.setTmp_businessid(attachment.getId());pdfAttachment.setFilename(fileName.split(\\.)[0] .pdf);pdfAttachment.setExtension(pdf);SmbFileUtils.save(toByteArray(pdfStream),uploadPath,newPdfFileName);inputStream.close();pdfStream.close();attachmentService.add(attachment);attachmentService.add(pdfAttachment);return Result.success(uuid,成功);} catch (Exception e) {e.printStackTrace();return Result.failed(文件上传失败);}}
知识库详情页面
左侧菜单使用JSTree.js插件右侧文档预览使用pdf.js插件
前端代码
!DOCTYPE html
html
headtitle文档管理/titlemeta charsetutf-8meta nameviewport contentwidthdevice-width, initial-scale1.0link relshortcut icon hreffavicon.icolink href../css/bootstrap.min.css relstylesheetlink href../css/font-awesome.min.css relstylesheetlink href../css/plugins/jsTree/style.min.css relstylesheetlink href../css/plugins/bootstrap-table/bootstrap-table.min.css relstylesheet!-- 全局js --script src../js/jquery.min.js/scriptscript src../js/bootstrap.min.js/scriptscript src../js/plugins/jsTree/jstree.min.js/scriptscript src../js/plugins/bootstrap-table/bootstrap-table.min.js/scriptscript src../js/plugins/layer/layer.min.js/scriptscript src../js/bd-framework.js/script
/head
body classwhite-bgstyle.pdf{position:relative; }.main_container{display:flex;}.left_container{width:320px; border-right:1px solid #e7e9e8; overflow:scroll;}.right_contaner{flex:1;}#tree{}.jstree-anchor {font-size: 14px !important;/* color:#262626 !important;*/}.jstree-default .jstree-node {margin-top: 3px; /* 调整节点顶部的间距 */margin-bottom: 3px; /* 调整节点底部的间距 */}.btn-power{display:none; }/stylediv classmain_containerdiv classleft_containerdiv iddirectoryExpandinput typetext idKeywords classform-control placeholder关键词搜索 /div styledisplay:flex; justify-content: space-between;align-items: center;margin-bottom:8px;padding:4px;div onclickdirectoryExpand() stylefont-size: 14px;color:#262626;padding-left:25px;i classfa fa-bars stylemargin-right:12px; /i目录/divdivdiv styleposition: absolute;margin-left:-90px;margin-top:-12px; classbtn-powerbutton data-toggledropdown classbtn btn-outline btn-default dropdown-toggle typebutton aria-expandedfalsei classglyphicon glyphicon-plus aria-hiddentrue/i /buttonbutton onclickbtn_deleteAll() classbtn btn-outline btn-default typebutton i classglyphicon glyphicon-trash aria-hiddentrue/i /buttonul classdropdown-menu pull-rightlia hrefjavascript:; onclickbtn_add()新建分组/a/lilia hrefjavascript:; onclickbtn_edit()编辑分组/a/lilia hrefjavascript:; onclickbtn_uploadFile()上传文档/a/li/ul/div/div/divdiv idtree/div/divdiv iddirectoryNoExpand styledisplay:none;div onclickdirectoryNoExpand() stylefont-size: 14px;color:#262626;padding-left:12px;i classfa fa-bars /i/div/div/divdiv classright_contaner div classpdf iframe idiframe1 width100% height100% src frameborder0 /iframe/div/div/divscriptvar currentNode null;var loadIndex null;function directoryExpand() {$(#directoryExpand).hide();$(.left_container).css(width, 40px);$(#directoryNoExpand).show(); }function directoryNoExpand() {$(#directoryExpand).show();$(.left_container).css(width, 320px);$(#directoryNoExpand).hide();}$(function () {getPower();$(this).bind(contextmenu, function (e) {e.preventDefault();});$(.left_container).height($(window).height() - 7);$(.pdf).height($(window).height() - 7);document.getElementById(iframe1).onload function () {parent.layer.close(loadIndex);}$(#Keywords).keydown(function (event) {initTree();});})var isManager false;function getPower() {$.get(/api/DocManage/IsPowerMange, { id: GetQuery(Id) }, function (result, resultState) {if (result.code 200) {$(.btn-power).show();isManager true;}initTree();}, json);}var $tree $(#tree);function initTree() {if (!!GetQuery(Id)) {var postData {}postData.id GetQuery(Id);postData.keywords $(#Keywords).val();$.get(/api/DocManage/GetTreeJson, postData, function (result, resultState) {if (isManager) {$tree.on(activate_node.jstree, function (obj, e) {var node e.node;if (node.id ! undefined) {currentNode node;loadPdf(node.id);}}).jstree({multiple : true,plugins: [checkbox],checkbox: {three_state: false,whole_node: false,tie_selection: false // 只有点击复选框才能勾选节点},core: {data: result.data,check_callback: function (operation, node, node_parent, node_position, more) {// 允许所有操作包括创建、重命名、删除、移动和复制节点return true;}}})} else {$tree.on(activate_node.jstree, function (obj, e) {var node e.node;if (node.id ! undefined) {currentNode node;loadPdf(node.id);}}).jstree({multiple : true,core: {data: result.data}})}}, json);}}function loadPdf(businessid) {loadIndex parent.layer.msg(文档加载中请耐心等待, { time: 1000 * 20 });$.get(/api/Attachment/getList?businessidbusinessidareapdf, {}, function (result, resultState) {if (result.code 200) {if (result.data.length 0) {for (var i 0; i result.data.length; i) {if (result.data[i].EXTENSION pdf) {if (result.data[i].ID ! currentNode.id) {$(#iframe1).attr(src, ../js/plugins/pdfjs-2.14.305-dist/web/DocManageViewer.html?file /api/Attachment/viewFile?id result.data[i].ID);}break;}}} else {$(#iframe1).attr(src, );parent.layer.close(loadIndex);}}}, json);}function btn_add() {var viewData {};if (currentNode) {viewData.parentid currentNode.id;} else {viewData.parentid GetQuery(Id)}var layerIndex parent.layer.open({btn: [确认], //按钮yes: function (index, layero) {var postData parent.$(#layui-layer-iframe index)[0].contentWindow.GetWebControls(#form1);$.ajax({url: /api/DocManage/Save,type: post,contentType: application/json,data: JSON.stringify(postData),dataType: json,success: function (result) {parent.layer.close(layerIndex);// 在选中的节点下插入新节点$tree.jstree(create_node, currentNode, { text: result.data.name, id: result.data.id, icon: no-icon }, last, function (newNode) {//console.log(New node created with ID:, newNode.id);});}});},type: 2,title: 新增,area: [350px, 550px],shadeClose: true, //开启遮罩关闭content: /docManage/menuEdit.html,success: function (layero, index) {parent.$(#layui-layer-iframe index)[0].contentWindow.SetWebControls(viewData);}});}function btn_edit() {var viewData {};if (currentNode) {viewData.parentid currentNode.id;} else {parent.layer.msg(请选择一个分组)return;}var layerIndex parent.layer.open({btn: [确认, 删除], //按钮yes: function (index, layero) {var postData parent.$(#layui-layer-iframe index)[0].contentWindow.GetWebControls(#form1);$.ajax({url: /api/DocManage/Save,type: post,contentType: application/json,data: JSON.stringify(postData),dataType: json,success: function (result) {parent.layer.close(layerIndex);$tree.jstree(rename_node, currentNode, result.data.name);}});}, btn2: function (index, layero) {var index parent.layer.confirm(是否删除, {btn: [是, 否] //按钮}, function () {if (currentNode) {var postData {};postData.id currentNode.id;$.get(/api/DocManage/Delete, postData, function (result, resultState) {if (result.code 200) {parent.layer.close(layerIndex);$tree.jstree(delete_node, currentNode);}}, json);}parent.layer.close(index);}, function () {parent.layer.close(index);});},type: 2,title: 编辑,area: [350px, 550px],shadeClose: true, //开启遮罩关闭content: /docManage/menuEdit.html,success: function (layero, index) {$.get(/api/DocManage/GetDetail, { id: currentNode.id }, function (result, resultState) {parent.$(#layui-layer-iframe index)[0].contentWindow.SetWebControls(result.data);}, json);}});}function btn_deleteAll() {var index parent.layer.confirm(是否删除, {btn: [是, 否] //按钮}, function () {var postData {};postData.ids getTreeSelectedData().join(,);$.get(/api/DocManage/DeleteAll, postData, function (result, resultState) {parent.layer.close(index);$tree.jstree(delete_node, getTreeSelectedData());}, json);}, function () {parent.layer.close(index);});}function btn_uploadFile() {var viewData {};if (currentNode) {viewData.parentid currentNode.id;} else {parent.layer.msg(请选择一个分组)return;}parent.layer.open({type: 2,title: 上传文档,area: [850px, 750px],shadeClose: true, //开启遮罩关闭content: /docManage/uploadFileViewToPDF.html?businessid currentNode.id,success: function (layero, index) {}});}function getTreeSelectedData() {var nodes $tree.jstree(get_checked); //使用get_checked方法return nodes;}/script/body
文件转为pdf
使用aspose把文件转为pdf public OutputStream doc2pdf(InputStream inputStream) throws Exception {// 验证License 若不验证则转化出的pdf文档会有水印产生if (!getLicense()) {return null;}try {OutputStream outputStream new ByteArrayOutputStream();Document doc new Document(inputStream);// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换doc.save(outputStream, SaveFormat.PDF);return outputStream;} catch (Exception e) {e.printStackTrace();throw new Exception(word转pdf失败);}}
访问nas
使用jcifs-ng访问nas
导入包
!-- samba共享文件夹--
dependencygroupIdeu.agno3.jcifs/groupIdartifactIdjcifs-ng/artifactIdversion2.1.3/version
/dependency
工具栏
public class SmbFileUtils {static String ip ;static String domain ;static String userName ;static String password ;static void SmbFileUtils(){}//根据账号密码登录private static CIFSContext withNTLMCredentials(CIFSContext ctx) {return ctx.withCredentials(new NtlmPasswordAuthenticator(domain,userName, password));}//保存文件public static String save(byte[] byteArr, String url,String fileName) throws IOException {InputStream in new ByteArrayInputStream(byteArr);String status ;try {CIFSContext context withNTLMCredentials(SingletonContext.getInstance());SmbFileWriter.createDirectory(smb:// domain / url, context);boolean result SmbFileWriter.writeSmbFile(in, smb:// domain / url / fileName, context);status success;} catch (Exception e) {e.printStackTrace();status error;} finally {in.close();return status;}}//获取文件public static InputStream getFile(String filePath) throws IOException {String url smb:// domain / filePath;try {CIFSContext context withNTLMCredentials(SingletonContext.getInstance());SmbFileReader reader new SmbFileReader();byte[] byteArr reader.readSmbFile(url, context);InputStream input new ByteArrayInputStream(byteArr);return input;} catch (Exception e) {e.printStackTrace();}return null;}//删除文件public static String delete(String filePath) throws IOException {String status ;String url smb:// domain / filePath;try {CIFSContext context withNTLMCredentials(SingletonContext.getInstance());SmbFile file new SmbFile(url, context);if (file.exists()) {file.delete();status success;}} catch (Exception e) {e.printStackTrace();status error;}return status;}//获取文件列表public static ListHashMap getPathList(String path) throws IOException {String url smb:// domain / path;ListHashMap filesList new ArrayList();CIFSContext context withNTLMCredentials(SingletonContext.getInstance());try {SmbFile smbFile new SmbFile(url, context);SmbFile[] files smbFile.listFiles();for (SmbFile file : files) {HashMap fileMap new HashMap();fileMap.put(fileName,file.getName());SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd HH:mm:ss); // 定义日期格式fileMap.put(date,sdf.format(new Date(file.getDate())));fileMap.put(size, String.format(%.2f, (file.length()/1024.0)/1024.0)MB);fileMap.put(fileType,file.isDirectory()?文件夹:文件);filesList.add(fileMap);}} catch (Exception e) {e.printStackTrace();}return filesList;}static class SmbFileReader {public byte[] readSmbFile(String path, CIFSContext context) throws IOException {try {SmbFile smbFile new SmbFile(path, context);long fileSize smbFile.length();if (fileSize Integer.MAX_VALUE) {System.out.println(file too big...);return null;}InputStream fi smbFile.getInputStream();byte[] buffer new byte[(int) fileSize];int offset 0;int numRead 0;while (offset buffer.length (numRead fi.read(buffer, offset, buffer.length - offset)) 0) {offset numRead;}// 确保所有数据均被读取if (offset ! buffer.length) {throw new IOException(Could not completely read file smbFile.getName());}fi.close();return buffer;} catch (Exception e) {e.printStackTrace();}return null;}}static class SmbFileWriter {static boolean writeSmbFile(String source, String target, CIFSContext context) throws IOException {if (StrUtils.isEmpty(source) || StrUtils.isEmpty(target)) {return false;}return writeSmbFile(Files.newInputStream(Paths.get(source)),target, context);}static boolean writeSmbFile(InputStream in, String target, CIFSContext context) throws IOException {if (Objects.nonNull(in) StrUtils.isNotEmpty(target)) {try (SmbFile file new SmbFile(target, context)) {try (SmbFile parent new SmbFile(file.getParent(), context)) {if (!parent.exists()) {createDirectory(file.getParent(), context);}if (!file.exists()) {file.createNewFile();}}try (OutputStream os file.getOutputStream()) {byte[] bytes new byte[1024];while (in.read(bytes) ! -1) {os.write(bytes);}return true;}}finally {in.close();}}return false;}static SmbFile createDirectory(String targetDir, CIFSContext context) throws MalformedURLException,CIFSException, MalformedURLException {try (SmbFile dir new SmbFile(targetDir, context)) {if (!dir.exists()) {dir.mkdir();}return dir;}}}
}