From dfc7d7184fed84f654162ed362bbb4412dd96677 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Wed, 20 Nov 2019 12:04:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8E=E5=8F=B0=E5=B0=8F=E8=AF=B4=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E5=8A=9F=E8=83=BD=E4=B8=8A=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/BookContentController.java | 128 - .../books/controller/BookController.java | 20 +- .../books/controller/BookIndexController.java | 128 - .../com/java2nb/books/dao/BookContentDao.java | 3 + .../com/java2nb/books/dao/BookIndexDao.java | 2 + .../books/service/BookContentService.java | 30 - .../books/service/BookIndexService.java | 30 - .../java2nb/books/service/BookService.java | 4 +- .../service/impl/BookContentServiceImpl.java | 55 - .../service/impl/BookIndexServiceImpl.java | 55 - .../books/service/impl/BookServiceImpl.java | 28 +- .../src/main/resources/application.yml | 2 +- .../mybatis/books/BookContentMapper.xml | 5 + .../mybatis/books/BookIndexMapper.xml | 4 + .../static/js/appjs/books/book/book.js | 16 +- .../js/appjs/books/bookIndex/bookIndex.js | 16 +- .../resources/static/wangEditor/.eslintignore | 2 - .../static/wangEditor/.eslintrc.json | 38 - .../static/wangEditor/.gitattributes | 22 - .../resources/static/wangEditor/.gitignore | 51 - .../resources/static/wangEditor/.npmignore | 5 - .../main/resources/static/wangEditor/ISSUE.md | 157 - .../main/resources/static/wangEditor/LICENSE | 22 - .../resources/static/wangEditor/README.md | 70 - .../resources/static/wangEditor/bower.json | 20 - .../static/wangEditor/docs/dev/README.md | 25 - .../docs/usage/01-getstart/01-demo.md | 41 - .../docs/usage/01-getstart/02-use-module.md | 49 - .../docs/usage/01-getstart/03-sperate.md | 48 - .../docs/usage/01-getstart/04-multi.md | 50 - .../docs/usage/02-content/01-set-content.md | 46 - .../docs/usage/02-content/02-get-content.md | 80 - .../docs/usage/02-content/03-use-textarea.md | 25 - .../docs/usage/02-content/04-get-json.md | 82 - .../docs/usage/03-config/01-menu.md | 52 - .../docs/usage/03-config/02-debug.md | 21 - .../docs/usage/03-config/03-onchange.md | 40 - .../docs/usage/03-config/04-z-index.md | 19 - .../docs/usage/03-config/05-lang.md | 30 - .../docs/usage/03-config/06-paste.md | 33 - .../usage/03-config/07-linkImgCallback.md | 12 - .../docs/usage/03-config/08-linkCheck.md | 16 - .../docs/usage/03-config/09-onfocus.md | 19 - .../docs/usage/03-config/10-onblur.md | 20 - .../docs/usage/03-config/11-linkImgCheck.md | 15 - .../docs/usage/03-config/12-colors.md | 29 - .../docs/usage/03-config/13-emot.md | 48 - .../docs/usage/04-uploadimg/01-show-tab.md | 52 - .../docs/usage/04-uploadimg/02-base64.md | 23 - .../usage/04-uploadimg/03-upload-config.md | 188 - .../docs/usage/04-uploadimg/04-qiniu.md | 115 - .../usage/05-other/01-全屏-预览-查看源码.md | 10 - .../docs/usage/05-other/02-上传附件.md | 24 - .../docs/usage/05-other/03-markdown.md | 12 - .../wangEditor/docs/usage/05-other/04-xss.md | 23 - .../docs/usage/05-other/05-react.md | 7 - .../wangEditor/docs/usage/05-other/06-vue.md | 7 - .../wangEditor/docs/usage/05-other/07-ng.md | 3 - .../wangEditor/docs/usage/05-other/08-api.md | 27 - .../static/wangEditor/docs/usage/README.md | 3 - .../static/wangEditor/example/README.md | 1 - .../example/demo/in-react/package.json | 19 - .../example/demo/in-react/public/favicon.ico | Bin 24838 -> 0 bytes .../example/demo/in-react/public/index.html | 40 - .../demo/in-react/public/manifest.json | 15 - .../example/demo/in-react/src/App.css | 24 - .../example/demo/in-react/src/App.js | 48 - .../example/demo/in-react/src/App.test.js | 8 - .../example/demo/in-react/src/index.css | 5 - .../example/demo/in-react/src/index.js | 8 - .../example/demo/in-react/src/logo.svg | 7 - .../in-react/src/registerServiceWorker.js | 51 - .../wangEditor/example/demo/in-vue/.babelrc | 14 - .../example/demo/in-vue/.editorconfig | 9 - .../example/demo/in-vue/.postcssrc.js | 8 - .../example/demo/in-vue/build/build.js | 35 - .../demo/in-vue/build/check-versions.js | 48 - .../example/demo/in-vue/build/dev-client.js | 9 - .../example/demo/in-vue/build/dev-server.js | 89 - .../example/demo/in-vue/build/utils.js | 71 - .../demo/in-vue/build/vue-loader.conf.js | 12 - .../demo/in-vue/build/webpack.base.conf.js | 58 - .../demo/in-vue/build/webpack.dev.conf.js | 35 - .../demo/in-vue/build/webpack.prod.conf.js | 120 - .../example/demo/in-vue/config/dev.env.js | 6 - .../example/demo/in-vue/config/index.js | 38 - .../example/demo/in-vue/config/prod.env.js | 3 - .../wangEditor/example/demo/in-vue/index.html | 11 - .../example/demo/in-vue/package.json | 60 - .../example/demo/in-vue/src/App.vue | 31 - .../example/demo/in-vue/src/assets/logo.png | Bin 6849 -> 0 bytes .../demo/in-vue/src/components/Editor.vue | 34 - .../demo/in-vue/src/components/Hello.vue | 53 - .../example/demo/in-vue/src/main.js | 13 - .../example/demo/in-vue/static/.gitkeep | 0 .../wangEditor/example/demo/test-amd-main.js | 4 - .../wangEditor/example/demo/test-amd.html | 15 - .../example/demo/test-css-reset.html | 66 - .../wangEditor/example/demo/test-emot.html | 84 - .../example/demo/test-fullscreen.html | 114 - .../example/demo/test-get-content.html | 34 - .../wangEditor/example/demo/test-getJSON.html | 30 - .../wangEditor/example/demo/test-lang.html | 31 - .../wangEditor/example/demo/test-menus.html | 26 - .../wangEditor/example/demo/test-mult.html | 44 - .../wangEditor/example/demo/test-onblur.html | 23 - .../example/demo/test-onchange.html | 24 - .../wangEditor/example/demo/test-onfocus.html | 22 - .../wangEditor/example/demo/test-paste.html | 25 - .../example/demo/test-set-content.html | 35 - .../wangEditor/example/demo/test-sperate.html | 35 - .../example/demo/test-textarea.html | 33 - .../example/demo/test-uploadimg.html | 58 - .../static/wangEditor/example/favicon.ico | Bin 4286 -> 0 bytes .../wangEditor/example/icomoon/Read Me.txt | 7 - .../example/icomoon/demo-files/demo.css | 155 - .../example/icomoon/demo-files/demo.js | 30 - .../wangEditor/example/icomoon/demo.html | 505 -- .../example/icomoon/fonts/icomoon.eot | Bin 5656 -> 0 bytes .../example/icomoon/fonts/icomoon.svg | 37 - .../example/icomoon/fonts/icomoon.ttf | Bin 5492 -> 0 bytes .../example/icomoon/fonts/icomoon.woff | Bin 5568 -> 0 bytes .../wangEditor/example/icomoon/selection.json | 775 --- .../wangEditor/example/icomoon/style.css | 113 - .../static/wangEditor/example/index.html | 62 - .../static/wangEditor/example/pay.png | Bin 95517 -> 0 bytes .../static/wangEditor/example/server/index.js | 88 - .../static/wangEditor/example/server/util.js | 14 - .../resources/static/wangEditor/gulpfile.js | 122 - .../resources/static/wangEditor/package.json | 60 - .../wangEditor/release/fonts/w-e-icon.woff | Bin 5568 -> 0 bytes .../static/wangEditor/release/wangEditor.css | 405 -- .../static/wangEditor/release/wangEditor.js | 4679 ----------------- .../wangEditor/release/wangEditor.min.css | 1 - .../wangEditor/release/wangEditor.min.js | 4 - .../wangEditor/release/wangEditor.min.js.map | 1 - .../static/wangEditor/src/fonts/w-e-icon.woff | Bin 5568 -> 0 bytes .../static/wangEditor/src/js/.babelrc | 10 - .../static/wangEditor/src/js/command/index.js | 106 - .../static/wangEditor/src/js/config.js | 387 -- .../static/wangEditor/src/js/editor/index.js | 339 -- .../src/js/editor/upload/progress.js | 65 - .../src/js/editor/upload/upload-img.js | 316 -- .../static/wangEditor/src/js/index.js | 24 - .../src/js/menus/backColor/index.js | 46 - .../wangEditor/src/js/menus/bold/index.js | 60 - .../wangEditor/src/js/menus/code/index.js | 150 - .../wangEditor/src/js/menus/droplist.js | 130 - .../wangEditor/src/js/menus/emoticon/index.js | 115 - .../src/js/menus/foreColor/index.js | 46 - .../wangEditor/src/js/menus/head/index.js | 70 - .../wangEditor/src/js/menus/img/index.js | 252 - .../static/wangEditor/src/js/menus/index.js | 125 - .../wangEditor/src/js/menus/italic/index.js | 60 - .../wangEditor/src/js/menus/justify/index.js | 44 - .../wangEditor/src/js/menus/link/index.js | 168 - .../wangEditor/src/js/menus/list/index.js | 82 - .../wangEditor/src/js/menus/menu-list.js | 63 - .../static/wangEditor/src/js/menus/panel.js | 195 - .../wangEditor/src/js/menus/quote/index.js | 75 - .../wangEditor/src/js/menus/redo/index.js | 35 - .../src/js/menus/strikethrough/index.js | 60 - .../wangEditor/src/js/menus/table/index.js | 376 -- .../src/js/menus/underline/index.js | 60 - .../wangEditor/src/js/menus/undo/index.js | 35 - .../wangEditor/src/js/menus/video/index.js | 86 - .../wangEditor/src/js/selection/index.js | 186 - .../static/wangEditor/src/js/text/index.js | 551 -- .../static/wangEditor/src/js/util/dom-core.js | 488 -- .../wangEditor/src/js/util/paste-handle.js | 86 - .../wangEditor/src/js/util/poly-fill.js | 48 - .../wangEditor/src/js/util/replace-lang.js | 21 - .../static/wangEditor/src/js/util/util.js | 71 - .../static/wangEditor/src/less/common.less | 19 - .../static/wangEditor/src/less/droplist.less | 48 - .../static/wangEditor/src/less/icon.less | 102 - .../static/wangEditor/src/less/menus.less | 33 - .../static/wangEditor/src/less/panel.less | 159 - .../static/wangEditor/src/less/text.less | 77 - .../templates/books/bookIndex/bookIndex.html | 15 +- novel-front/pom.xml | 6 + .../books/web/BookController.java | 4 + .../src/main/resources/application.yml | 4 +- sql/2019-11-20.sql | 2 + 184 files changed, 98 insertions(+), 16353 deletions(-) delete mode 100644 novel-admin/src/main/java/com/java2nb/books/controller/BookContentController.java delete mode 100644 novel-admin/src/main/java/com/java2nb/books/controller/BookIndexController.java delete mode 100644 novel-admin/src/main/java/com/java2nb/books/service/BookContentService.java delete mode 100644 novel-admin/src/main/java/com/java2nb/books/service/BookIndexService.java delete mode 100644 novel-admin/src/main/java/com/java2nb/books/service/impl/BookContentServiceImpl.java delete mode 100644 novel-admin/src/main/java/com/java2nb/books/service/impl/BookIndexServiceImpl.java delete mode 100644 novel-admin/src/main/resources/static/wangEditor/.eslintignore delete mode 100644 novel-admin/src/main/resources/static/wangEditor/.eslintrc.json delete mode 100644 novel-admin/src/main/resources/static/wangEditor/.gitattributes delete mode 100644 novel-admin/src/main/resources/static/wangEditor/.gitignore delete mode 100644 novel-admin/src/main/resources/static/wangEditor/.npmignore delete mode 100644 novel-admin/src/main/resources/static/wangEditor/ISSUE.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/LICENSE delete mode 100644 novel-admin/src/main/resources/static/wangEditor/README.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/bower.json delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/dev/README.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/01-demo.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/02-use-module.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/03-sperate.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/04-multi.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/01-set-content.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/02-get-content.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/03-use-textarea.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/04-get-json.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/01-menu.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/02-debug.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/03-onchange.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/04-z-index.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/05-lang.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/06-paste.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/07-linkImgCallback.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/08-linkCheck.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/09-onfocus.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/10-onblur.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/11-linkImgCheck.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/12-colors.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/13-emot.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/01-show-tab.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/02-base64.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/03-upload-config.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/04-qiniu.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/01-全屏-预览-查看源码.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/02-上传附件.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/03-markdown.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/04-xss.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/05-react.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/06-vue.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/07-ng.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/08-api.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/docs/usage/README.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/README.md delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/package.json delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/public/favicon.ico delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/public/index.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/public/manifest.json delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/App.css delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/App.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/App.test.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/index.css delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/logo.svg delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/registerServiceWorker.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/.babelrc delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/.editorconfig delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/.postcssrc.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/build.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/check-versions.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/dev-client.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/dev-server.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/utils.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/vue-loader.conf.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/webpack.base.conf.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/webpack.dev.conf.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/webpack.prod.conf.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/config/dev.env.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/config/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/config/prod.env.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/index.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/package.json delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/App.vue delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/assets/logo.png delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/components/Editor.vue delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/components/Hello.vue delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/main.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/static/.gitkeep delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-amd-main.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-amd.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-css-reset.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-emot.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-fullscreen.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-get-content.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-getJSON.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-lang.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-menus.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-mult.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-onblur.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-onchange.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-onfocus.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-paste.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-set-content.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-sperate.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-textarea.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/demo/test-uploadimg.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/favicon.ico delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/icomoon/Read Me.txt delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/icomoon/demo-files/demo.css delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/icomoon/demo-files/demo.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/icomoon/demo.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/icomoon/fonts/icomoon.eot delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/icomoon/fonts/icomoon.svg delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/icomoon/fonts/icomoon.ttf delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/icomoon/fonts/icomoon.woff delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/icomoon/selection.json delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/icomoon/style.css delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/index.html delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/pay.png delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/server/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/example/server/util.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/gulpfile.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/package.json delete mode 100644 novel-admin/src/main/resources/static/wangEditor/release/fonts/w-e-icon.woff delete mode 100644 novel-admin/src/main/resources/static/wangEditor/release/wangEditor.css delete mode 100644 novel-admin/src/main/resources/static/wangEditor/release/wangEditor.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/release/wangEditor.min.css delete mode 100644 novel-admin/src/main/resources/static/wangEditor/release/wangEditor.min.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/release/wangEditor.min.js.map delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/fonts/w-e-icon.woff delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/.babelrc delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/command/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/config.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/editor/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/editor/upload/progress.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/editor/upload/upload-img.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/backColor/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/bold/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/code/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/droplist.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/emoticon/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/foreColor/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/head/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/img/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/italic/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/justify/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/link/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/list/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/menu-list.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/panel.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/quote/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/redo/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/strikethrough/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/table/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/underline/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/undo/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/menus/video/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/selection/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/text/index.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/util/dom-core.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/util/paste-handle.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/util/poly-fill.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/util/replace-lang.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/js/util/util.js delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/less/common.less delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/less/droplist.less delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/less/icon.less delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/less/menus.less delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/less/panel.less delete mode 100644 novel-admin/src/main/resources/static/wangEditor/src/less/text.less create mode 100644 sql/2019-11-20.sql diff --git a/novel-admin/src/main/java/com/java2nb/books/controller/BookContentController.java b/novel-admin/src/main/java/com/java2nb/books/controller/BookContentController.java deleted file mode 100644 index b0752f8..0000000 --- a/novel-admin/src/main/java/com/java2nb/books/controller/BookContentController.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.java2nb.books.controller; - -import java.util.List; -import java.util.Map; - -import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; -import io.swagger.annotations.ApiOperation; - - -import com.java2nb.books.domain.BookContentDO; -import com.java2nb.books.service.BookContentService; -import com.java2nb.common.utils.PageBean; -import com.java2nb.common.utils.Query; -import com.java2nb.common.utils.R; - -/** - * - * - * @author xiongxy - * @email 1179705413@qq.com - * @date 2019-11-13 09:28:11 - */ - -@Controller -@RequestMapping("/books/bookContent") -public class BookContentController { - @Autowired - private BookContentService bookContentService; - - @GetMapping() - @RequiresPermissions("books:bookContent:bookContent") - String BookContent() { - return "books/bookContent/bookContent"; - } - - @ApiOperation(value = "获取列表", notes = "获取列表") - @ResponseBody - @GetMapping("/list") - @RequiresPermissions("books:bookContent:bookContent") - public R list(@RequestParam Map params) { - //查询列表数据 - Query query = new Query(params); - List bookContentList = bookContentService.list(query); - int total = bookContentService.count(query); - PageBean pageBean = new PageBean(bookContentList, total); - return R.ok().put("data", pageBean); - } - - @ApiOperation(value = "新增页面", notes = "新增页面") - @GetMapping("/add") - String add() { - return "books/bookContent/add"; - } - - @ApiOperation(value = "修改页面", notes = "修改页面") - @GetMapping("/edit/{id}") - String edit(@PathVariable("id") Long id, Model model) { - BookContentDO bookContent = bookContentService.get(id); - model.addAttribute("bookContent", bookContent); - return "books/bookContent/edit"; - } - - @ApiOperation(value = "查看页面", notes = "查看页面") - @GetMapping("/detail/{id}") - String detail(@PathVariable("id") Long id, Model model) { - BookContentDO bookContent = bookContentService.get(id); - model.addAttribute("bookContent", bookContent); - return "books/bookContent/detail"; - } - - /** - * 保存 - */ - @ApiOperation(value = "新增", notes = "新增") - @ResponseBody - @PostMapping("/save") - public R save( BookContentDO bookContent) { - if (bookContentService.save(bookContent) > 0) { - return R.ok(); - } - return R.error(); - } - - /** - * 修改 - */ - @ApiOperation(value = "修改", notes = "修改") - @ResponseBody - @RequestMapping("/update") - public R update( BookContentDO bookContent) { - bookContentService.update(bookContent); - return R.ok(); - } - - /** - * 删除 - */ - @ApiOperation(value = "删除", notes = "删除") - @PostMapping("/remove") - @ResponseBody - public R remove( Long id) { - if (bookContentService.remove(id) > 0) { - return R.ok(); - } - return R.error(); - } - - /** - * 删除 - */ - @ApiOperation(value = "批量删除", notes = "批量删除") - @PostMapping("/batchRemove") - @ResponseBody - public R remove(@RequestParam("ids[]") Long[] ids) { - bookContentService.batchRemove(ids); - return R.ok(); - } - -} diff --git a/novel-admin/src/main/java/com/java2nb/books/controller/BookController.java b/novel-admin/src/main/java/com/java2nb/books/controller/BookController.java index 4b68fcf..efa5166 100644 --- a/novel-admin/src/main/java/com/java2nb/books/controller/BookController.java +++ b/novel-admin/src/main/java/com/java2nb/books/controller/BookController.java @@ -150,7 +150,9 @@ public class BookController { } @GetMapping("/index") - String BookIndex() { + String BookIndex(Long bookId, Model model) { + + model.addAttribute("bookId",bookId); return "books/bookIndex/bookIndex"; } @@ -167,26 +169,26 @@ public class BookController { } /** - * 删除 + * 删除章节 */ - @ApiOperation(value = "删除", notes = "删除") + @ApiOperation(value = "删除章节", notes = "删除章节") @PostMapping("/index/remove") @ResponseBody - public R indexRemove( Long id) { - if (bookService.indexRemove(id) > 0) { + public R indexRemove( Long id,Long bookId) { + if (bookService.indexRemove(id,bookId) > 0) { return R.ok(); } return R.error(); } /** - * 删除 + * 删除章节 */ - @ApiOperation(value = "批量删除", notes = "批量删除") + @ApiOperation(value = "批量删除章节", notes = "批量删除章节") @PostMapping("/index/batchRemove") @ResponseBody - public R indexRemove(@RequestParam("ids[]") Long[] ids) { - bookService.batchIndexRemove(ids); + public R indexRemove(@RequestParam("ids[]") Long[] ids,@RequestParam("bookIds[]") Long[] bookIds) { + bookService.batchIndexRemove(ids,bookIds); return R.ok(); } } diff --git a/novel-admin/src/main/java/com/java2nb/books/controller/BookIndexController.java b/novel-admin/src/main/java/com/java2nb/books/controller/BookIndexController.java deleted file mode 100644 index 6f7dcd4..0000000 --- a/novel-admin/src/main/java/com/java2nb/books/controller/BookIndexController.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.java2nb.books.controller; - -import java.util.List; -import java.util.Map; - -import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; -import io.swagger.annotations.ApiOperation; - - -import com.java2nb.books.domain.BookIndexDO; -import com.java2nb.books.service.BookIndexService; -import com.java2nb.common.utils.PageBean; -import com.java2nb.common.utils.Query; -import com.java2nb.common.utils.R; - -/** - * - * - * @author xiongxy - * @email 1179705413@qq.com - * @date 2019-11-13 09:28:15 - */ - -@Controller -@RequestMapping("/books/bookIndex") -public class BookIndexController { - @Autowired - private BookIndexService bookIndexService; - - @GetMapping() - @RequiresPermissions("books:bookIndex:bookIndex") - String BookIndex() { - return "books/bookIndex/bookIndex"; - } - - @ApiOperation(value = "获取列表", notes = "获取列表") - @ResponseBody - @GetMapping("/list") - @RequiresPermissions("books:bookIndex:bookIndex") - public R list(@RequestParam Map params) { - //查询列表数据 - Query query = new Query(params); - List bookIndexList = bookIndexService.list(query); - int total = bookIndexService.count(query); - PageBean pageBean = new PageBean(bookIndexList, total); - return R.ok().put("data", pageBean); - } - - @ApiOperation(value = "新增页面", notes = "新增页面") - @GetMapping("/add") - String add() { - return "books/bookIndex/add"; - } - - @ApiOperation(value = "修改页面", notes = "修改页面") - @GetMapping("/edit/{id}") - String edit(@PathVariable("id") Long id, Model model) { - BookIndexDO bookIndex = bookIndexService.get(id); - model.addAttribute("bookIndex", bookIndex); - return "books/bookIndex/edit"; - } - - @ApiOperation(value = "查看页面", notes = "查看页面") - @GetMapping("/detail/{id}") - String detail(@PathVariable("id") Long id, Model model) { - BookIndexDO bookIndex = bookIndexService.get(id); - model.addAttribute("bookIndex", bookIndex); - return "books/bookIndex/detail"; - } - - /** - * 保存 - */ - @ApiOperation(value = "新增", notes = "新增") - @ResponseBody - @PostMapping("/save") - public R save( BookIndexDO bookIndex) { - if (bookIndexService.save(bookIndex) > 0) { - return R.ok(); - } - return R.error(); - } - - /** - * 修改 - */ - @ApiOperation(value = "修改", notes = "修改") - @ResponseBody - @RequestMapping("/update") - public R update( BookIndexDO bookIndex) { - bookIndexService.update(bookIndex); - return R.ok(); - } - - /** - * 删除 - */ - @ApiOperation(value = "删除", notes = "删除") - @PostMapping("/remove") - @ResponseBody - public R remove( Long id) { - if (bookIndexService.remove(id) > 0) { - return R.ok(); - } - return R.error(); - } - - /** - * 删除 - */ - @ApiOperation(value = "批量删除", notes = "批量删除") - @PostMapping("/batchRemove") - @ResponseBody - public R remove(@RequestParam("ids[]") Long[] ids) { - bookIndexService.batchRemove(ids); - return R.ok(); - } - -} diff --git a/novel-admin/src/main/java/com/java2nb/books/dao/BookContentDao.java b/novel-admin/src/main/java/com/java2nb/books/dao/BookContentDao.java index 28e9de6..d91952f 100644 --- a/novel-admin/src/main/java/com/java2nb/books/dao/BookContentDao.java +++ b/novel-admin/src/main/java/com/java2nb/books/dao/BookContentDao.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Map; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; /** * @@ -31,4 +32,6 @@ public interface BookContentDao { int batchRemove(Long[] ids); void insertBatch(List newContentList); + + void removeByBookIds(@Param("bookIds") String bookIds); } diff --git a/novel-admin/src/main/java/com/java2nb/books/dao/BookIndexDao.java b/novel-admin/src/main/java/com/java2nb/books/dao/BookIndexDao.java index 2f6d3a3..46b84ca 100644 --- a/novel-admin/src/main/java/com/java2nb/books/dao/BookIndexDao.java +++ b/novel-admin/src/main/java/com/java2nb/books/dao/BookIndexDao.java @@ -40,4 +40,6 @@ public interface BookIndexDao { List listVO(Query query); int countVO(Query query); + + void removeByBookIds(@Param("bookIds") String bookIds); } diff --git a/novel-admin/src/main/java/com/java2nb/books/service/BookContentService.java b/novel-admin/src/main/java/com/java2nb/books/service/BookContentService.java deleted file mode 100644 index 412c8be..0000000 --- a/novel-admin/src/main/java/com/java2nb/books/service/BookContentService.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.java2nb.books.service; - -import com.java2nb.books.domain.BookContentDO; - -import java.util.List; -import java.util.Map; - -/** - * - * - * @author xiongxy - * @email 1179705413@qq.com - * @date 2019-11-13 09:28:11 - */ -public interface BookContentService { - - BookContentDO get(Long id); - - List list(Map map); - - int count(Map map); - - int save(BookContentDO bookContent); - - int update(BookContentDO bookContent); - - int remove(Long id); - - int batchRemove(Long[] ids); -} diff --git a/novel-admin/src/main/java/com/java2nb/books/service/BookIndexService.java b/novel-admin/src/main/java/com/java2nb/books/service/BookIndexService.java deleted file mode 100644 index c2738ad..0000000 --- a/novel-admin/src/main/java/com/java2nb/books/service/BookIndexService.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.java2nb.books.service; - -import com.java2nb.books.domain.BookIndexDO; - -import java.util.List; -import java.util.Map; - -/** - * - * - * @author xiongxy - * @email 1179705413@qq.com - * @date 2019-11-13 09:28:15 - */ -public interface BookIndexService { - - BookIndexDO get(Long id); - - List list(Map map); - - int count(Map map); - - int save(BookIndexDO bookIndex); - - int update(BookIndexDO bookIndex); - - int remove(Long id); - - int batchRemove(Long[] ids); -} diff --git a/novel-admin/src/main/java/com/java2nb/books/service/BookService.java b/novel-admin/src/main/java/com/java2nb/books/service/BookService.java index fd4b10c..5433303 100644 --- a/novel-admin/src/main/java/com/java2nb/books/service/BookService.java +++ b/novel-admin/src/main/java/com/java2nb/books/service/BookService.java @@ -42,7 +42,7 @@ public interface BookService { int indexVOCount(Query query); - int indexRemove(Long id); + int indexRemove(Long id, Long bookId); - int batchIndexRemove(Long[] ids); + int batchIndexRemove(Long[] ids, Long[] bookIds); } diff --git a/novel-admin/src/main/java/com/java2nb/books/service/impl/BookContentServiceImpl.java b/novel-admin/src/main/java/com/java2nb/books/service/impl/BookContentServiceImpl.java deleted file mode 100644 index e41891d..0000000 --- a/novel-admin/src/main/java/com/java2nb/books/service/impl/BookContentServiceImpl.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.java2nb.books.service.impl; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; - -import com.java2nb.books.dao.BookContentDao; -import com.java2nb.books.domain.BookContentDO; -import com.java2nb.books.service.BookContentService; - - - -@Service -public class BookContentServiceImpl implements BookContentService { - @Autowired - private BookContentDao bookContentDao; - - @Override - public BookContentDO get(Long id){ - return bookContentDao.get(id); - } - - @Override - public List list(Map map){ - return bookContentDao.list(map); - } - - @Override - public int count(Map map){ - return bookContentDao.count(map); - } - - @Override - public int save(BookContentDO bookContent){ - return bookContentDao.save(bookContent); - } - - @Override - public int update(BookContentDO bookContent){ - return bookContentDao.update(bookContent); - } - - @Override - public int remove(Long id){ - return bookContentDao.remove(id); - } - - @Override - public int batchRemove(Long[] ids){ - return bookContentDao.batchRemove(ids); - } - -} diff --git a/novel-admin/src/main/java/com/java2nb/books/service/impl/BookIndexServiceImpl.java b/novel-admin/src/main/java/com/java2nb/books/service/impl/BookIndexServiceImpl.java deleted file mode 100644 index 454d130..0000000 --- a/novel-admin/src/main/java/com/java2nb/books/service/impl/BookIndexServiceImpl.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.java2nb.books.service.impl; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; - -import com.java2nb.books.dao.BookIndexDao; -import com.java2nb.books.domain.BookIndexDO; -import com.java2nb.books.service.BookIndexService; - - - -@Service -public class BookIndexServiceImpl implements BookIndexService { - @Autowired - private BookIndexDao bookIndexDao; - - @Override - public BookIndexDO get(Long id){ - return bookIndexDao.get(id); - } - - @Override - public List list(Map map){ - return bookIndexDao.list(map); - } - - @Override - public int count(Map map){ - return bookIndexDao.count(map); - } - - @Override - public int save(BookIndexDO bookIndex){ - return bookIndexDao.save(bookIndex); - } - - @Override - public int update(BookIndexDO bookIndex){ - return bookIndexDao.update(bookIndex); - } - - @Override - public int remove(Long id){ - return bookIndexDao.remove(id); - } - - @Override - public int batchRemove(Long[] ids){ - return bookIndexDao.batchRemove(ids); - } - -} diff --git a/novel-admin/src/main/java/com/java2nb/books/service/impl/BookServiceImpl.java b/novel-admin/src/main/java/com/java2nb/books/service/impl/BookServiceImpl.java index a6500da..9aee630 100644 --- a/novel-admin/src/main/java/com/java2nb/books/service/impl/BookServiceImpl.java +++ b/novel-admin/src/main/java/com/java2nb/books/service/impl/BookServiceImpl.java @@ -12,7 +12,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Date; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -68,15 +67,26 @@ public class BookServiceImpl implements BookService { return bookDao.update(book); } - + + @Transactional @Override public int remove(Long id){ - return bookDao.remove(id); + int rows = bookDao.remove(id); + bookIndexDao.removeByBookIds(id+""); + bookContentDao.removeByBookIds(id+""); + return rows; } - + + @Transactional @Override public int batchRemove(Long[] ids){ - return bookDao.batchRemove(ids); + + int rows = bookDao.batchRemove(ids); + String bookIds = StringUtils.join(ids,","); + bookIndexDao.removeByBookIds(bookIds); + bookContentDao.removeByBookIds(bookIds); + return rows; + } @Override @@ -108,12 +118,16 @@ public class BookServiceImpl implements BookService { } @Override - public int indexRemove(Long id) { + @Transactional + public int indexRemove(Long id, Long bookId) { + bookContentDao.removeByBookIds(id+""); return bookIndexDao.remove(id); } + @Transactional @Override - public int batchIndexRemove(Long[] ids) { + public int batchIndexRemove(Long[] ids, Long[] bookIds) { + bookContentDao.removeByBookIds(StringUtils.join(ids,",")); return bookIndexDao.batchRemove(ids); } diff --git a/novel-admin/src/main/resources/application.yml b/novel-admin/src/main/resources/application.yml index f9b80d9..cd945a7 100644 --- a/novel-admin/src/main/resources/application.yml +++ b/novel-admin/src/main/resources/application.yml @@ -35,7 +35,7 @@ spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver - url: jdbc:mysql://127.0.0.1:3306/books_inner?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai + url: jdbc:mysql://127.0.0.1:3306/books?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: books password: books #password: diff --git a/novel-admin/src/main/resources/mybatis/books/BookContentMapper.xml b/novel-admin/src/main/resources/mybatis/books/BookContentMapper.xml index fd6232c..76d0682 100644 --- a/novel-admin/src/main/resources/mybatis/books/BookContentMapper.xml +++ b/novel-admin/src/main/resources/mybatis/books/BookContentMapper.xml @@ -94,4 +94,9 @@ + + + delete from book_content where book_id in (${bookIds}); + + \ No newline at end of file diff --git a/novel-admin/src/main/resources/mybatis/books/BookIndexMapper.xml b/novel-admin/src/main/resources/mybatis/books/BookIndexMapper.xml index dc7f968..9bd518a 100644 --- a/novel-admin/src/main/resources/mybatis/books/BookIndexMapper.xml +++ b/novel-admin/src/main/resources/mybatis/books/BookIndexMapper.xml @@ -130,4 +130,8 @@ select max(index_num) from book_index where book_id = #{bookId,jdbcType=VARCHAR} ; + + delete from book_index where book_id in (${bookIds}); + + \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/js/appjs/books/book/book.js b/novel-admin/src/main/resources/static/js/appjs/books/book/book.js index 99411a1..47bf835 100644 --- a/novel-admin/src/main/resources/static/js/appjs/books/book/book.js +++ b/novel-admin/src/main/resources/static/js/appjs/books/book/book.js @@ -125,7 +125,10 @@ function load() { var p = '章节发布 '; - return d + r + p; + var cm = '章节管理 '; + return d + r + p +cm; } }] }); @@ -157,6 +160,17 @@ function addIndex(bookId) { }); } +function manageIndex(bookId) { + layer.open({ + type: 2, + title: '章节管理', + maxmin: true, + shadeClose: false, // 点击遮罩关闭层 + area: ['800px', '520px'], + content: prefix + '/index?bookId='+bookId // iframe的url + }); +} + function detail(id) { layer.open({ type: 2, diff --git a/novel-admin/src/main/resources/static/js/appjs/books/bookIndex/bookIndex.js b/novel-admin/src/main/resources/static/js/appjs/books/bookIndex/bookIndex.js index 6a9ed53..fab5b4c 100644 --- a/novel-admin/src/main/resources/static/js/appjs/books/bookIndex/bookIndex.js +++ b/novel-admin/src/main/resources/static/js/appjs/books/bookIndex/bookIndex.js @@ -80,7 +80,7 @@ function load() { + '\')"> ';*/ var r = ' '; + + '\',\''+row.bookId+'\')"> '; return r; } }] @@ -124,7 +124,7 @@ function edit(id) { }); } -function remove(id) { +function remove(id,bookId) { layer.confirm('确定要删除选中的记录?', { btn: ['确定', '取消'] }, function () { @@ -132,7 +132,8 @@ function remove(id) { url: prefix + "/remove", type: "post", data: { - 'id': id + 'id': id, + 'bookId':bookId }, success: function (r) { if (r.code == 0) { @@ -159,15 +160,22 @@ function batchRemove() { btn: ['确定', '取消'] // 按钮 }, function () { + debugger var ids = new Array(); // 遍历所有选择的行数据,取每条数据对应的ID $.each(rows, function (i, row) { ids[i] = row['id']; }); + var bookIds = new Array(); + // 遍历所有选择的行数据,取每条数据对应的ID + $.each(rows, function (i, row) { + bookIds[i] = row['bookId']; + }); $.ajax({ type: 'POST', data: { - "ids": ids + "ids": ids, + "bookIds":bookIds }, url: prefix + '/batchRemove', success: function (r) { diff --git a/novel-admin/src/main/resources/static/wangEditor/.eslintignore b/novel-admin/src/main/resources/static/wangEditor/.eslintignore deleted file mode 100644 index c02d109..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -src/js/util/ierange.js -src/js/util/poly-fill.js \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/.eslintrc.json b/novel-admin/src/main/resources/static/wangEditor/.eslintrc.json deleted file mode 100644 index 0148b38..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/.eslintrc.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "env": { - "browser": true, - "commonjs": true, - "es6": true - }, - "globals": { - "ENV": true - }, - "extends": "eslint:recommended", - "parserOptions": { - "sourceType": "module" - }, - "rules": { - "no-console":0, - "indent": [ - "error", - 4 - ], - "linebreak-style": [ - "error", - "unix" - ], - "quotes": [ - "error", - "single", - { - "allowTemplateLiterals": true - } - ], - "semi": [ - "error", - "never" - ], - "no-unused-vars": 0, - "no-debugger": 0 - } -} \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/.gitattributes b/novel-admin/src/main/resources/static/wangEditor/.gitattributes deleted file mode 100644 index 412eeda..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/.gitattributes +++ /dev/null @@ -1,22 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto - -# Custom for Visual Studio -*.cs diff=csharp -*.sln merge=union -*.csproj merge=union -*.vbproj merge=union -*.fsproj merge=union -*.dbproj merge=union - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain diff --git a/novel-admin/src/main/resources/static/wangEditor/.gitignore b/novel-admin/src/main/resources/static/wangEditor/.gitignore deleted file mode 100644 index 481571c..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/.gitignore +++ /dev/null @@ -1,51 +0,0 @@ - -#忽略 -**/node_modules/* -node_modules/* -npm-debug.log -example/upload-files - -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# ========================= -# Operating System Files -# ========================= - -# OSX -# ========================= - -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - - -# Thumbnails -._* - -# Files that might appear on external disk -.Spotlight-V100 -.Trashes - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk diff --git a/novel-admin/src/main/resources/static/wangEditor/.npmignore b/novel-admin/src/main/resources/static/wangEditor/.npmignore deleted file mode 100644 index 333dd25..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/.npmignore +++ /dev/null @@ -1,5 +0,0 @@ -node_modules/* -npm-debug.log -docs/* -src/* -example/* \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/ISSUE.md b/novel-admin/src/main/resources/static/wangEditor/ISSUE.md deleted file mode 100644 index 796cbee..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/ISSUE.md +++ /dev/null @@ -1,157 +0,0 @@ -# 问题记录 - -## 版本修复 - -### v3.0.1 - -- [done] 如何设置自动增加高度(补充文档) -- [done] src/js/editor/Bar 改为 Progress,仅供上传图片使用 -- [done] Panel 在右上角增加一个“关闭”按钮 -- [done] 显示页面 table、quote、code 等样式,说明一下 -- [done] 增加自定义上传回调函数,用以自定义返回图片的格式 -- [done] 上传附带的参数,也加入到 form-data 中一份 -- [done] 编辑器默认情况下,菜单栏不能点击,必须focus了编辑器求之后才能点击 -- [done] 点击菜单弹出panel之后,再点击编辑器区域其他地方,panel不消失 -- [done] 自定义filename,v2版本就有 -- [done] ff 中的 bug -- [done] ff 中粘贴图片和文字出现问题 https://github.com/wangfupeng1988/wangEditor/issues/609 -- [done] 火狐浏览器下,创建表格,编辑表格内容时,会出现两个控制点(有人提供了解决方案) -- [done] 配置最多上传的文件个数 -- [done] 连续给两段内容 添加有/无序列表时,样式会出问题,且其他内容找不到了,并且编辑器不处于编辑状态。 -- [done] onchange -- [done] IE11下面一直报错。并且表格无法正常使用 - -### v3.0.2 - -- [done] 用 onchange 完善 vue react 的 demo -- [done] 插入图片之后,光标移动到图片的前面,然后回车,图片消失,并且不能撤销 -- [done] 修复上传图片 customInsert 无效的bug -- [done] 编辑区域 z-index 可配置 -- [done] 上传图片不应该把状态码限制在 200,而是 2xx -- [done] editor.txt.html() 之后,没有定位光标位置 - -### v3.0.3 - -- [done] 粘贴图片在低版本的谷歌浏览器中无法使用,提示验证图片未通过,undefined不是图片。 -- [done] 动态赋值内容,会自动换行,因为给自动加了`


` -- [done] 不选中任何内容,点击“加粗”报错:Failed to execute 'setEnd' on 'Range' -- [done] toolbar 小图标的 z-index 可配置 - -### v3.0.4 - -- [done] 允许使用者通过`replace`实现多语言 -- [done] `_alert()`,可自定义配置提示框 -- [done] 支持用户自定义上传图片的事件,如用户要上传到七牛云、阿里云 - -### v3.0.5 - -- [done] 图片上传中,insertLinkImg 方法中,去掉 img.onload 之后再插入的逻辑吧,这样会打乱多个图片的顺序 -- [done] `` 标签重叠问题,两行文字都是`h2`,然后将第一行选中设置为`h1`,结果是 `

测试1

测试2` -- [done] 补充 ng 集成的示例 https://github.com/wangfupeng1988/wangEditor/issues/859 -- [done] 菜单不能折叠的说明,加入到文档中 -- [done] 上传图片 before 函数中,增加一个判断,可以让用户终止图片的上传 - -### v3.0.6 - -- [done] src/fonts 中的字体文件名改一下,用 icomoon 容易发生冲突 -- [done] 将禁用编辑器的操作完善到文档中 https://www.kancloud.cn/wangfupeng/wangeditor3/368562 -- [done] 开放表格中的粘贴功能(之前因不明问题而封闭) -- [done] 代码块中,光标定位到最后位置时,连续两次回车要跳出代码块 - -### v3.0.7 - -- [done] 紧急修复上一个版本导致的菜单图标不显示的 bug - -### v3.0.8 - -- [done] 修复 backColor 和 foreColor 代码文件名混淆的问题 -- [done] 修改 IE 中 “引用” 的功能 -- [done] 增加粘贴过滤样式的可配置 -- [done] 修复 IE 粘贴文字的问题 - -### v3.0.9 - -- [done] config 中,上传图片的 token 注视掉 -- [done] 将一些常见 API 开放,写到文档中 https://www.kancloud.cn/wangfupeng/wangeditor3/404586 -- [done] IE 火狐 插入多行代码有问题 -- [done] 粘贴时,在`

`中,不能只粘贴纯文本,还得要图片 -- [done] 粘贴内容中,过滤掉``注释 -- [done] **支持上传七牛云存储** - -### v3.0.10 - -- [done] 支持插入网络图片的回调函数 -- [done] 插入链接时候的格式校验 -- [done] 支持拖拽上传 - -### v3.0.11 - -- [done] 如何用 textarea 创建编辑器,完善到文档中,许多人提问 -- [done] 修复`editor.customConfig.customUploadImg`不触发的 bug -- [done] 修复有序列表和无序列表切换时 onchange 不触发的 bug - -### v3.0.12 - -- [done] 增加 onfocus 和 onblur (感谢 [hold-baby](https://github.com/hold-baby) 提交的 [PR](https://github.com/wangfupeng1988/wangEditor/pull/1076)) -- [done] 上传的自定义参数`editor.customConfig.uploadImgParams`是否拼接到 url 中,支持可配置 -- [done] onchange 触发的延迟时间,支持可配置 - -### v3.0.13 - -- [done] 修复图片 选中/取消选中 时,触发 onchange 的问题 -- [done] 修复只通过 length 判断 onchange 是否触发的问题 -- [done] 增加插入网络图片的校验函数 -- [done] 增加自定义处理粘贴文本的事件 -- [done] 修复选中一个图片时点击删除键会误删除其他内容的 bug -- [done] 修复 window chrome 中“复制图片”然后粘贴图片,会粘贴为两张的 bug -- [done] 修复无法撤销“引用”的问题 - -### v3.0.14 - -- [done] 可以配置前景色、背景色 -- [done] 回车时无法从`

....

`中跳出 -- [done] 增加获取 JSON 格式内容的 API - -### v3.0.15 - -- [done] 表情兼容图片和 emoji ,都可自定义配置 - -### v3.0.16 - -- [done] 修复粘贴图片的 bug -- [done] 修复`pasteTextHandle`执行两次的问题 -- [done] 修复插入链接时,文字和链接为空时,`linkCheck`不执行的 bug -- [done] 粘贴 html 时,过滤掉其中的`data-xxx`属性 -- [done] 修复中文输入法输入过程中出发 onchange 的问题,感谢 [github.com/CongAn](https://github.com/CongAn) PR -- [done] `editor.txt.html`和`editor.txt.text`中,替换`​`字符为空字符串 -- [done] 精确图片大小计算,将`maxSize / 1000 / 1000`改为`maxSize / 1024 / 1024` -- [done] 修复 droplist 类型菜单(颜色、背景色等)点击不准确的问题 - -### v3.0.17 - -- [done] 合并 pr [菜单和编辑区域分离 onfocus onblur 失效bug](https://github.com/wangfupeng1988/wangEditor/pull/1174) ,感谢 [hold-baby](https://github.com/hold-baby) 提供 pr -- [done] 使用`document.execCommand("styleWithCSS", null, true)`,这样设置字体颜色就会用 css 而不是用`` - - -### 近期计划解决 - -- 撤销的兼容性问题(会误伤其他编辑器或者 input textarea 等),考虑用 onchange 记录 undo 和 redo 的内容(但是得考虑直接修改 dom 的情况,如 quote code img list table 菜单) - - 列表撤销会删除一行?https://github.com/wangfupeng1988/wangEditor/issues/1131 - - 页面中有 input 等输入标签时,undo redo 会误伤 https://github.com/wangfupeng1988/wangEditor/issues/1024 - - 两个编辑器 undo 的问题 https://github.com/wangfupeng1988/wangEditor/issues/1010 - - list undo redo 有问题。选中几行,先设置有序列表,再设置无序列表,然后撤销,就能复现问题 -- 粘贴文字的样式问题(可暂时配置 `pasteTextHandle` 自行处理) - - 先输入文字,再粘贴 excel 表格,样式丢失 https://github.com/wangfupeng1988/wangEditor/issues/1000 - - IE 11 直接输入文字会空一行在第二行出现内容 https://github.com/wangfupeng1988/wangEditor/issues/919 - - windows 下 word excel 的粘贴,存在垃圾数据 - -## 待排期 - -- 调研 safari、IE 和ff中粘贴图片 https://github.com/wangfupeng1988/wangEditor/issues/831 -- 图片调整大小,表格调整的方式,是否用 toolbar 的方式? -- 删除掉`./release`之后,执行`npm run release`会报错,原因是`fonts`文件没拷贝全,就要去替换`css`中的字体文件为`base64`格式,导致找不到文件。 -- 先点击'B'再输入内容这种形式,前期先支持 webkit 和 IE,火狐的支持后面再加上 -- 图片压缩 canvas https://github.com/think2011/localResizeIMG -- github 徽章 https://github.com/EyreFree/GitHubBadgeIntroduction -- 将代码在进行拆分,做到“每个程序只做一件事”,不要出现过长的代码文件。例如 `src/js/command/index.js` 和 `src/js/selection/index.js` - diff --git a/novel-admin/src/main/resources/static/wangEditor/LICENSE b/novel-admin/src/main/resources/static/wangEditor/LICENSE deleted file mode 100644 index 5239660..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2017 王福朋 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/novel-admin/src/main/resources/static/wangEditor/README.md b/novel-admin/src/main/resources/static/wangEditor/README.md deleted file mode 100644 index 0ab9445..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/README.md +++ /dev/null @@ -1,70 +0,0 @@ - -# wangEditor - -## 介绍 - -**wangEditor** —— 轻量级 web 富文本编辑器,配置方便,使用简单。支持 IE10+ 浏览器。 - -- 官网:[www.wangEditor.com](http://www.wangeditor.com/) -- 文档:[www.kancloud.cn/wangfupeng/wangeditor3/332599](http://www.kancloud.cn/wangfupeng/wangeditor3/332599) -- 源码:[github.com/wangfupeng1988/wangEditor](https://github.com/wangfupeng1988/wangEditor) (欢迎 star) - -![图片](http://images2015.cnblogs.com/blog/138012/201705/138012-20170530202905633-1840158981.png) - -*查看 v2 版本的代码和文档点击[这里](https://github.com/wangfupeng1988/wangEditor/tree/v2)* - - -## 下载 - -- 直接下载:[https://github.com/wangfupeng1988/wangEditor/releases](https://github.com/wangfupeng1988/wangEditor/releases) -- 使用`npm`下载:`npm install wangeditor` (注意 `wangeditor` 全部是**小写字母**) -- 使用`bower`下载:`bower install wangEditor` (前提保证电脑已安装了`bower`) -- 使用CDN:[//unpkg.com/wangeditor/release/wangEditor.min.js](https://unpkg.com/wangeditor/release/wangEditor.min.js) - - -## 使用 - -```javascript -var E = window.wangEditor -var editor = new E('#div1') -editor.create() -``` - - -## 运行 demo - -- 下载源码 `git clone git@github.com:wangfupeng1988/wangEditor.git` -- 安装或者升级最新版本 node(最低`v6.x.x`) -- 进入目录,安装依赖包 `cd wangEditor && npm i` -- 安装包完成之后,windows 用户运行`npm run win-example`,Mac 用户运行`npm run example` -- 打开浏览器访问[localhost:3000/index.html](http://localhost:3000/index.html) -- 用于 React、vue 或者 angular 可查阅[文档](http://www.kancloud.cn/wangfupeng/wangeditor3/332599)中[其他](https://www.kancloud.cn/wangfupeng/wangeditor3/335783)章节中的相关介绍 - -## 交流 - -### QQ 群 - -以下 QQ 群欢迎加入交流问题(可能有些群已经满员) - -- 164999061 -- 281268320 - -### 提问 - -注意,作者只受理以下几种提问方式,其他方式直接忽略 - -- 直接在 [github issues](https://github.com/wangfupeng1988/wangEditor/issues) 提交问题 -- 去[知乎](https://www.zhihu.com/)提问,并邀请[作者](https://www.zhihu.com/people/wang-fu-peng-54/activities)来回答 -- 去[segmentfault](https://segmentfault.com)提问,并邀请[作者](https://segmentfault.com/u/wangfupeng1988)来回答 - -每次升级版本修复的问题记录在[这里](./ISSUE.md) - -## 关于作者 - -- 关注作者的博客 - 《[深入理解javascript原型和闭包系列](http://www.cnblogs.com/wangfupeng1988/p/4001284.html)》《[深入理解javascript异步系列](https://github.com/wangfupeng1988/js-async-tutorial)》《[CSS知多少](http://www.cnblogs.com/wangfupeng1988/p/4325007.html)》 -- 学习作者的教程 - 《[前端JS基础面试题](http://coding.imooc.com/class/115.html)》《[React.js模拟大众点评webapp](http://coding.imooc.com/class/99.html)》《[zepto设计与源码分析](http://www.imooc.com/learn/745)》《[用grunt搭建自动化的web前端开发环境](http://study.163.com/course/courseMain.htm?courseId=1103003)》《[json2.js源码解读](http://study.163.com/course/courseMain.htm?courseId=691008)》 - -如果你感觉有收获,欢迎给我打赏 ———— 以激励我更多输出优质开源内容 - -![图片](https://camo.githubusercontent.com/e1558b631931e0a1606c769a61f48770cc0ccb56/687474703a2f2f696d61676573323031352e636e626c6f67732e636f6d2f626c6f672f3133383031322f3230313730322f3133383031322d32303137303232383131323233373739382d313530373139363634332e706e67) - diff --git a/novel-admin/src/main/resources/static/wangEditor/bower.json b/novel-admin/src/main/resources/static/wangEditor/bower.json deleted file mode 100644 index 0c4ed0d..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/bower.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "wangEditor", - "description": "wangEditor - 基于javascript和css开发的 web 富文本编辑器, 轻量、简洁、易用、开源免费", - "main": "release/wangEditor.js", - "authors": [ - "wangfupeng " - ], - "license": "MIT", - "keywords": [ - "wangEditor", - "web 富文本编辑器" - ], - "homepage": "https://github.com/wangfupeng1988/wangEditor", - "moduleType": [ - "amd", - "cmd", - "node" - ], - "private": true -} diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/dev/README.md b/novel-admin/src/main/resources/static/wangEditor/docs/dev/README.md deleted file mode 100644 index 473dbcb..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/dev/README.md +++ /dev/null @@ -1,25 +0,0 @@ -面向开发者的文档 - - -框架介绍 - -- 下载和运行 -- 目录结构介绍 -- `example`目录 -- `src`目录(`js`目录,`less`目录) -- `package.json` -- `gulpfile.js` - -如何提交 PR - - - -上线 - -- 修改`package.json`版本 -- 提交到github,并创建tag -- 提交到 npm -- 更新 .md 文档 -- 文档同步到 kancloud -- …… - diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/01-demo.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/01-demo.md deleted file mode 100644 index b71612f..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/01-demo.md +++ /dev/null @@ -1,41 +0,0 @@ -# 简单的 demo - -## 下载 - -- 点击 [https://github.com/wangfupeng1988/wangEditor/releases](https://github.com/wangfupeng1988/wangEditor/releases) 下载最新版。进入`release`文件夹下找到`wangEditor.js`或者`wangEditor.min.js`即可 -- 使用CDN:[//unpkg.com/wangeditor/release/wangEditor.min.js](https://unpkg.com/wangeditor/release/wangEditor.min.js) -- 使用`bower`下载:`bower install wangEditor` (前提保证电脑已安装了`bower`) - -*PS:支持`npm`安装,请参见后面的章节* - -## 制作 demo - -编辑器效果如下。 - -![图片](https://camo.githubusercontent.com/f3d072718d8fcbbacf8cc80465a34cceffcf5b4a/687474703a2f2f696d61676573323031352e636e626c6f67732e636f6d2f626c6f672f3133383031322f3230313730352f3133383031322d32303137303533303230323930353633332d313834303135383938312e706e67) - -代码示例如下。**注意,以下代码中无需引用任何 CSS 文件!!!** - -```html - - - - - wangEditor demo - - -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - - - - -``` diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/02-use-module.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/02-use-module.md deleted file mode 100644 index 0356a68..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/02-use-module.md +++ /dev/null @@ -1,49 +0,0 @@ -# 使用模块定义 - -wangEditor 除了直接使用` - - -``` - -## CommonJS - -可以使用`npm install wangeditor`安装(注意,这里`wangeditor`全是**小写字母**) - -```javascript -// 引用 -var E = require('wangeditor') // 使用 npm 安装 -var E = require('/wangEditor.min.js') // 使用下载的源码 - -// 创建编辑器 -var editor = new E('#editor') -editor.create() -``` diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/03-sperate.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/03-sperate.md deleted file mode 100644 index 0fcd276..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/03-sperate.md +++ /dev/null @@ -1,48 +0,0 @@ -# 菜单和编辑区域分离 - -如果你想要像 知乎专栏、简书、石墨、网易云笔记 这些编辑页面一样,将编辑区域和菜单分离,也可以实现。 - -这样,菜单和编辑器区域就是使用者可自己控制的元素,可自定义样式。例如:将菜单`fixed`、编辑器区域高度自动增加等 - -## 代码示例 - -```html - - - - - wangEditor 菜单和编辑器区域分离 - - - -
-
-
中间隔离带
-
-

请输入内容

-
- - - - - -``` - -## 显示效果 - -从上面代码可以看出,菜单和编辑区域其实就是两个单独的`
`,位置、尺寸都可以随便定义。 - -![](http://images2015.cnblogs.com/blog/138012/201705/138012-20170531224756289-7442240.png) - diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/04-multi.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/04-multi.md deleted file mode 100644 index aee3540..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/01-getstart/04-multi.md +++ /dev/null @@ -1,50 +0,0 @@ -# 同一个页面创建多个编辑器 - -wangEditor 支持一个页面创建多个编辑器 - -## 代码示例 - -```html - - - - - wangEditor 一个页面多个编辑器 - - - -
-
-
中间隔离带
-
-

第一个 demo(菜单和编辑器区域分开)

-
- -
-

第二个 demo(常规)

-
- - - - - - -``` - diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/01-set-content.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/01-set-content.md deleted file mode 100644 index 7631f6f..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/01-set-content.md +++ /dev/null @@ -1,46 +0,0 @@ -# 设置内容 - -以下方式中,如果条件允许,尽量使用第一种方式,效率最高。 - -## html 初始化内容 - -直接将内容写到要创建编辑器的`
`标签中 - -```html -
-

初始化的内容

-

初始化的内容

-
- - - -``` - -## js 设置内容 - -创建编辑器之后,使用`editor.txt.html(...)`设置编辑器内容 - -```html -
-
- - - -``` - -## 追加内容 - -创建编辑器之后,可使用`editor.txt.append('

追加的内容

')`继续追加内容。 - -## 清空内容 - -可使用`editor.txt.clear()`清空编辑器内容 diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/02-get-content.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/02-get-content.md deleted file mode 100644 index e21c277..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/02-get-content.md +++ /dev/null @@ -1,80 +0,0 @@ -# 读取内容 - -可以`html`和`text`的方式读取编辑器的内容。 - -```html -
-

欢迎使用 wangEditor 编辑器

-
- - - - - -``` - -需要注意的是:**从编辑器中获取的 html 代码是不包含任何样式的纯 html**,如果显示的时候需要对其中的`` `` `
`等标签进行自定义样式(这样既可实现多皮肤功能),下面提供了编辑器中使用的样式供参考 - -```css -/* table 样式 */ -table { - border-top: 1px solid #ccc; - border-left: 1px solid #ccc; -} -table td, -table th { - border-bottom: 1px solid #ccc; - border-right: 1px solid #ccc; - padding: 3px 5px; -} -table th { - border-bottom: 2px solid #ccc; - text-align: center; -} - -/* blockquote 样式 */ -blockquote { - display: block; - border-left: 8px solid #d0e5f2; - padding: 5px 10px; - margin: 10px 0; - line-height: 1.4; - font-size: 100%; - background-color: #f1f1f1; -} - -/* code 样式 */ -code { - display: inline-block; - *display: inline; - *zoom: 1; - background-color: #f1f1f1; - border-radius: 3px; - padding: 3px 5px; - margin: 0 3px; -} -pre code { - display: block; -} - -/* ul ol 样式 */ -ul, ol { - margin: 10px 0 10px 20px; -} -``` - diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/03-use-textarea.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/03-use-textarea.md deleted file mode 100644 index 1707e13..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/03-use-textarea.md +++ /dev/null @@ -1,25 +0,0 @@ -# 使用 textarea - -wangEditor 从`v3`版本开始不支持 textarea ,但是可以通过`onchange`来实现 textarea 中提交富文本内容。 - -```html -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - - - -``` \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/04-get-json.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/04-get-json.md deleted file mode 100644 index d623ac4..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/02-content/04-get-json.md +++ /dev/null @@ -1,82 +0,0 @@ -# 获取 JSON 格式的内容 - -可以通过`editor.txt.getJSON`获取 JSON 格式的编辑器的内容,`v3.0.14`开始支持,示例如下 - -```html -
-

欢迎使用 wangEditor 富文本编辑器

- -
- - - - -``` - - ------ - -如果编辑器区域的 html 内容是如下: - -```html -

欢迎使用 wangEditor 富文本编辑器

- -``` - -那么获取的 JSON 格式就如下: - -```json -[ - { - "tag": "p", - "attrs": [], - "children": [ - "欢迎使用 ", - { - "tag": "b", - "attrs": [], - "children": [ - "wangEditor" - ] - }, - " 富文本编辑器" - ] - }, - { - "tag": "img", - "attrs": [ - { - "name": "src", - "value": "https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo_top_ca79a146.png" - }, - { - "name": "style", - "value": "max-width:100%;" - } - ], - "children": [] - }, - { - "tag": "p", - "attrs": [], - "children": [ - { - "tag": "br", - "attrs": [], - "children": [] - } - ] - } -] -``` \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/01-menu.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/01-menu.md deleted file mode 100644 index bce6ba7..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/01-menu.md +++ /dev/null @@ -1,52 +0,0 @@ -# 自定义菜单 - -编辑器创建之前,可使用`editor.customConfig.menus`定义显示哪些菜单和菜单的顺序。**注意:v3 版本的菜单不支持换行折叠了(因为换行之后菜单栏是在太难看),如果菜单栏宽度不够,建议精简菜单项。** - -## 代码示例 - -```html -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - -``` - -## 默认菜单 - -编辑默认的菜单配置如下 - -```javascript -[ - 'head', // 标题 - 'bold', // 粗体 - 'italic', // 斜体 - 'underline', // 下划线 - 'strikeThrough', // 删除线 - 'foreColor', // 文字颜色 - 'backColor', // 背景颜色 - 'link', // 插入链接 - 'list', // 列表 - 'justify', // 对齐方式 - 'quote', // 引用 - 'emoticon', // 表情 - 'image', // 插入图片 - 'table', // 表格 - 'video', // 插入视频 - 'code', // 插入代码 - 'undo', // 撤销 - 'redo' // 重复 -] -``` diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/02-debug.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/02-debug.md deleted file mode 100644 index e94d7a4..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/02-debug.md +++ /dev/null @@ -1,21 +0,0 @@ -# 定义 debug 模式 - -可通过`editor.customConfig.debug = true`配置`debug`模式,`debug`模式下,有 JS 错误会以`throw Error`方式提示出来。默认值为`false`,即不会抛出异常。 - -但是,在实际开发中不建议直接定义为`true`或者`false`,可通过 url 参数进行干预,示例如下: - -```html -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - -``` - diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/03-onchange.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/03-onchange.md deleted file mode 100644 index 296091c..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/03-onchange.md +++ /dev/null @@ -1,40 +0,0 @@ -# 配置 onchange 函数 - -配置`onchange`函数之后,用户操作(鼠标点击、键盘打字等)导致的内容变化之后,会自动触发`onchange`函数执行。 - -但是,**用户自己使用 JS 修改了`div1`的`innerHTML`,不会自动触发`onchange`函数**,此时你可以通过执行`editor.change()`来手动触发`onchange`函数的执行。 - -```html -
-

欢迎使用 wangEditor 富文本编辑器

-
- -

手动触发 onchange 函数执行

- - - - -``` - ------ - -另外,如果需要修改 onchange 触发的延迟时间(onchange 会在用户无任何操作的 xxx 毫秒之后被触发),可通过如下配置 - -```js -// 自定义 onchange 触发的延迟时间,默认为 200 ms -editor.customConfig.onchangeTimeout = 1000 // 单位 ms -``` diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/04-z-index.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/04-z-index.md deleted file mode 100644 index 129bf1c..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/04-z-index.md +++ /dev/null @@ -1,19 +0,0 @@ -# 配置编辑区域的 z-index - -编辑区域的`z-index`默认为`10000`,可自定义修改,代码配置如下。需改之后,编辑区域和菜单的`z-index`会同时生效。 - -```html -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - -``` - - diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/05-lang.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/05-lang.md deleted file mode 100644 index 01900fe..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/05-lang.md +++ /dev/null @@ -1,30 +0,0 @@ -# 多语言 - -可以通过`lang`配置项配置多语言,其实就是通过该配置项中的配置,将编辑器显示的文字,替换成你需要的文字。 - -```html -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - -``` - -**注意,以上代码中的`链接文字`要写在`链接`前面,`上传图片`要写在`上传`前面,因为前者包含后者。如果不这样做,可能会出现替换不全的问题,切记切记!** diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/06-paste.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/06-paste.md deleted file mode 100644 index a7126c8..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/06-paste.md +++ /dev/null @@ -1,33 +0,0 @@ -# 粘贴文本 - -**注意,以下配置暂时对 IE 无效。IE 暂时使用系统自带的粘贴功能,没有样式过滤!** - -## 关闭粘贴样式的过滤 - -当从其他网页复制文本内容粘贴到编辑器中,编辑器会默认过滤掉复制文本中自带的样式,目的是让粘贴后的文本变得更加简洁和轻量。用户可通过`editor.customConfig.pasteFilterStyle = false`手动关闭掉粘贴样式的过滤。 - -## 自定义处理粘贴的文本内容 - -使用者可通过`editor.customConfig.pasteTextHandle`对粘贴的文本内容进行自定义的过滤、处理等操作,然后返回处理之后的文本内容。编辑器最终会粘贴用户处理之后并且返回的的内容。 - -## 示例代码 - -```html -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - -``` \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/07-linkImgCallback.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/07-linkImgCallback.md deleted file mode 100644 index 52169e8..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/07-linkImgCallback.md +++ /dev/null @@ -1,12 +0,0 @@ -# 插入网络图片的回调 - -插入网络图片时,可通过如下配置获取到图片的信息。`v3.0.10`开始支持。 - -```js -var E = window.wangEditor -var editor = new E('#div1') -editor.customConfig.linkImgCallback = function (url) { - console.log(url) // url 即插入图片的地址 -} -editor.create() -``` diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/08-linkCheck.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/08-linkCheck.md deleted file mode 100644 index b581438..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/08-linkCheck.md +++ /dev/null @@ -1,16 +0,0 @@ -# 插入链接的校验 - -插入链接时,可通过如下配置对文字和链接进行校验。`v3.0.10`开始支持。 - -```js -var E = window.wangEditor -var editor = new E('#div1') -editor.customConfig.linkCheck = function (text, link) { - console.log(text) // 插入的文字 - console.log(link) // 插入的链接 - - return true // 返回 true 表示校验成功 - // return '验证失败' // 返回字符串,即校验失败的提示信息 -} -editor.create() -``` \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/09-onfocus.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/09-onfocus.md deleted file mode 100644 index 7caba6b..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/09-onfocus.md +++ /dev/null @@ -1,19 +0,0 @@ -# 配置 onfocus 函数 - -配置`onfocus`函数之后,用户点击富文本区域会触发`onfocus`函数执行。 - -```html -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - -``` diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/10-onblur.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/10-onblur.md deleted file mode 100644 index f7544bc..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/10-onblur.md +++ /dev/null @@ -1,20 +0,0 @@ -# 配置 onblur 函数 - -配置`onblur`函数之后,如果当前有手动获取焦点的富文本并且鼠标点击富文本以外的区域,则会触发`onblur`函数执行。 - -```html -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - -``` diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/11-linkImgCheck.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/11-linkImgCheck.md deleted file mode 100644 index efb3320..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/11-linkImgCheck.md +++ /dev/null @@ -1,15 +0,0 @@ -# 插入网络图片的校验 - -插入网络图片时,可对图片地址做自定义校验。`v3.0.13`开始支持。 - -```js -var E = window.wangEditor -var editor = new E('#div1') -editor.customConfig.linkImgCheck = function (src) { - console.log(src) // 图片的链接 - - return true // 返回 true 表示校验成功 - // return '验证失败' // 返回字符串,即校验失败的提示信息 -} -editor.create() -``` \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/12-colors.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/12-colors.md deleted file mode 100644 index e86e57d..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/12-colors.md +++ /dev/null @@ -1,29 +0,0 @@ -# 配置字体颜色、背景色 - -编辑器的字体颜色和背景色,可以通过`editor.customConfig.colors`自定义配置 - -```html -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - -``` \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/13-emot.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/13-emot.md deleted file mode 100644 index 5363834..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/03-config/13-emot.md +++ /dev/null @@ -1,48 +0,0 @@ -# 配置表情 - -`v3.0.15`开始支持配置表情,支持图片格式和 emoji ,可通过`editor.customConfig.emotions`配置。**注意看代码示例中的注释:** - -```html -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - -``` - -温馨提示:需要表情图片可以去 https://api.weibo.com/2/emotions.json?source=1362404091 和 http://yuncode.net/code/c_524ba520e58ce30 逛一逛,或者自己搜索。 diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/01-show-tab.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/01-show-tab.md deleted file mode 100644 index 8261950..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/01-show-tab.md +++ /dev/null @@ -1,52 +0,0 @@ -# 隐藏/显示 tab - -## 显示“上传图片”tab - -默认情况下,编辑器不会显示“上传图片”的tab,因为你还没有配置上传图片的信息。 - -![](http://images2015.cnblogs.com/blog/138012/201706/138012-20170601204308039-691571074.png) - -参考一下示例显示“上传图片”tab - -```html -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - -``` - -显示效果 - -![](http://images2015.cnblogs.com/blog/138012/201706/138012-20170601204504524-830243744.png) - -## 隐藏“网络图片”tab - -默认情况下,“网络图片”tab是一直存在的。如果不需要,可以参考一下示例来隐藏它。 - -```html -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - -``` diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/02-base64.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/02-base64.md deleted file mode 100644 index 3a2d71a..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/02-base64.md +++ /dev/null @@ -1,23 +0,0 @@ -# 使用 base64 保存图片 - -如果需要使用 base64 编码直接将图片插入到内容中,可参考一下示例配置 - -```html -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - -``` - -示例效果如下 - -![](http://images2015.cnblogs.com/blog/138012/201706/138012-20170601204759258-1412289899.png) - - diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/03-upload-config.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/03-upload-config.md deleted file mode 100644 index 6720ce6..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/03-upload-config.md +++ /dev/null @@ -1,188 +0,0 @@ -# 上传图片 & 配置 - -将图片上传到服务器上的配置方式 - -## 上传图片 - -参考如下代码 - -```html -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - -``` - -其中`/upload`是上传图片的服务器端接口,接口返回的**数据格式**如下(**实际返回数据时,不要加任何注释!!!**) - -```json -{ - // errno 即错误代码,0 表示没有错误。 - // 如果有错误,errno != 0,可通过下文中的监听函数 fail 拿到该错误码进行自定义处理 - "errno": 0, - - // data 是一个数组,返回若干图片的线上地址 - "data": [ - "图片1地址", - "图片2地址", - "……" - ] -} -``` - -## 限制图片大小 - -默认限制图片大小是 5M - -```javascript -// 将图片大小限制为 3M -editor.customConfig.uploadImgMaxSize = 3 * 1024 * 1024 -``` - -## 限制一次最多能传几张图片 - -默认为 10000 张(即不限制),需要限制可自己配置 - -```javascript -// 限制一次最多上传 5 张图片 -editor.customConfig.uploadImgMaxLength = 5 -``` - -## 自定义上传参数 - -上传图片时可自定义传递一些参数,例如传递验证的`token`等。参数会被添加到`formdata`中。 - -```javascript -editor.customConfig.uploadImgParams = { - token: 'abcdef12345' // 属性值会自动进行 encode ,此处无需 encode -} -``` - -如果**还需要**将参数拼接到 url 中,可再加上如下配置 - -``` -editor.customConfig.uploadImgParamsWithUrl = true -``` - -## 自定义 fileName - -上传图片时,可自定义`filename`,即在使用`formdata.append(name, file)`添加图片文件时,自定义第一个参数。 - -```javascript -editor.customConfig.uploadFileName = 'yourFileName' -``` - -## 自定义 header - -上传图片时刻自定义设置 header - -```javascript -editor.customConfig.uploadImgHeaders = { - 'Accept': 'text/x-json' -} -``` - -## withCredentials(跨域传递 cookie) - -跨域上传中如果需要传递 cookie 需设置 withCredentials - -```javascript -editor.customConfig.withCredentials = true -``` - -## 自定义 timeout 时间 - -默认的 timeout 时间是 10 秒钟 - -```javascript -// 将 timeout 时间改为 3s -editor.customConfig.uploadImgTimeout = 3000 -``` - -## 监听函数 - -可使用监听函数在上传图片的不同阶段做相应处理 - -```javascript -editor.customConfig.uploadImgHooks = { - before: function (xhr, editor, files) { - // 图片上传之前触发 - // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,files 是选择的图片文件 - - // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传 - // return { - // prevent: true, - // msg: '放弃上传' - // } - }, - success: function (xhr, editor, result) { - // 图片上传并返回结果,图片插入成功之后触发 - // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果 - }, - fail: function (xhr, editor, result) { - // 图片上传并返回结果,但图片插入错误时触发 - // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果 - }, - error: function (xhr, editor) { - // 图片上传出错时触发 - // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象 - }, - timeout: function (xhr, editor) { - // 图片上传超时时触发 - // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象 - }, - - // 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置 - // (但是,服务器端返回的必须是一个 JSON 格式字符串!!!否则会报错) - customInsert: function (insertImg, result, editor) { - // 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!) - // insertImg 是插入图片的函数,editor 是编辑器对象,result 是服务器端返回的结果 - - // 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片: - var url = result.url - insertImg(url) - - // result 必须是一个 JSON 格式字符串!!!否则报错 - } -} -``` - -## 自定义提示方法 - -上传图片的错误提示默认使用`alert`弹出,你也可以自定义用户体验更好的提示方式 - -```javascript -editor.customConfig.customAlert = function (info) { - // info 是需要提示的内容 - alert('自定义提示:' + info) -} -``` - -## 自定义上传图片事件 - -如果想完全自己控制图片上传的过程,可以使用如下代码 - -```javascript -editor.customConfig.customUploadImg = function (files, insert) { - // files 是 input 中选中的文件列表 - // insert 是获取图片 url 后,插入到编辑器的方法 - - // 上传代码返回结果之后,将图片插入到编辑器中 - insert(imgUrl) -} -``` diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/04-qiniu.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/04-qiniu.md deleted file mode 100644 index e5c2ca4..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/04-uploadimg/04-qiniu.md +++ /dev/null @@ -1,115 +0,0 @@ -# 上传到七牛云存储 - -完整的 demo 请参见 https://github.com/wangfupeng1988/js-sdk ,可下载下来本地运行 demo - -> 注意:配置了上传七牛云存储之后,**无法再使用插入网络图片** - -核心代码如下: - -```js -var E = window.wangEditor -var editor = new E('#div1') -// 允许上传到七牛云存储 -editor.customConfig.qiniu = true -editor.create() - -// 初始化七牛上传 -uploadInit() - -// 初始化七牛上传的方法 -function uploadInit() { - // 获取相关 DOM 节点的 ID - var btnId = editor.imgMenuId; - var containerId = editor.toolbarElemId; - var textElemId = editor.textElemId; - - // 创建上传对象 - var uploader = Qiniu.uploader({ - runtimes: 'html5,flash,html4', //上传模式,依次退化 - browse_button: btnId, //上传选择的点选按钮,**必需** - uptoken_url: '/uptoken', - //Ajax请求upToken的Url,**强烈建议设置**(服务端提供) - // uptoken : '', - //若未指定uptoken_url,则必须指定 uptoken ,uptoken由其他程序生成 - // unique_names: true, - // 默认 false,key为文件名。若开启该选项,SDK会为每个文件自动生成key(文件名) - // save_key: true, - // 默认 false。若在服务端生成uptoken的上传策略中指定了 `sava_key`,则开启,SDK在前端将不对key进行任何处理 - domain: 'http://7xrjl5.com1.z0.glb.clouddn.com/', - //bucket 域名,下载资源时用到,**必需** - container: containerId, //上传区域DOM ID,默认是browser_button的父元素, - max_file_size: '100mb', //最大文件体积限制 - flash_swf_url: '../js/plupload/Moxie.swf', //引入flash,相对路径 - filters: { - mime_types: [ - //只允许上传图片文件 (注意,extensions中,逗号后面不要加空格) - { title: "图片文件", extensions: "jpg,gif,png,bmp" } - ] - }, - max_retries: 3, //上传失败最大重试次数 - dragdrop: true, //开启可拖曳上传 - drop_element: textElemId, //拖曳上传区域元素的ID,拖曳文件或文件夹后可触发上传 - chunk_size: '4mb', //分块上传时,每片的体积 - auto_start: true, //选择文件后自动上传,若关闭需要自己绑定事件触发上传 - init: { - 'FilesAdded': function(up, files) { - plupload.each(files, function(file) { - // 文件添加进队列后,处理相关的事情 - printLog('on FilesAdded'); - }); - }, - 'BeforeUpload': function(up, file) { - // 每个文件上传前,处理相关的事情 - printLog('on BeforeUpload'); - }, - 'UploadProgress': function(up, file) { - // 显示进度 - printLog('进度 ' + file.percent) - }, - 'FileUploaded': function(up, file, info) { - // 每个文件上传成功后,处理相关的事情 - // 其中 info 是文件上传成功后,服务端返回的json,形式如 - // { - // "hash": "Fh8xVqod2MQ1mocfI4S4KpRL6D98", - // "key": "gogopher.jpg" - // } - printLog(info); - // 参考http://developer.qiniu.com/docs/v6/api/overview/up/response/simple-response.html - - var domain = up.getOption('domain'); - var res = $.parseJSON(info); - var sourceLink = domain + res.key; //获取上传成功后的文件的Url - - printLog(sourceLink); - - // 插入图片到editor - editor.cmd.do('insertHtml', '') - }, - 'Error': function(up, err, errTip) { - //上传出错时,处理相关的事情 - printLog('on Error'); - }, - 'UploadComplete': function() { - //队列文件处理完毕后,处理相关的事情 - printLog('on UploadComplete'); - } - // Key 函数如果有需要自行配置,无特殊需要请注释 - //, - // 'Key': function(up, file) { - // // 若想在前端对每个文件的key进行个性化处理,可以配置该函数 - // // 该配置必须要在 unique_names: false , save_key: false 时才生效 - // var key = ""; - // // do something with key here - // return key - // } - } - // domain 为七牛空间(bucket)对应的域名,选择某个空间后,可通过"空间设置->基本设置->域名设置"查看获取 - // uploader 为一个plupload对象,继承了所有plupload的方法,参考http://plupload.com/docs - }); -} - -// 封装 console.log 函数 -function printLog(title, info) { - window.console && console.log(title, info); -} -``` \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/01-全屏-预览-查看源码.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/01-全屏-预览-查看源码.md deleted file mode 100644 index 27588c8..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/01-全屏-预览-查看源码.md +++ /dev/null @@ -1,10 +0,0 @@ -# 全屏 & 预览 & 查看源码 - -## 全屏 - -虽然 wangEditor 没有内置全屏功能,但是你可以通过简单的代码来搞定,作者已经做了一个demo来示范。通过运行 demo(文档一开始就介绍了)即可看到该示例页面,直接查看页面源代码即可。 - -## 预览 & 查看源码 - -如果需要预览和查看源码的功能,也需要跟全屏功能一样,自己定义按钮。点击按钮时通过`editor.txt.html()`获取编辑器内容,然后自定义实现预览和查看源码功能。 - diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/02-上传附件.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/02-上传附件.md deleted file mode 100644 index 1f3cc88..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/02-上传附件.md +++ /dev/null @@ -1,24 +0,0 @@ -# 关于上传附件 - -**有用户问到编辑器能否有上传附件的功能?我的建议是不要把附件做到内容中。** - -原因很简单,如果将附件上传之后再插入到富文本内容中,其实就是一个链接的形式。如下图: - -![](http://box.kancloud.cn/2016-02-19_56c718ec6f9bf.png) - -而用户在用编辑器编辑文本时,操作是非常随意多样的,他把这个链接删了,你服务器要想实时删除上传的附件文件,是难监控到的。 - -还有,用户如果要上传很多个附件,也是很难管理的,还是因为富文本的内容变化多样,用户可以随便在什么地方插入附件,而且形式和链接一样。 - -------- - -反过来,我们想一下平时用附件和编辑器最多的产品是什么——是邮箱。邮箱如何处理附件的,大家应该很清楚。它把文本内容和附件分开,这样附件就可以很轻松、明了的进行管理,绝对不会和编辑内容的链接产生混淆。 - -![](http://box.kancloud.cn/2016-02-19_56c718ec83f7e.png) - -你能看到的所有的邮箱产品,几乎都是这样设计的。 - -------- - -因此,在你提问编辑器能否上传附件这个问题的时候,可以想一下能否参照邮箱的实现来设计? - diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/03-markdown.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/03-markdown.md deleted file mode 100644 index c723347..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/03-markdown.md +++ /dev/null @@ -1,12 +0,0 @@ -# 关于 markdown - -**好多使用者问到,wangEditor编辑器能否集成markdown?——答案是:富文本编辑器无法和markdown集成到一起。** - ------ - - -你可以参考 [简书](http://www.jianshu.com/) 的实现方式,简书中编辑器也无法实现富文本和`markdown`的自由切换。要么使用富文本编写文章,要么使用`markdown`编写文章,不能公用。 - -本质上,富文本编辑器和`markdown`编辑器是两回事儿。 - - diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/04-xss.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/04-xss.md deleted file mode 100644 index 286337f..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/04-xss.md +++ /dev/null @@ -1,23 +0,0 @@ -# 预防 XSS 攻击 - -> 术业有专攻 - -要想在前端预防 xss 攻击,还得依赖于其他工具,例如[xss.js](http://jsxss.com/zh/index.html)(如果打不开页面,就从百度搜一下) - -代码示例如下 - -```html - - - -``` - diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/05-react.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/05-react.md deleted file mode 100644 index 8dcc2d4..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/05-react.md +++ /dev/null @@ -1,7 +0,0 @@ -# 用于 React - -如果需要将 wangEditor 用于 React 中,可参见如下示例 - -- 下载源码 `git clone git@github.com:wangfupeng1988/wangEditor.git` -- 进入 React 示例目录 `cd wangEditor/example/demo/in-react/`,查看`src/App.js`即可 -- 也可以运行`npm install && npm start`查看在 React 中的效果(`http://localhost:3000/`) diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/06-vue.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/06-vue.md deleted file mode 100644 index 47e167a..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/06-vue.md +++ /dev/null @@ -1,7 +0,0 @@ -# 用于 Vue - -如果需要将 wangEditor 用于 Vue 中,可参见如下示例 - -- 下载源码 `git clone git@github.com:wangfupeng1988/wangEditor.git` -- 进入 vue 示例目录 `cd wangEditor/example/demo/in-vue/`,查看`src/components/Editor.vue`即可 -- 也可以运行`npm install && npm run dev`查看在 vue 中的效果(`http://localhost:8080/`) diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/07-ng.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/07-ng.md deleted file mode 100644 index 1d59afc..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/07-ng.md +++ /dev/null @@ -1,3 +0,0 @@ -# 用于 Angular - -感谢 [@fengnovo](https://github.com/fengnovo) 提供了一个 angular2 的兼容示例,可供参考 https://github.com/fengnovo/wangEditor/tree/master/example/demo/in-ng2 diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/08-api.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/08-api.md deleted file mode 100644 index e8b4f6d..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/05-other/08-api.md +++ /dev/null @@ -1,27 +0,0 @@ -# 常用 API - -## 属性 - -- 获取编辑器的唯一标识 `editor.id` -- 获取编辑区域 DOM 节点 `editor.$textElem[0]` -- 获取菜单栏 DOM 节点 `editor.$toolbarElem[0]` -- 获取编辑器配置信息 `editor.config` -- 获取编辑区域 DOM 节点 ID `editor.textElemId` -- 获取菜单栏 DOM 节点 ID `editor.toolbarElemId` -- 获取菜单栏中“图片”菜单的 DOM 节点 ID `editor.imgMenuId` - -## 方法 - -### 选取操作 - -- 获取选中的文字 `editor.selection.getSelectionText()` -- 获取选取所在的 DOM 节点 `editor.selection.getSelectionContainerElem()[0]` - - 开始节点 `editor.selection.getSelectionStartElem()[0]` - - 结束节点 `editor.selection.getSelectionEndElem()[0]` -- 折叠选取 `editor.selection.collapseRange()` -- 更多可参见[源码中](https://github.com/wangfupeng1988/wangEditor/blob/master/src/js/selection/index.js)定义的方法 - -### 编辑内容操作 - -- 插入 HTML `editor.cmd.do('insertHTML', '

...

')` -- 可通过`editor.cmd.do(name, value)`来执行`document.execCommand(name, false, value)`的操作 \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/docs/usage/README.md b/novel-admin/src/main/resources/static/wangEditor/docs/usage/README.md deleted file mode 100644 index 4c801e6..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/docs/usage/README.md +++ /dev/null @@ -1,3 +0,0 @@ -同步[../../README.md](../../README.md)的内容 - -将所有文档跟新到 www.kancloud.cn/wangfupeng/wangeditor3/332599 中 diff --git a/novel-admin/src/main/resources/static/wangEditor/example/README.md b/novel-admin/src/main/resources/static/wangEditor/example/README.md deleted file mode 100644 index 6e17ca0..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/README.md +++ /dev/null @@ -1 +0,0 @@ -wangEditor demo diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/package.json b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/package.json deleted file mode 100644 index 054d5cd..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "wangeditor-in-react", - "version": "0.1.0", - "private": true, - "dependencies": { - "react": "^15.5.4", - "react-dom": "^15.5.4", - "wangeditor": ">=3.0.0" - }, - "devDependencies": { - "react-scripts": "1.0.7" - }, - "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test --env=jsdom", - "eject": "react-scripts eject" - } -} diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/public/favicon.ico b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/public/favicon.ico deleted file mode 100644 index 5c125de5d897c1ff5692a656485b3216123dcd89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24838 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 - - - - - - - - - - React App - - - -
- - - diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/public/manifest.json b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/public/manifest.json deleted file mode 100644 index be607e4..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/public/manifest.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "192x192", - "type": "image/png" - } - ], - "start_url": "./index.html", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" -} diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/App.css b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/App.css deleted file mode 100644 index 15adfdc..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/App.css +++ /dev/null @@ -1,24 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - animation: App-logo-spin infinite 20s linear; - height: 80px; -} - -.App-header { - background-color: #222; - height: 150px; - padding: 20px; - color: white; -} - -.App-intro { - font-size: large; -} - -@keyframes App-logo-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } -} diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/App.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/App.js deleted file mode 100644 index 95b21fb..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/App.js +++ /dev/null @@ -1,48 +0,0 @@ -import React, { Component } from 'react'; -import logo from './logo.svg'; -import './App.css'; -import E from 'wangeditor' - -class App extends Component { - constructor(props, context) { - super(props, context); - this.state = { - editorContent: '' - } - } - render() { - return ( -
-
- logo -

Welcome to React

-
-

- To get started, edit src/App.js and save to reload. -

- - {/* 将生成编辑器 */} -
-
- - -
- ); - } - componentDidMount() { - const elem = this.refs.editorElem - const editor = new E(elem) - // 使用 onchange 函数监听内容的变化,并实时更新到 state 中 - editor.customConfig.onchange = html => { - this.setState({ - editorContent: html - }) - } - editor.create() - } - clickHandle() { - alert(this.state.editorContent) - } -} - -export default App; diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/App.test.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/App.test.js deleted file mode 100644 index b84af98..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/App.test.js +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App'; - -it('renders without crashing', () => { - const div = document.createElement('div'); - ReactDOM.render(, div); -}); diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/index.css b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/index.css deleted file mode 100644 index b4cc725..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/index.css +++ /dev/null @@ -1,5 +0,0 @@ -body { - margin: 0; - padding: 0; - font-family: sans-serif; -} diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/index.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/index.js deleted file mode 100644 index 53c7688..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/index.js +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App'; -import registerServiceWorker from './registerServiceWorker'; -import './index.css'; - -ReactDOM.render(, document.getElementById('root')); -registerServiceWorker(); diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/logo.svg b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/logo.svg deleted file mode 100644 index 6b60c10..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/logo.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/registerServiceWorker.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/registerServiceWorker.js deleted file mode 100644 index 9966897..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-react/src/registerServiceWorker.js +++ /dev/null @@ -1,51 +0,0 @@ -// In production, we register a service worker to serve assets from local cache. - -// This lets the app load faster on subsequent visits in production, and gives -// it offline capabilities. However, it also means that developers (and users) -// will only see deployed updates on the "N+1" visit to a page, since previously -// cached resources are updated in the background. - -// To learn more about the benefits of this model, read https://goo.gl/KwvDNy. -// This link also includes instructions on opting out of this behavior. - -export default function register() { - if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { - window.addEventListener('load', () => { - const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; - navigator.serviceWorker - .register(swUrl) - .then(registration => { - registration.onupdatefound = () => { - const installingWorker = registration.installing; - installingWorker.onstatechange = () => { - if (installingWorker.state === 'installed') { - if (navigator.serviceWorker.controller) { - // At this point, the old content will have been purged and - // the fresh content will have been added to the cache. - // It's the perfect time to display a "New content is - // available; please refresh." message in your web app. - console.log('New content is available; please refresh.'); - } else { - // At this point, everything has been precached. - // It's the perfect time to display a - // "Content is cached for offline use." message. - console.log('Content is cached for offline use.'); - } - } - }; - }; - }) - .catch(error => { - console.error('Error during service worker registration:', error); - }); - }); - } -} - -export function unregister() { - if ('serviceWorker' in navigator) { - navigator.serviceWorker.ready.then(registration => { - registration.unregister(); - }); - } -} diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/.babelrc b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/.babelrc deleted file mode 100644 index 13f0e47..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/.babelrc +++ /dev/null @@ -1,14 +0,0 @@ -{ - "presets": [ - ["env", { "modules": false }], - "stage-2" - ], - "plugins": ["transform-runtime"], - "comments": false, - "env": { - "test": { - "presets": ["env", "stage-2"], - "plugins": [ "istanbul" ] - } - } -} diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/.editorconfig b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/.editorconfig deleted file mode 100644 index 9d08a1a..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/.editorconfig +++ /dev/null @@ -1,9 +0,0 @@ -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/.postcssrc.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/.postcssrc.js deleted file mode 100644 index ea9a5ab..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/.postcssrc.js +++ /dev/null @@ -1,8 +0,0 @@ -// https://github.com/michael-ciniawsky/postcss-load-config - -module.exports = { - "plugins": { - // to edit target browsers: use "browserlist" field in package.json - "autoprefixer": {} - } -} diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/build.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/build.js deleted file mode 100644 index 6b8add1..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/build.js +++ /dev/null @@ -1,35 +0,0 @@ -require('./check-versions')() - -process.env.NODE_ENV = 'production' - -var ora = require('ora') -var rm = require('rimraf') -var path = require('path') -var chalk = require('chalk') -var webpack = require('webpack') -var config = require('../config') -var webpackConfig = require('./webpack.prod.conf') - -var spinner = ora('building for production...') -spinner.start() - -rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { - if (err) throw err - webpack(webpackConfig, function (err, stats) { - spinner.stop() - if (err) throw err - process.stdout.write(stats.toString({ - colors: true, - modules: false, - children: false, - chunks: false, - chunkModules: false - }) + '\n\n') - - console.log(chalk.cyan(' Build complete.\n')) - console.log(chalk.yellow( - ' Tip: built files are meant to be served over an HTTP server.\n' + - ' Opening index.html over file:// won\'t work.\n' - )) - }) -}) diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/check-versions.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/check-versions.js deleted file mode 100644 index 100f3a0..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/check-versions.js +++ /dev/null @@ -1,48 +0,0 @@ -var chalk = require('chalk') -var semver = require('semver') -var packageConfig = require('../package.json') -var shell = require('shelljs') -function exec (cmd) { - return require('child_process').execSync(cmd).toString().trim() -} - -var versionRequirements = [ - { - name: 'node', - currentVersion: semver.clean(process.version), - versionRequirement: packageConfig.engines.node - }, -] - -if (shell.which('npm')) { - versionRequirements.push({ - name: 'npm', - currentVersion: exec('npm --version'), - versionRequirement: packageConfig.engines.npm - }) -} - -module.exports = function () { - var warnings = [] - for (var i = 0; i < versionRequirements.length; i++) { - var mod = versionRequirements[i] - if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { - warnings.push(mod.name + ': ' + - chalk.red(mod.currentVersion) + ' should be ' + - chalk.green(mod.versionRequirement) - ) - } - } - - if (warnings.length) { - console.log('') - console.log(chalk.yellow('To use this template, you must update following to modules:')) - console.log() - for (var i = 0; i < warnings.length; i++) { - var warning = warnings[i] - console.log(' ' + warning) - } - console.log() - process.exit(1) - } -} diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/dev-client.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/dev-client.js deleted file mode 100644 index 18aa1e2..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/dev-client.js +++ /dev/null @@ -1,9 +0,0 @@ -/* eslint-disable */ -require('eventsource-polyfill') -var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') - -hotClient.subscribe(function (event) { - if (event.action === 'reload') { - window.location.reload() - } -}) diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/dev-server.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/dev-server.js deleted file mode 100644 index 782dc6f..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/dev-server.js +++ /dev/null @@ -1,89 +0,0 @@ -require('./check-versions')() - -var config = require('../config') -if (!process.env.NODE_ENV) { - process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) -} - -var opn = require('opn') -var path = require('path') -var express = require('express') -var webpack = require('webpack') -var proxyMiddleware = require('http-proxy-middleware') -var webpackConfig = require('./webpack.dev.conf') - -// default port where dev server listens for incoming traffic -var port = process.env.PORT || config.dev.port -// automatically open browser, if not set will be false -var autoOpenBrowser = !!config.dev.autoOpenBrowser -// Define HTTP proxies to your custom API backend -// https://github.com/chimurai/http-proxy-middleware -var proxyTable = config.dev.proxyTable - -var app = express() -var compiler = webpack(webpackConfig) - -var devMiddleware = require('webpack-dev-middleware')(compiler, { - publicPath: webpackConfig.output.publicPath, - quiet: true -}) - -var hotMiddleware = require('webpack-hot-middleware')(compiler, { - log: () => {} -}) -// force page reload when html-webpack-plugin template changes -compiler.plugin('compilation', function (compilation) { - compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { - hotMiddleware.publish({ action: 'reload' }) - cb() - }) -}) - -// proxy api requests -Object.keys(proxyTable).forEach(function (context) { - var options = proxyTable[context] - if (typeof options === 'string') { - options = { target: options } - } - app.use(proxyMiddleware(options.filter || context, options)) -}) - -// handle fallback for HTML5 history API -app.use(require('connect-history-api-fallback')()) - -// serve webpack bundle output -app.use(devMiddleware) - -// enable hot-reload and state-preserving -// compilation error display -app.use(hotMiddleware) - -// serve pure static assets -var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) -app.use(staticPath, express.static('./static')) - -var uri = 'http://localhost:' + port - -var _resolve -var readyPromise = new Promise(resolve => { - _resolve = resolve -}) - -console.log('> Starting dev server...') -devMiddleware.waitUntilValid(() => { - console.log('> Listening at ' + uri + '\n') - // when env is testing, don't need open it - if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { - opn(uri) - } - _resolve() -}) - -var server = app.listen(port) - -module.exports = { - ready: readyPromise, - close: () => { - server.close() - } -} diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/utils.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/utils.js deleted file mode 100644 index b1d54b4..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/utils.js +++ /dev/null @@ -1,71 +0,0 @@ -var path = require('path') -var config = require('../config') -var ExtractTextPlugin = require('extract-text-webpack-plugin') - -exports.assetsPath = function (_path) { - var assetsSubDirectory = process.env.NODE_ENV === 'production' - ? config.build.assetsSubDirectory - : config.dev.assetsSubDirectory - return path.posix.join(assetsSubDirectory, _path) -} - -exports.cssLoaders = function (options) { - options = options || {} - - var cssLoader = { - loader: 'css-loader', - options: { - minimize: process.env.NODE_ENV === 'production', - sourceMap: options.sourceMap - } - } - - // generate loader string to be used with extract text plugin - function generateLoaders (loader, loaderOptions) { - var loaders = [cssLoader] - if (loader) { - loaders.push({ - loader: loader + '-loader', - options: Object.assign({}, loaderOptions, { - sourceMap: options.sourceMap - }) - }) - } - - // Extract CSS when that option is specified - // (which is the case during production build) - if (options.extract) { - return ExtractTextPlugin.extract({ - use: loaders, - fallback: 'vue-style-loader' - }) - } else { - return ['vue-style-loader'].concat(loaders) - } - } - - // https://vue-loader.vuejs.org/en/configurations/extract-css.html - return { - css: generateLoaders(), - postcss: generateLoaders(), - less: generateLoaders('less'), - sass: generateLoaders('sass', { indentedSyntax: true }), - scss: generateLoaders('sass'), - stylus: generateLoaders('stylus'), - styl: generateLoaders('stylus') - } -} - -// Generate loaders for standalone style files (outside of .vue) -exports.styleLoaders = function (options) { - var output = [] - var loaders = exports.cssLoaders(options) - for (var extension in loaders) { - var loader = loaders[extension] - output.push({ - test: new RegExp('\\.' + extension + '$'), - use: loader - }) - } - return output -} diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/vue-loader.conf.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/vue-loader.conf.js deleted file mode 100644 index 7aee79b..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/vue-loader.conf.js +++ /dev/null @@ -1,12 +0,0 @@ -var utils = require('./utils') -var config = require('../config') -var isProduction = process.env.NODE_ENV === 'production' - -module.exports = { - loaders: utils.cssLoaders({ - sourceMap: isProduction - ? config.build.productionSourceMap - : config.dev.cssSourceMap, - extract: isProduction - }) -} diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/webpack.base.conf.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/webpack.base.conf.js deleted file mode 100644 index daa3589..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/webpack.base.conf.js +++ /dev/null @@ -1,58 +0,0 @@ -var path = require('path') -var utils = require('./utils') -var config = require('../config') -var vueLoaderConfig = require('./vue-loader.conf') - -function resolve (dir) { - return path.join(__dirname, '..', dir) -} - -module.exports = { - entry: { - app: './src/main.js' - }, - output: { - path: config.build.assetsRoot, - filename: '[name].js', - publicPath: process.env.NODE_ENV === 'production' - ? config.build.assetsPublicPath - : config.dev.assetsPublicPath - }, - resolve: { - extensions: ['.js', '.vue', '.json'], - alias: { - 'vue$': 'vue/dist/vue.esm.js', - '@': resolve('src') - } - }, - module: { - rules: [ - { - test: /\.vue$/, - loader: 'vue-loader', - options: vueLoaderConfig - }, - { - test: /\.js$/, - loader: 'babel-loader', - include: [resolve('src'), resolve('test')] - }, - { - test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, - loader: 'url-loader', - options: { - limit: 10000, - name: utils.assetsPath('img/[name].[hash:7].[ext]') - } - }, - { - test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, - loader: 'url-loader', - options: { - limit: 10000, - name: utils.assetsPath('fonts/[name].[hash:7].[ext]') - } - } - ] - } -} diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/webpack.dev.conf.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/webpack.dev.conf.js deleted file mode 100644 index 5470402..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/webpack.dev.conf.js +++ /dev/null @@ -1,35 +0,0 @@ -var utils = require('./utils') -var webpack = require('webpack') -var config = require('../config') -var merge = require('webpack-merge') -var baseWebpackConfig = require('./webpack.base.conf') -var HtmlWebpackPlugin = require('html-webpack-plugin') -var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') - -// add hot-reload related code to entry chunks -Object.keys(baseWebpackConfig.entry).forEach(function (name) { - baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) -}) - -module.exports = merge(baseWebpackConfig, { - module: { - rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) - }, - // cheap-module-eval-source-map is faster for development - devtool: '#cheap-module-eval-source-map', - plugins: [ - new webpack.DefinePlugin({ - 'process.env': config.dev.env - }), - // https://github.com/glenjamin/webpack-hot-middleware#installation--usage - new webpack.HotModuleReplacementPlugin(), - new webpack.NoEmitOnErrorsPlugin(), - // https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: 'index.html', - template: 'index.html', - inject: true - }), - new FriendlyErrorsPlugin() - ] -}) diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/webpack.prod.conf.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/webpack.prod.conf.js deleted file mode 100644 index da44b65..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/build/webpack.prod.conf.js +++ /dev/null @@ -1,120 +0,0 @@ -var path = require('path') -var utils = require('./utils') -var webpack = require('webpack') -var config = require('../config') -var merge = require('webpack-merge') -var baseWebpackConfig = require('./webpack.base.conf') -var CopyWebpackPlugin = require('copy-webpack-plugin') -var HtmlWebpackPlugin = require('html-webpack-plugin') -var ExtractTextPlugin = require('extract-text-webpack-plugin') -var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') - -var env = config.build.env - -var webpackConfig = merge(baseWebpackConfig, { - module: { - rules: utils.styleLoaders({ - sourceMap: config.build.productionSourceMap, - extract: true - }) - }, - devtool: config.build.productionSourceMap ? '#source-map' : false, - output: { - path: config.build.assetsRoot, - filename: utils.assetsPath('js/[name].[chunkhash].js'), - chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') - }, - plugins: [ - // http://vuejs.github.io/vue-loader/en/workflow/production.html - new webpack.DefinePlugin({ - 'process.env': env - }), - new webpack.optimize.UglifyJsPlugin({ - compress: { - warnings: false - }, - sourceMap: true - }), - // extract css into its own file - new ExtractTextPlugin({ - filename: utils.assetsPath('css/[name].[contenthash].css') - }), - // Compress extracted CSS. We are using this plugin so that possible - // duplicated CSS from different components can be deduped. - new OptimizeCSSPlugin({ - cssProcessorOptions: { - safe: true - } - }), - // generate dist index.html with correct asset hash for caching. - // you can customize output by editing /index.html - // see https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: config.build.index, - template: 'index.html', - inject: true, - minify: { - removeComments: true, - collapseWhitespace: true, - removeAttributeQuotes: true - // more options: - // https://github.com/kangax/html-minifier#options-quick-reference - }, - // necessary to consistently work with multiple chunks via CommonsChunkPlugin - chunksSortMode: 'dependency' - }), - // split vendor js into its own file - new webpack.optimize.CommonsChunkPlugin({ - name: 'vendor', - minChunks: function (module, count) { - // any required modules inside node_modules are extracted to vendor - return ( - module.resource && - /\.js$/.test(module.resource) && - module.resource.indexOf( - path.join(__dirname, '../node_modules') - ) === 0 - ) - } - }), - // extract webpack runtime and module manifest to its own file in order to - // prevent vendor hash from being updated whenever app bundle is updated - new webpack.optimize.CommonsChunkPlugin({ - name: 'manifest', - chunks: ['vendor'] - }), - // copy custom static assets - new CopyWebpackPlugin([ - { - from: path.resolve(__dirname, '../static'), - to: config.build.assetsSubDirectory, - ignore: ['.*'] - } - ]) - ] -}) - -if (config.build.productionGzip) { - var CompressionWebpackPlugin = require('compression-webpack-plugin') - - webpackConfig.plugins.push( - new CompressionWebpackPlugin({ - asset: '[path].gz[query]', - algorithm: 'gzip', - test: new RegExp( - '\\.(' + - config.build.productionGzipExtensions.join('|') + - ')$' - ), - threshold: 10240, - minRatio: 0.8 - }) - ) -} - -if (config.build.bundleAnalyzerReport) { - var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin - webpackConfig.plugins.push(new BundleAnalyzerPlugin()) -} - -module.exports = webpackConfig diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/config/dev.env.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/config/dev.env.js deleted file mode 100644 index efead7c..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/config/dev.env.js +++ /dev/null @@ -1,6 +0,0 @@ -var merge = require('webpack-merge') -var prodEnv = require('./prod.env') - -module.exports = merge(prodEnv, { - NODE_ENV: '"development"' -}) diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/config/index.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/config/index.js deleted file mode 100644 index 196da1f..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/config/index.js +++ /dev/null @@ -1,38 +0,0 @@ -// see http://vuejs-templates.github.io/webpack for documentation. -var path = require('path') - -module.exports = { - build: { - env: require('./prod.env'), - index: path.resolve(__dirname, '../dist/index.html'), - assetsRoot: path.resolve(__dirname, '../dist'), - assetsSubDirectory: 'static', - assetsPublicPath: '/', - productionSourceMap: true, - // Gzip off by default as many popular static hosts such as - // Surge or Netlify already gzip all static assets for you. - // Before setting to `true`, make sure to: - // npm install --save-dev compression-webpack-plugin - productionGzip: false, - productionGzipExtensions: ['js', 'css'], - // Run the build command with an extra argument to - // View the bundle analyzer report after build finishes: - // `npm run build --report` - // Set to `true` or `false` to always turn it on or off - bundleAnalyzerReport: process.env.npm_config_report - }, - dev: { - env: require('./dev.env'), - port: 8080, - autoOpenBrowser: true, - assetsSubDirectory: 'static', - assetsPublicPath: '/', - proxyTable: {}, - // CSS Sourcemaps off by default because relative paths are "buggy" - // with this option, according to the CSS-Loader README - // (https://github.com/webpack/css-loader#sourcemaps) - // In our experience, they generally work as expected, - // just be aware of this issue when enabling this option. - cssSourceMap: false - } -} diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/config/prod.env.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/config/prod.env.js deleted file mode 100644 index 773d263..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/config/prod.env.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - NODE_ENV: '"production"' -} diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/index.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/index.html deleted file mode 100644 index 47ae14a..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - wangeditor-in-vue - - -
- - - diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/package.json b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/package.json deleted file mode 100644 index 80cf68f..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/package.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "name": "wangeditor-in-vue", - "version": "1.0.0", - "description": "A Vue.js project", - "author": "git ", - "private": true, - "scripts": { - "dev": "node build/dev-server.js", - "start": "node build/dev-server.js", - "build": "node build/build.js" - }, - "dependencies": { - "vue": "^2.3.3", - "wangeditor": ">=3.0.0" - }, - "devDependencies": { - "autoprefixer": "^6.7.2", - "babel-core": "^6.22.1", - "babel-loader": "^6.2.10", - "babel-plugin-transform-runtime": "^6.22.0", - "babel-preset-env": "^1.3.2", - "babel-preset-stage-2": "^6.22.0", - "babel-register": "^6.22.0", - "chalk": "^1.1.3", - "connect-history-api-fallback": "^1.3.0", - "copy-webpack-plugin": "^4.0.1", - "css-loader": "^0.28.0", - "eventsource-polyfill": "^0.9.6", - "express": "^4.14.1", - "extract-text-webpack-plugin": "^2.0.0", - "file-loader": "^0.11.1", - "friendly-errors-webpack-plugin": "^1.1.3", - "html-webpack-plugin": "^2.28.0", - "http-proxy-middleware": "^0.17.3", - "webpack-bundle-analyzer": "^2.2.1", - "semver": "^5.3.0", - "shelljs": "^0.7.6", - "opn": "^4.0.2", - "optimize-css-assets-webpack-plugin": "^1.3.0", - "ora": "^1.2.0", - "rimraf": "^2.6.0", - "url-loader": "^0.5.8", - "vue-loader": "^12.1.0", - "vue-style-loader": "^3.0.1", - "vue-template-compiler": "^2.3.3", - "webpack": "^2.6.1", - "webpack-dev-middleware": "^1.10.0", - "webpack-hot-middleware": "^2.18.0", - "webpack-merge": "^4.1.0" - }, - "engines": { - "node": ">= 4.0.0", - "npm": ">= 3.0.0" - }, - "browserslist": [ - "> 1%", - "last 2 versions", - "not ie <= 8" - ] -} diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/App.vue b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/App.vue deleted file mode 100644 index 27d15ff..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/App.vue +++ /dev/null @@ -1,31 +0,0 @@ - - - - - diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/assets/logo.png b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/assets/logo.png deleted file mode 100644 index f3d2503fc2a44b5053b0837ebea6e87a2d339a43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6849 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 -
-
- -
- - - - - diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/components/Hello.vue b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/components/Hello.vue deleted file mode 100644 index 2d80539..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/components/Hello.vue +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/main.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/main.js deleted file mode 100644 index 7b7fec7..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/src/main.js +++ /dev/null @@ -1,13 +0,0 @@ -// The Vue build version to load with the `import` command -// (runtime-only or standalone) has been set in webpack.base.conf with an alias. -import Vue from 'vue' -import App from './App' - -Vue.config.productionTip = false - -/* eslint-disable no-new */ -new Vue({ - el: '#app', - template: '', - components: { App } -}) diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/static/.gitkeep b/novel-admin/src/main/resources/static/wangEditor/example/demo/in-vue/static/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-amd-main.js b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-amd-main.js deleted file mode 100644 index 444b2da..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-amd-main.js +++ /dev/null @@ -1,4 +0,0 @@ -require(['/wangEditor.min.js'], function (E) { - var editor2 = new E('#div3') - editor2.create() -}) \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-amd.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-amd.html deleted file mode 100644 index 6a3d666..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-amd.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - wangEditor 使用 AMD 加载 - - -

wangEditor 使用 AMD 加载

-
-

欢迎使用 wangEditor 富文本编辑器

-
- - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-css-reset.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-css-reset.html deleted file mode 100644 index c01a10d..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-css-reset.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - wangEditor css reset - - - -

wangEditor css reset

-
-

欢迎使用 wangEditor 富文本编辑器

-
- - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-emot.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-emot.html deleted file mode 100644 index 02d8f7f..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-emot.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - - wangEditor 配置表情 - - -

wangEditor 配置表情

-
-

欢迎使用 wangEditor 富文本编辑器

-
- - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-fullscreen.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-fullscreen.html deleted file mode 100644 index cbbaa01..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-fullscreen.html +++ /dev/null @@ -1,114 +0,0 @@ - - - - - wangEditor 全屏 - - - -

wangEditor 全屏

- - -
- -
-
-
- -
-
- -
-

wangEditor 本身不包含“全屏”功能,不过可以很简单的开发出来

-

注意,全屏模式与max-height有冲突,尽量避免一起使用

-
-
- - -
- - - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-get-content.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-get-content.html deleted file mode 100644 index 012c81c..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-get-content.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - wangEditor 获取内容 - - -

wangEditor 获取内容

-
-

欢迎使用 wangEditor 富文本编辑器

-

欢迎使用 wangEditor 富文本编辑器

-
-
- - -
- - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-getJSON.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-getJSON.html deleted file mode 100644 index 68cd155..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-getJSON.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - wangEditor demo getJSON - - -

获取 JSON

-
-

欢迎使用 wangEditor 富文本编辑器

- -
- - - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-lang.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-lang.html deleted file mode 100644 index 6c77826..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-lang.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - wangEditor lang test - - -

多语言测试

-
-

欢迎使用 wangEditor 富文本编辑器

-
- - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-menus.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-menus.html deleted file mode 100644 index 4afd45f..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-menus.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - wangEditor 菜单配置 - - -

wangEditor 自定义菜单配置

-
-

欢迎使用 wangEditor 富文本编辑器

-
- - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-mult.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-mult.html deleted file mode 100644 index bd6f7e1..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-mult.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - wangEditor 一个页面多个编辑器 - - - - -

第一个 demo(菜单和编辑器区域分开)

-
-
-
中间隔离带
-
-

请输入内容

-
- -

第二个 demo(常规)

-
-

请输入内容

-
- - - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-onblur.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-onblur.html deleted file mode 100644 index a6644bf..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-onblur.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - wangEditor test onblur - - -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-onchange.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-onchange.html deleted file mode 100644 index 231de10..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-onchange.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - wangEditor test onchange - - -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-onfocus.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-onfocus.html deleted file mode 100644 index 7d95de0..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-onfocus.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - wangEditor test onfocus - - -
-

欢迎使用 wangEditor 富文本编辑器

-
- - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-paste.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-paste.html deleted file mode 100644 index a3a7477..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-paste.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - wangEditor paste test - - -

wangEditor paste test

-
-

欢迎使用 wangEditor 富文本编辑器

-
- - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-set-content.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-set-content.html deleted file mode 100644 index 42eff3b..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-set-content.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - wangEditor 设置内容 - - -

wangEditor 设置内容

-
-

欢迎使用 wangEditor 富文本编辑器

-
-
- - -
- - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-sperate.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-sperate.html deleted file mode 100644 index 0d0b857..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-sperate.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - wangEditor 菜单和编辑器区域分离 - - - - -

wangEditor 菜单和编辑器区域分离

-
-
-
中间隔离带
-
-

请输入内容

-
- - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-textarea.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-textarea.html deleted file mode 100644 index 8e41119..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-textarea.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - wangEditor demo textarea - - -

编辑器

-
-

欢迎使用 wangEditor 富文本编辑器

-
- -
- -

textarea

- - - - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-uploadimg.html b/novel-admin/src/main/resources/static/wangEditor/example/demo/test-uploadimg.html deleted file mode 100644 index 97246ca..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/demo/test-uploadimg.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - - wangEditor 上传图片 - - -

wangEditor 上传图片到服务器

-
-

欢迎使用 wangEditor 富文本编辑器

-
- -

wangEditor 以base64保存图片文件

-
-

欢迎使用 wangEditor 富文本编辑器

-
- -

wangEditor 自定义上传图片

-
-

欢迎使用 wangEditor 富文本编辑器

-
- - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/favicon.ico b/novel-admin/src/main/resources/static/wangEditor/example/favicon.ico deleted file mode 100644 index 6075775de436a980a4302ef7aef74de01c41b0c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4286 zcmc&&O>B%&6n$7UQqdt=@z*v&Q?bzKLSoUO#6~PE5H>bMLPQ%IVu3WFL~PjjU9e$c zfk;F|M@mb`Y=jVGM%$!C!VrRx);ZI6larS>W7DtNoZk2D-+AwS_uX%%&P~8?eZAvf zcO~UqjdQLMfXb}^s4xD&HobBbqYCHF@12$fJ_32*-8g|<_tqZ#>?|C^uxf~-xLn|oXB z`M3t|{{_H0cm>P`lHUI+aOnQ4F`p02^xQ3w4}p8YBj6%13HaB#=D_DJ&;u}*Ia+}* zF60mGR}o|DGr261Cyd(_iMteuE62~e{}Rb_B9bTM?~25|hmJL`zUBD0OAgk=4?ky} zOa?TMju*rB$NS!deCx+NzYT!;mgB$e<9GOG(=^ zZ@UoK_#XM}ZEqlLZ883R-j8Q^9Z(LAkBNPW*x9QXLu?hj#q%zhoqd=37(e@*`R(z3 zmV>fM?8n7^+Uwaf*gG_a`ESCwPUhS{KL?s!@2SPByd%CAlY@@;K>c*g-fX^4FkT7RKFCkd z{sG|mXlyuM3;P403*ft!bsMW!jpN$R0(`dTfc3yvfSk%dfO$2bu}O@1#&#acKLmZO zzmD}9T1)T`LLa-sW6dA-AAA1ewg0gH7=J(ZZ#{af_pJGvOPoLX8vwpH_#Bb|KZ}+6 z{=q)NXV3?*7Lq^?dBg8t{G4a^VZ0@|vjBTw9 - - - - IcoMoon Demo - - - - - -
-

Font Name: icomoon (Glyphs: 27)

-
-
-

Grid Size: 14

-
-
- - - - icon-close -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-remove -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-times -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-trash-o -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-terminal -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-header -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-paint-brush -
-
- - -
-
- liga: - -
-
-
-
-

Grid Size: 16

-
-
- - - - icon-pencil2 -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-image -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-play -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-location -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-undo -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-redo -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-quotes-left -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-list-numbered -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-list2 -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-upload2 -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-link -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-happy -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-cancel-circle -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-bold -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-underline -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-italic -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-strikethrough -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-page-break -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-table2 -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-paragraph-left -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-paragraph-center -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-paragraph-right -
-
- - -
-
- liga: - -
-
-
- - -
-

Font Test Drive

- - -
  -
-
- -
-

Generated by IcoMoon

-
- - - - diff --git a/novel-admin/src/main/resources/static/wangEditor/example/icomoon/fonts/icomoon.eot b/novel-admin/src/main/resources/static/wangEditor/example/icomoon/fonts/icomoon.eot deleted file mode 100644 index 0d144fdfa4924f18e0bb237e911d7b4847e3f4fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5656 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 diff --git a/novel-admin/src/main/resources/static/wangEditor/example/icomoon/fonts/icomoon.svg b/novel-admin/src/main/resources/static/wangEditor/example/icomoon/fonts/icomoon.svg deleted file mode 100644 index 21be016..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/icomoon/fonts/icomoon.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/icomoon/fonts/icomoon.ttf b/novel-admin/src/main/resources/static/wangEditor/example/icomoon/fonts/icomoon.ttf deleted file mode 100644 index 80be9ad27182d62f562b8181714691ace353524a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5492 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 diff --git a/novel-admin/src/main/resources/static/wangEditor/example/icomoon/fonts/icomoon.woff b/novel-admin/src/main/resources/static/wangEditor/example/icomoon/fonts/icomoon.woff deleted file mode 100644 index fa64c4d86cef0bd3aadc1906f25b2c0ce6bf96da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5568 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 QY+$Fm0gCU~ - - - - wangEditor demo list - - - -
-

可访问 wangEditor 官网 了解更多内容

-
-

欢迎使用 wangEditor 富文本编辑器

-
- -

wangEditor demo list(demo页面直接查看网页源代码即可)

- - -

其他链接

-
- -
- -

向我捐赠

- -
- - - - - - \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/pay.png b/novel-admin/src/main/resources/static/wangEditor/example/pay.png deleted file mode 100644 index 98efb8d042abe0e0dc1e3db9581ce383304f572f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 95517 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 diff --git a/novel-admin/src/main/resources/static/wangEditor/example/server/index.js b/novel-admin/src/main/resources/static/wangEditor/example/server/index.js deleted file mode 100644 index 28d8a60..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/server/index.js +++ /dev/null @@ -1,88 +0,0 @@ -const fs = require('fs') -const path = require('path') -const formidable = require('formidable') -const util = require('./util.js') - -const koa = require('koa') -const app = koa() - -// 捕获错误 -const onerror = require('koa-onerror') -onerror(app) - -// post body 解析 -const bodyParser = require('koa-bodyparser') -app.use(bodyParser()) - -// 静态文件服务,针对 html js css fonts 文件 -const staticCache = require('koa-static-cache') -function setStaticCache() { - const exampleDir = path.join(__dirname, '..', '..', 'example') - const releaseDir = path.join(__dirname, '..', '..', 'release') - app.use(staticCache(exampleDir)) - app.use(staticCache(releaseDir)) -} -setStaticCache() - -// 配置路由 -const router = require('koa-router')() - -// 保存上传的文件 -function saveFiles(req) { - return new Promise((resolve, reject) => { - const imgLinks = [] - const form = new formidable.IncomingForm() - form.parse(req, function (err, fields, files) { - if (err) { - reject('formidable, form.parse err', err.stack) - } - // 存储图片的文件夹 - const storePath = path.resolve(__dirname, '..', 'upload-files') - if (!fs.existsSync(storePath)) { - fs.mkdirSync(storePath) - } - - // 遍历所有上传来的图片 - util.objForEach(files, (name, file) => { - // 图片临时位置 - const tempFilePath = file.path - // 图片名称和路径 - const fileName = file.name - const fullFileName = path.join(storePath, fileName) - // 将临时文件保存为正式文件 - fs.renameSync(tempFilePath, fullFileName) - // 存储链接 - imgLinks.push('/upload-files/' + fileName) - }) - - // 重新设置静态文件缓存 - setStaticCache() - - // 返回结果 - resolve({ - errno: 0, - data: imgLinks - }) - }) - }) -} - -// 上传图片 -router.post('/upload-img', function* () { - const ctx = this - const req = ctx.req - const res = ctx.res - - // 获取数据 - const data = yield saveFiles(req) - - // 返回结果 - this.body = JSON.stringify(data) -}) -app.use(router.routes()).use(router.allowedMethods()); - -// 启动服务 -app.listen(3000) -console.log('listening on port %s', 3000) - -module.exports = app \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/example/server/util.js b/novel-admin/src/main/resources/static/wangEditor/example/server/util.js deleted file mode 100644 index 62477f2..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/example/server/util.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - // 遍历对象 - objForEach: function (obj, fn) { - let key, result - for (key in obj) { - if (obj.hasOwnProperty(key)) { - result = fn.call(obj, key, obj[key]) - if (result === false) { - break - } - } - } - } -} \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/wangEditor/gulpfile.js b/novel-admin/src/main/resources/static/wangEditor/gulpfile.js deleted file mode 100644 index 171e7e5..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/gulpfile.js +++ /dev/null @@ -1,122 +0,0 @@ -const path = require('path') -const fs = require('fs') -const gulp = require('gulp') -const rollup = require('rollup') -const uglify = require('gulp-uglify') -const sourcemaps = require('gulp-sourcemaps') -const rename = require('gulp-rename') -const less = require('gulp-less') -const concat = require('gulp-concat') -const cssmin = require('gulp-cssmin') -const eslint = require('rollup-plugin-eslint') -const postcss = require('gulp-postcss') -const autoprefixer = require('autoprefixer') -const cssgrace = require('cssgrace') -const resolve = require('rollup-plugin-node-resolve') -const babel = require('rollup-plugin-babel') -const gulpReplace = require('gulp-replace') - -// 拷贝 fonts 文件 -gulp.task('copy-fonts', () => { - gulp.src('./src/fonts/*') - .pipe(gulp.dest('./release/fonts')) -}) - -// 处理 css -gulp.task('css', () => { - gulp.src('./src/less/**/*.less') - .pipe(less()) - // 产出的未压缩的文件名 - .pipe(concat('wangEditor.css')) - // 配置 postcss - .pipe(postcss([ - autoprefixer, - cssgrace - ])) - // 将 css 引用的字体文件转换为 base64 格式 - .pipe(gulpReplace( /'fonts\/w-e-icon\..+?'/gm, function (fontFile) { - // fontFile 例如 'fonts/w-e-icon.eot?paxlku' - fontFile = fontFile.slice(0, -1).slice(1) - fontFile = fontFile.split('?')[0] - var ext = fontFile.split('.')[1] - // 读取文件内容,转换为 base64 格式 - var filePath = path.resolve(__dirname, 'release', fontFile) - var content = fs.readFileSync(filePath) - var base64 = content.toString('base64') - // 返回 - return 'data:application/x-font-' + ext + ';charset=utf-8;base64,' + base64 - })) - // 产出文件的位置 - .pipe(gulp.dest('./release')) - // 产出的压缩后的文件名 - .pipe(rename('wangEditor.min.css')) - .pipe(cssmin()) - .pipe(gulp.dest('./release')) -}) - -// 处理 JS -gulp.task('script', () => { - // rollup 打包 js 模块 - return rollup.rollup({ - // 入口文件 - entry: './src/js/index.js', - plugins: [ - // 对原始文件启动 eslint 检查,配置参见 ./.eslintrc.json - eslint(), - resolve(), - babel({ - exclude: 'node_modules/**' // only transpile our source code - }) - ] - }).then(bundle => { - bundle.write({ - // 产出文件使用 umd 规范(即兼容 amd cjs 和 iife) - format: 'umd', - // iife 规范下的全局变量名称 - moduleName: 'wangEditor', - // 产出的未压缩的文件名 - dest: './release/wangEditor.js' - }).then(() => { - // 待 rollup 打包 js 完毕之后,再进行如下的处理: - gulp.src('./release/wangEditor.js') - // inline css - .pipe(gulpReplace(/__INLINE_CSS__/gm, function () { - // 读取 css 文件内容 - var filePath = path.resolve(__dirname, 'release', 'wangEditor.css') - var content = fs.readFileSync(filePath).toString('utf-8') - // 替换 \n \ ' 三个字符 - content = content.replace(/\n/g, '').replace(/\\/g, '\\\\').replace(/'/g, '\\\'') - return content - })) - .pipe(gulp.dest('./release')) - .pipe(sourcemaps.init()) - // 压缩 - .pipe(uglify()) - // 产出的压缩的文件名 - .pipe(rename('wangEditor.min.js')) - // 生成 sourcemap - .pipe(sourcemaps.write('')) - .pipe(gulp.dest('./release')) - }) - }) -}) - - -// 默认任务配置 -gulp.task('default', () => { - gulp.run('copy-fonts', 'css', 'script') - - // 监听 js 原始文件的变化 - gulp.watch('./src/js/**/*.js', () => { - gulp.run('script') - }) - // 监听 css 原始文件的变化 - gulp.watch('./src/less/**/*.less', () => { - gulp.run('css', 'script') - }) - // 监听 icon.less 的变化,变化时重新拷贝 fonts 文件 - gulp.watch('./src/less/icon.less', () => { - gulp.run('copy-fonts') - }) -}) - diff --git a/novel-admin/src/main/resources/static/wangEditor/package.json b/novel-admin/src/main/resources/static/wangEditor/package.json deleted file mode 100644 index b42d94d..0000000 --- a/novel-admin/src/main/resources/static/wangEditor/package.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "name": "wangeditor", - "title": "wangEditor", - "version": "3.0.17", - "description": "wangEditor - 基于javascript和css开发的 web 富文本编辑器, 轻量、简洁、易用、开源免费", - "homepage": "http://wangeditor.github.io/", - "author": { - "name": "wangfupeng1988", - "url": "https://github.com/wangfupeng1988" - }, - "keywords": [ - "wangEditor", - "web 富文本编辑器" - ], - "main": "release/wangEditor.js", - "maintainers": [ - { - "name": "wangfupeng1988", - "web": "http://www.cnblogs.com/wangfupeng1988/default.html?OnlyTitle=1", - "mail": "wangfupeng1988@163.com" - } - ], - "repositories": [ - { - "type": "git", - "url": "https://github.com/wangfupeng1988/wangEditor" - } - ], - "scripts": { - "release": "gulp", - "win-example": "node ./example/server/index.js", - "example": "/bin/rm -rf ./example/upload-files && mkdir ./example/upload-files && npm run win-example" - }, - "devDependencies": { - "autoprefixer": "^6.7.7", - "babel-plugin-external-helpers": "^6.22.0", - "babel-preset-latest": "^6.24.0", - "cssgrace": "^3.0.0", - "formidable": "^1.1.1", - "gulp": "^3.9.1", - "gulp-concat": "^2.6.1", - "gulp-cssmin": "^0.1.7", - "gulp-less": "^3.3.0", - "gulp-postcss": "^6.4.0", - "gulp-rename": "^1.2.2", - "gulp-replace": "^0.5.4", - "gulp-sourcemaps": "^2.5.0", - "gulp-uglify": "^2.1.2", - "koa": "^1.2.4", - "koa-bodyparser": "^2.3.0", - "koa-onerror": "^3.1.0", - "koa-router": "^5.4.0", - "koa-static-cache": "^4.0.0", - "rollup": "^0.41.6", - "rollup-plugin-babel": "^2.7.1", - "rollup-plugin-eslint": "^3.0.0", - "rollup-plugin-node-resolve": "^3.0.0" - }, - "dependencies": {} -} diff --git a/novel-admin/src/main/resources/static/wangEditor/release/fonts/w-e-icon.woff b/novel-admin/src/main/resources/static/wangEditor/release/fonts/w-e-icon.woff deleted file mode 100644 index fa64c4d86cef0bd3aadc1906f25b2c0ce6bf96da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5568 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 QY+$Fm0gCU~= 0 && matches.item(i) !== this) {} - return i > -1; - }; - } -}; - -/* - DOM 操作 API -*/ - -// 根据 html 代码片段创建 dom 对象 -function createElemByHTML(html) { - var div = void 0; - div = document.createElement('div'); - div.innerHTML = html; - return div.children; -} - -// 是否是 DOM List -function isDOMList(selector) { - if (!selector) { - return false; - } - if (selector instanceof HTMLCollection || selector instanceof NodeList) { - return true; - } - return false; -} - -// 封装 document.querySelectorAll -function querySelectorAll(selector) { - var result = document.querySelectorAll(selector); - if (isDOMList(result)) { - return result; - } else { - return [result]; - } -} - -// 记录所有的事件绑定 -var eventList = []; - -// 创建构造函数 -function DomElement(selector) { - if (!selector) { - return; - } - - // selector 本来就是 DomElement 对象,直接返回 - if (selector instanceof DomElement) { - return selector; - } - - this.selector = selector; - var nodeType = selector.nodeType; - - // 根据 selector 得出的结果(如 DOM,DOM List) - var selectorResult = []; - if (nodeType === 9) { - // document 节点 - selectorResult = [selector]; - } else if (nodeType === 1) { - // 单个 DOM 节点 - selectorResult = [selector]; - } else if (isDOMList(selector) || selector instanceof Array) { - // DOM List 或者数组 - selectorResult = selector; - } else if (typeof selector === 'string') { - // 字符串 - selector = selector.replace('/\n/mg', '').trim(); - if (selector.indexOf('<') === 0) { - // 如
- selectorResult = createElemByHTML(selector); - } else { - // 如 #id .class - selectorResult = querySelectorAll(selector); - } - } - - var length = selectorResult.length; - if (!length) { - // 空数组 - return this; - } - - // 加入 DOM 节点 - var i = void 0; - for (i = 0; i < length; i++) { - this[i] = selectorResult[i]; - } - this.length = length; -} - -// 修改原型 -DomElement.prototype = { - constructor: DomElement, - - // 类数组,forEach - forEach: function forEach(fn) { - var i = void 0; - for (i = 0; i < this.length; i++) { - var elem = this[i]; - var result = fn.call(elem, elem, i); - if (result === false) { - break; - } - } - return this; - }, - - // clone - clone: function clone(deep) { - var cloneList = []; - this.forEach(function (elem) { - cloneList.push(elem.cloneNode(!!deep)); - }); - return $(cloneList); - }, - - // 获取第几个元素 - get: function get(index) { - var length = this.length; - if (index >= length) { - index = index % length; - } - return $(this[index]); - }, - - // 第一个 - first: function first() { - return this.get(0); - }, - - // 最后一个 - last: function last() { - var length = this.length; - return this.get(length - 1); - }, - - // 绑定事件 - on: function on(type, selector, fn) { - // selector 不为空,证明绑定事件要加代理 - if (!fn) { - fn = selector; - selector = null; - } - - // type 是否有多个 - var types = []; - types = type.split(/\s+/); - - return this.forEach(function (elem) { - types.forEach(function (type) { - if (!type) { - return; - } - - // 记录下,方便后面解绑 - eventList.push({ - elem: elem, - type: type, - fn: fn - }); - - if (!selector) { - // 无代理 - elem.addEventListener(type, fn); - return; - } - - // 有代理 - elem.addEventListener(type, function (e) { - var target = e.target; - if (target.matches(selector)) { - fn.call(target, e); - } - }); - }); - }); - }, - - // 取消事件绑定 - off: function off(type, fn) { - return this.forEach(function (elem) { - elem.removeEventListener(type, fn); - }); - }, - - // 获取/设置 属性 - attr: function attr(key, val) { - if (val == null) { - // 获取值 - return this[0].getAttribute(key); - } else { - // 设置值 - return this.forEach(function (elem) { - elem.setAttribute(key, val); - }); - } - }, - - // 添加 class - addClass: function addClass(className) { - if (!className) { - return this; - } - return this.forEach(function (elem) { - var arr = void 0; - if (elem.className) { - // 解析当前 className 转换为数组 - arr = elem.className.split(/\s/); - arr = arr.filter(function (item) { - return !!item.trim(); - }); - // 添加 class - if (arr.indexOf(className) < 0) { - arr.push(className); - } - // 修改 elem.class - elem.className = arr.join(' '); - } else { - elem.className = className; - } - }); - }, - - // 删除 class - removeClass: function removeClass(className) { - if (!className) { - return this; - } - return this.forEach(function (elem) { - var arr = void 0; - if (elem.className) { - // 解析当前 className 转换为数组 - arr = elem.className.split(/\s/); - arr = arr.filter(function (item) { - item = item.trim(); - // 删除 class - if (!item || item === className) { - return false; - } - return true; - }); - // 修改 elem.class - elem.className = arr.join(' '); - } - }); - }, - - // 修改 css - css: function css(key, val) { - var currentStyle = key + ':' + val + ';'; - return this.forEach(function (elem) { - var style = (elem.getAttribute('style') || '').trim(); - var styleArr = void 0, - resultArr = []; - if (style) { - // 将 style 按照 ; 拆分为数组 - styleArr = style.split(';'); - styleArr.forEach(function (item) { - // 对每项样式,按照 : 拆分为 key 和 value - var arr = item.split(':').map(function (i) { - return i.trim(); - }); - if (arr.length === 2) { - resultArr.push(arr[0] + ':' + arr[1]); - } - }); - // 替换或者新增 - resultArr = resultArr.map(function (item) { - if (item.indexOf(key) === 0) { - return currentStyle; - } else { - return item; - } - }); - if (resultArr.indexOf(currentStyle) < 0) { - resultArr.push(currentStyle); - } - // 结果 - elem.setAttribute('style', resultArr.join('; ')); - } else { - // style 无值 - elem.setAttribute('style', currentStyle); - } - }); - }, - - // 显示 - show: function show() { - return this.css('display', 'block'); - }, - - // 隐藏 - hide: function hide() { - return this.css('display', 'none'); - }, - - // 获取子节点 - children: function children() { - var elem = this[0]; - if (!elem) { - return null; - } - - return $(elem.children); - }, - - // 获取子节点(包括文本节点) - childNodes: function childNodes() { - var elem = this[0]; - if (!elem) { - return null; - } - - return $(elem.childNodes); - }, - - // 增加子节点 - append: function append($children) { - return this.forEach(function (elem) { - $children.forEach(function (child) { - elem.appendChild(child); - }); - }); - }, - - // 移除当前节点 - remove: function remove() { - return this.forEach(function (elem) { - if (elem.remove) { - elem.remove(); - } else { - var parent = elem.parentElement; - parent && parent.removeChild(elem); - } - }); - }, - - // 是否包含某个子节点 - isContain: function isContain($child) { - var elem = this[0]; - var child = $child[0]; - return elem.contains(child); - }, - - // 尺寸数据 - getSizeData: function getSizeData() { - var elem = this[0]; - return elem.getBoundingClientRect(); // 可得到 bottom height left right top width 的数据 - }, - - // 封装 nodeName - getNodeName: function getNodeName() { - var elem = this[0]; - return elem.nodeName; - }, - - // 从当前元素查找 - find: function find(selector) { - var elem = this[0]; - return $(elem.querySelectorAll(selector)); - }, - - // 获取当前元素的 text - text: function text(val) { - if (!val) { - // 获取 text - var elem = this[0]; - return elem.innerHTML.replace(/<.*?>/g, function () { - return ''; - }); - } else { - // 设置 text - return this.forEach(function (elem) { - elem.innerHTML = val; - }); - } - }, - - // 获取 html - html: function html(value) { - var elem = this[0]; - if (value == null) { - return elem.innerHTML; - } else { - elem.innerHTML = value; - return this; - } - }, - - // 获取 value - val: function val() { - var elem = this[0]; - return elem.value.trim(); - }, - - // focus - focus: function focus() { - return this.forEach(function (elem) { - elem.focus(); - }); - }, - - // parent - parent: function parent() { - var elem = this[0]; - return $(elem.parentElement); - }, - - // parentUntil 找到符合 selector 的父节点 - parentUntil: function parentUntil(selector, _currentElem) { - var results = document.querySelectorAll(selector); - var length = results.length; - if (!length) { - // 传入的 selector 无效 - return null; - } - - var elem = _currentElem || this[0]; - if (elem.nodeName === 'BODY') { - return null; - } - - var parent = elem.parentElement; - var i = void 0; - for (i = 0; i < length; i++) { - if (parent === results[i]) { - // 找到,并返回 - return $(parent); - } - } - - // 继续查找 - return this.parentUntil(selector, parent); - }, - - // 判断两个 elem 是否相等 - equal: function equal($elem) { - if ($elem.nodeType === 1) { - return this[0] === $elem; - } else { - return this[0] === $elem[0]; - } - }, - - // 将该元素插入到某个元素前面 - insertBefore: function insertBefore(selector) { - var $referenceNode = $(selector); - var referenceNode = $referenceNode[0]; - if (!referenceNode) { - return this; - } - return this.forEach(function (elem) { - var parent = referenceNode.parentNode; - parent.insertBefore(elem, referenceNode); - }); - }, - - // 将该元素插入到某个元素后面 - insertAfter: function insertAfter(selector) { - var $referenceNode = $(selector); - var referenceNode = $referenceNode[0]; - if (!referenceNode) { - return this; - } - return this.forEach(function (elem) { - var parent = referenceNode.parentNode; - if (parent.lastChild === referenceNode) { - // 最后一个元素 - parent.appendChild(elem); - } else { - // 不是最后一个元素 - parent.insertBefore(elem, referenceNode.nextSibling); - } - }); - } -}; - -// new 一个对象 -function $(selector) { - return new DomElement(selector); -} - -// 解绑所有事件,用于销毁编辑器 -$.offAll = function () { - eventList.forEach(function (item) { - var elem = item.elem; - var type = item.type; - var fn = item.fn; - // 解绑 - elem.removeEventListener(type, fn); - }); -}; - -/* - 配置信息 -*/ - -var config = { - - // 默认菜单配置 - menus: ['head', 'bold', 'italic', 'underline', 'strikeThrough', 'foreColor', 'backColor', 'link', 'list', 'justify', 'quote', 'emoticon', 'image', 'table', 'video', 'code', 'undo', 'redo'], - - colors: ['#000000', '#eeece0', '#1c487f', '#4d80bf', '#c24f4a', '#8baa4a', '#7b5ba1', '#46acc8', '#f9963b', '#ffffff'], - - // // 语言配置 - // lang: { - // '设置标题': 'title', - // '正文': 'p', - // '链接文字': 'link text', - // '链接': 'link', - // '插入': 'insert', - // '创建': 'init' - // }, - - // 表情 - emotions: [{ - // tab 的标题 - title: '默认', - // type -> 'emoji' / 'image' - type: 'image', - // content -> 数组 - content: [{ - alt: '[坏笑]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/50/pcmoren_huaixiao_org.png' - }, { - alt: '[舔屏]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/40/pcmoren_tian_org.png' - }, { - alt: '[污]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/3c/pcmoren_wu_org.png' - }, { - alt: '[允悲]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/2c/moren_yunbei_org.png' - }, { - alt: '[笑而不语]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/3a/moren_xiaoerbuyu_org.png' - }, { - alt: '[费解]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/3c/moren_feijie_org.png' - }, { - alt: '[憧憬]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/37/moren_chongjing_org.png' - }, { - alt: '[并不简单]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/fc/moren_bbjdnew_org.png' - }, { - alt: '[微笑]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/5c/huanglianwx_org.gif' - }, { - alt: '[酷]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/8a/pcmoren_cool2017_org.png' - }, { - alt: '[嘻嘻]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/0b/tootha_org.gif' - }, { - alt: '[哈哈]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/6a/laugh.gif' - }, { - alt: '[可爱]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/14/tza_org.gif' - }, { - alt: '[可怜]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/af/kl_org.gif' - }, { - alt: '[挖鼻]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/0b/wabi_org.gif' - }, { - alt: '[吃惊]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/f4/cj_org.gif' - }, { - alt: '[害羞]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/6e/shamea_org.gif' - }, { - alt: '[挤眼]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/c3/zy_org.gif' - }, { - alt: '[闭嘴]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/29/bz_org.gif' - }, { - alt: '[鄙视]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/71/bs2_org.gif' - }, { - alt: '[爱你]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/6d/lovea_org.gif' - }, { - alt: '[泪]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/9d/sada_org.gif' - }, { - alt: '[偷笑]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/19/heia_org.gif' - }, { - alt: '[亲亲]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/8f/qq_org.gif' - }, { - alt: '[生病]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/b6/sb_org.gif' - }, { - alt: '[太开心]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/58/mb_org.gif' - }, { - alt: '[白眼]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/d9/landeln_org.gif' - }, { - alt: '[右哼哼]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/98/yhh_org.gif' - }, { - alt: '[左哼哼]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/6d/zhh_org.gif' - }, { - alt: '[嘘]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/a6/x_org.gif' - }, { - alt: '[衰]', - src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/af/cry.gif' - }] - }, { - // tab 的标题 - title: '新浪', - // type -> 'emoji' / 'image' - type: 'image', - // content -> 数组 - content: [{ - src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/7a/shenshou_thumb.gif', - alt: '[草泥马]' - }, { - src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/60/horse2_thumb.gif', - alt: '[神马]' - }, { - src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/bc/fuyun_thumb.gif', - alt: '[浮云]' - }, { - src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/c9/geili_thumb.gif', - alt: '[给力]' - }, { - src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/f2/wg_thumb.gif', - alt: '[围观]' - }, { - src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/70/vw_thumb.gif', - alt: '[威武]' - }, { - src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/6e/panda_thumb.gif', - alt: '[熊猫]' - }, { - src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/81/rabbit_thumb.gif', - alt: '[兔子]' - }, { - src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/bc/otm_thumb.gif', - alt: '[奥特曼]' - }, { - src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/15/j_thumb.gif', - alt: '[囧]' - }, { - src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/89/hufen_thumb.gif', - alt: '[互粉]' - }, { - src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/c4/liwu_thumb.gif', - alt: '[礼物]' - }] - }, { - // tab 的标题 - title: 'emoji', - // type -> 'emoji' / 'image' - type: 'emoji', - // content -> 数组 - content: '😀 😃 😄 😁 😆 😅 😂 😊 😇 🙂 🙃 😉 😌 😍 😘 😗 😙 😚 😋 😜 😝 😛 🤑 🤗 🤓 😎 😏 😒 😞 😔 😟 😕 🙁 😣 😖 😫 😩 😤 😠 😡 😶 😐 😑 😯 😦 😧 😮 😲 😵 😳 😱 😨 😰 😢 😥 😭 😓 😪 😴 🙄 🤔 😬 🤐'.split(/\s/) - }], - - // 编辑区域的 z-index - zIndex: 10000, - - // 是否开启 debug 模式(debug 模式下错误会 throw error 形式抛出) - debug: false, - - // 插入链接时候的格式校验 - linkCheck: function linkCheck(text, link) { - // text 是插入的文字 - // link 是插入的链接 - return true; // 返回 true 即表示成功 - // return '校验失败' // 返回字符串即表示失败的提示信息 - }, - - // 插入网络图片的校验 - linkImgCheck: function linkImgCheck(src) { - // src 即图片的地址 - return true; // 返回 true 即表示成功 - // return '校验失败' // 返回字符串即表示失败的提示信息 - }, - - // 粘贴过滤样式,默认开启 - pasteFilterStyle: true, - - // 对粘贴的文字进行自定义处理,返回处理后的结果。编辑器会将处理后的结果粘贴到编辑区域中。 - // IE 暂时不支持 - pasteTextHandle: function pasteTextHandle(content) { - // content 即粘贴过来的内容(html 或 纯文本),可进行自定义处理然后返回 - return content; - }, - - // onchange 事件 - // onchange: function (html) { - // // html 即变化之后的内容 - // console.log(html) - // }, - - // 是否显示添加网络图片的 tab - showLinkImg: true, - - // 插入网络图片的回调 - linkImgCallback: function linkImgCallback(url) { - // console.log(url) // url 即插入图片的地址 - }, - - // 默认上传图片 max size: 5M - uploadImgMaxSize: 5 * 1024 * 1024, - - // 配置一次最多上传几个图片 - // uploadImgMaxLength: 5, - - // 上传图片,是否显示 base64 格式 - uploadImgShowBase64: false, - - // 上传图片,server 地址(如果有值,则 base64 格式的配置则失效) - // uploadImgServer: '/upload', - - // 自定义配置 filename - uploadFileName: '', - - // 上传图片的自定义参数 - uploadImgParams: { - // token: 'abcdef12345' - }, - - // 上传图片的自定义header - uploadImgHeaders: { - // 'Accept': 'text/x-json' - }, - - // 配置 XHR withCredentials - withCredentials: false, - - // 自定义上传图片超时时间 ms - uploadImgTimeout: 10000, - - // 上传图片 hook - uploadImgHooks: { - // customInsert: function (insertLinkImg, result, editor) { - // console.log('customInsert') - // // 图片上传并返回结果,自定义插入图片的事件,而不是编辑器自动插入图片 - // const data = result.data1 || [] - // data.forEach(link => { - // insertLinkImg(link) - // }) - // }, - before: function before(xhr, editor, files) { - // 图片上传之前触发 - - // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传 - // return { - // prevent: true, - // msg: '放弃上传' - // } - }, - success: function success(xhr, editor, result) { - // 图片上传并返回结果,图片插入成功之后触发 - }, - fail: function fail(xhr, editor, result) { - // 图片上传并返回结果,但图片插入错误时触发 - }, - error: function error(xhr, editor) { - // 图片上传出错时触发 - }, - timeout: function timeout(xhr, editor) { - // 图片上传超时时触发 - } - }, - - // 是否上传七牛云,默认为 false - qiniu: false - -}; - -/* - 工具 -*/ - -// 和 UA 相关的属性 -var UA = { - _ua: navigator.userAgent, - - // 是否 webkit - isWebkit: function isWebkit() { - var reg = /webkit/i; - return reg.test(this._ua); - }, - - // 是否 IE - isIE: function isIE() { - return 'ActiveXObject' in window; - } -}; - -// 遍历对象 -function objForEach(obj, fn) { - var key = void 0, - result = void 0; - for (key in obj) { - if (obj.hasOwnProperty(key)) { - result = fn.call(obj, key, obj[key]); - if (result === false) { - break; - } - } - } -} - -// 遍历类数组 -function arrForEach(fakeArr, fn) { - var i = void 0, - item = void 0, - result = void 0; - var length = fakeArr.length || 0; - for (i = 0; i < length; i++) { - item = fakeArr[i]; - result = fn.call(fakeArr, item, i); - if (result === false) { - break; - } - } -} - -// 获取随机数 -function getRandom(prefix) { - return prefix + Math.random().toString().slice(2); -} - -// 替换 html 特殊字符 -function replaceHtmlSymbol(html) { - if (html == null) { - return ''; - } - return html.replace(//gm, '>').replace(/"/gm, '"'); -} - -// 返回百分比的格式 - - -// 判断是不是 function -function isFunction(fn) { - return typeof fn === 'function'; -} - -/* - bold-menu -*/ -// 构造函数 -function Bold(editor) { - this.editor = editor; - this.$elem = $('
\n \n
'); - this.type = 'click'; - - // 当前是否 active 状态 - this._active = false; -} - -// 原型 -Bold.prototype = { - constructor: Bold, - - // 点击事件 - onClick: function onClick(e) { - // 点击菜单将触发这里 - - var editor = this.editor; - var isSeleEmpty = editor.selection.isSelectionEmpty(); - - if (isSeleEmpty) { - // 选区是空的,插入并选中一个“空白” - editor.selection.createEmptyRange(); - } - - // 执行 bold 命令 - editor.cmd.do('bold'); - - if (isSeleEmpty) { - // 需要将选取折叠起来 - editor.selection.collapseRange(); - editor.selection.restoreSelection(); - } - }, - - // 试图改变 active 状态 - tryChangeActive: function tryChangeActive(e) { - var editor = this.editor; - var $elem = this.$elem; - if (editor.cmd.queryCommandState('bold')) { - this._active = true; - $elem.addClass('w-e-active'); - } else { - this._active = false; - $elem.removeClass('w-e-active'); - } - } -}; - -/* - 替换多语言 - */ - -var replaceLang = function (editor, str) { - var langArgs = editor.config.langArgs || []; - var result = str; - - langArgs.forEach(function (item) { - var reg = item.reg; - var val = item.val; - - if (reg.test(result)) { - result = result.replace(reg, function () { - return val; - }); - } - }); - - return result; -}; - -/* - droplist -*/ -var _emptyFn = function _emptyFn() {}; - -// 构造函数 -function DropList(menu, opt) { - var _this = this; - - // droplist 所依附的菜单 - var editor = menu.editor; - this.menu = menu; - this.opt = opt; - // 容器 - var $container = $('
'); - - // 标题 - var $title = opt.$title; - var titleHtml = void 0; - if ($title) { - // 替换多语言 - titleHtml = $title.html(); - titleHtml = replaceLang(editor, titleHtml); - $title.html(titleHtml); - - $title.addClass('w-e-dp-title'); - $container.append($title); - } - - var list = opt.list || []; - var type = opt.type || 'list'; // 'list' 列表形式(如“标题”菜单) / 'inline-block' 块状形式(如“颜色”菜单) - var onClick = opt.onClick || _emptyFn; - - // 加入 DOM 并绑定事件 - var $list = $('
    '); - $container.append($list); - list.forEach(function (item) { - var $elem = item.$elem; - - // 替换多语言 - var elemHtml = $elem.html(); - elemHtml = replaceLang(editor, elemHtml); - $elem.html(elemHtml); - - var value = item.value; - var $li = $('
  • '); - if ($elem) { - $li.append($elem); - $list.append($li); - $li.on('click', function (e) { - onClick(value); - - // 隐藏 - _this.hideTimeoutId = setTimeout(function () { - _this.hide(); - }, 0); - }); - } - }); - - // 绑定隐藏事件 - $container.on('mouseleave', function (e) { - _this.hideTimeoutId = setTimeout(function () { - _this.hide(); - }, 0); - }); - - // 记录属性 - this.$container = $container; - - // 基本属性 - this._rendered = false; - this._show = false; -} - -// 原型 -DropList.prototype = { - constructor: DropList, - - // 显示(插入DOM) - show: function show() { - if (this.hideTimeoutId) { - // 清除之前的定时隐藏 - clearTimeout(this.hideTimeoutId); - } - - var menu = this.menu; - var $menuELem = menu.$elem; - var $container = this.$container; - if (this._show) { - return; - } - if (this._rendered) { - // 显示 - $container.show(); - } else { - // 加入 DOM 之前先定位位置 - var menuHeight = $menuELem.getSizeData().height || 0; - var width = this.opt.width || 100; // 默认为 100 - $container.css('margin-top', menuHeight + 'px').css('width', width + 'px'); - - // 加入到 DOM - $menuELem.append($container); - this._rendered = true; - } - - // 修改属性 - this._show = true; - }, - - // 隐藏(移除DOM) - hide: function hide() { - if (this.showTimeoutId) { - // 清除之前的定时显示 - clearTimeout(this.showTimeoutId); - } - - var $container = this.$container; - if (!this._show) { - return; - } - // 隐藏并需改属性 - $container.hide(); - this._show = false; - } -}; - -/* - menu - header -*/ -// 构造函数 -function Head(editor) { - var _this = this; - - this.editor = editor; - this.$elem = $('
    '); - this.type = 'droplist'; - - // 当前是否 active 状态 - this._active = false; - - // 初始化 droplist - this.droplist = new DropList(this, { - width: 100, - $title: $('

    设置标题

    '), - type: 'list', // droplist 以列表形式展示 - list: [{ $elem: $('

    H1

    '), value: '

    ' }, { $elem: $('

    H2

    '), value: '

    ' }, { $elem: $('

    H3

    '), value: '

    ' }, { $elem: $('

    H4

    '), value: '

    ' }, { $elem: $('

    H5
    '), value: '
    ' }, { $elem: $('

    正文

    '), value: '

    ' }], - onClick: function onClick(value) { - // 注意 this 是指向当前的 Head 对象 - _this._command(value); - } - }); -} - -// 原型 -Head.prototype = { - constructor: Head, - - // 执行命令 - _command: function _command(value) { - var editor = this.editor; - - var $selectionElem = editor.selection.getSelectionContainerElem(); - if (editor.$textElem.equal($selectionElem)) { - // 不能选中多行来设置标题,否则会出现问题 - // 例如选中的是

    xxx

    yyy

    来设置标题,设置之后会成为

    xxx
    yyy

    不符合预期 - return; - } - - editor.cmd.do('formatBlock', value); - }, - - // 试图改变 active 状态 - tryChangeActive: function tryChangeActive(e) { - var editor = this.editor; - var $elem = this.$elem; - var reg = /^h/i; - var cmdValue = editor.cmd.queryCommandValue('formatBlock'); - if (reg.test(cmdValue)) { - this._active = true; - $elem.addClass('w-e-active'); - } else { - this._active = false; - $elem.removeClass('w-e-active'); - } - } -}; - -/* - panel -*/ - -var emptyFn = function emptyFn() {}; - -// 记录已经显示 panel 的菜单 -var _isCreatedPanelMenus = []; - -// 构造函数 -function Panel(menu, opt) { - this.menu = menu; - this.opt = opt; -} - -// 原型 -Panel.prototype = { - constructor: Panel, - - // 显示(插入DOM) - show: function show() { - var _this = this; - - var menu = this.menu; - if (_isCreatedPanelMenus.indexOf(menu) >= 0) { - // 该菜单已经创建了 panel 不能再创建 - return; - } - - var editor = menu.editor; - var $body = $('body'); - var $textContainerElem = editor.$textContainerElem; - var opt = this.opt; - - // panel 的容器 - var $container = $('
    '); - var width = opt.width || 300; // 默认 300px - $container.css('width', width + 'px').css('margin-left', (0 - width) / 2 + 'px'); - - // 添加关闭按钮 - var $closeBtn = $(''); - $container.append($closeBtn); - $closeBtn.on('click', function () { - _this.hide(); - }); - - // 准备 tabs 容器 - var $tabTitleContainer = $('
      '); - var $tabContentContainer = $('
      '); - $container.append($tabTitleContainer).append($tabContentContainer); - - // 设置高度 - var height = opt.height; - if (height) { - $tabContentContainer.css('height', height + 'px').css('overflow-y', 'auto'); - } - - // tabs - var tabs = opt.tabs || []; - var tabTitleArr = []; - var tabContentArr = []; - tabs.forEach(function (tab, tabIndex) { - if (!tab) { - return; - } - var title = tab.title || ''; - var tpl = tab.tpl || ''; - - // 替换多语言 - title = replaceLang(editor, title); - tpl = replaceLang(editor, tpl); - - // 添加到 DOM - var $title = $('
    • ' + title + '
    • '); - $tabTitleContainer.append($title); - var $content = $(tpl); - $tabContentContainer.append($content); - - // 记录到内存 - $title._index = tabIndex; - tabTitleArr.push($title); - tabContentArr.push($content); - - // 设置 active 项 - if (tabIndex === 0) { - $title._active = true; - $title.addClass('w-e-active'); - } else { - $content.hide(); - } - - // 绑定 tab 的事件 - $title.on('click', function (e) { - if ($title._active) { - return; - } - // 隐藏所有的 tab - tabTitleArr.forEach(function ($title) { - $title._active = false; - $title.removeClass('w-e-active'); - }); - tabContentArr.forEach(function ($content) { - $content.hide(); - }); - - // 显示当前的 tab - $title._active = true; - $title.addClass('w-e-active'); - $content.show(); - }); - }); - - // 绑定关闭事件 - $container.on('click', function (e) { - // 点击时阻止冒泡 - e.stopPropagation(); - }); - $body.on('click', function (e) { - _this.hide(); - }); - - // 添加到 DOM - $textContainerElem.append($container); - - // 绑定 opt 的事件,只有添加到 DOM 之后才能绑定成功 - tabs.forEach(function (tab, index) { - if (!tab) { - return; - } - var events = tab.events || []; - events.forEach(function (event) { - var selector = event.selector; - var type = event.type; - var fn = event.fn || emptyFn; - var $content = tabContentArr[index]; - $content.find(selector).on(type, function (e) { - e.stopPropagation(); - var needToHide = fn(e); - // 执行完事件之后,是否要关闭 panel - if (needToHide) { - _this.hide(); - } - }); - }); - }); - - // focus 第一个 elem - var $inputs = $container.find('input[type=text],textarea'); - if ($inputs.length) { - $inputs.get(0).focus(); - } - - // 添加到属性 - this.$container = $container; - - // 隐藏其他 panel - this._hideOtherPanels(); - // 记录该 menu 已经创建了 panel - _isCreatedPanelMenus.push(menu); - }, - - // 隐藏(移除DOM) - hide: function hide() { - var menu = this.menu; - var $container = this.$container; - if ($container) { - $container.remove(); - } - - // 将该 menu 记录中移除 - _isCreatedPanelMenus = _isCreatedPanelMenus.filter(function (item) { - if (item === menu) { - return false; - } else { - return true; - } - }); - }, - - // 一个 panel 展示时,隐藏其他 panel - _hideOtherPanels: function _hideOtherPanels() { - if (!_isCreatedPanelMenus.length) { - return; - } - _isCreatedPanelMenus.forEach(function (menu) { - var panel = menu.panel || {}; - if (panel.hide) { - panel.hide(); - } - }); - } -}; - -/* - menu - link -*/ -// 构造函数 -function Link(editor) { - this.editor = editor; - this.$elem = $('
      '); - this.type = 'panel'; - - // 当前是否 active 状态 - this._active = false; -} - -// 原型 -Link.prototype = { - constructor: Link, - - // 点击事件 - onClick: function onClick(e) { - var editor = this.editor; - var $linkelem = void 0; - - if (this._active) { - // 当前选区在链接里面 - $linkelem = editor.selection.getSelectionContainerElem(); - if (!$linkelem) { - return; - } - // 将该元素都包含在选取之内,以便后面整体替换 - editor.selection.createRangeByElem($linkelem); - editor.selection.restoreSelection(); - // 显示 panel - this._createPanel($linkelem.text(), $linkelem.attr('href')); - } else { - // 当前选区不在链接里面 - if (editor.selection.isSelectionEmpty()) { - // 选区是空的,未选中内容 - this._createPanel('', ''); - } else { - // 选中内容了 - this._createPanel(editor.selection.getSelectionText(), ''); - } - } - }, - - // 创建 panel - _createPanel: function _createPanel(text, link) { - var _this = this; - - // panel 中需要用到的id - var inputLinkId = getRandom('input-link'); - var inputTextId = getRandom('input-text'); - var btnOkId = getRandom('btn-ok'); - var btnDelId = getRandom('btn-del'); - - // 是否显示“删除链接” - var delBtnDisplay = this._active ? 'inline-block' : 'none'; - - // 初始化并显示 panel - var panel = new Panel(this, { - width: 300, - // panel 中可包含多个 tab - tabs: [{ - // tab 的标题 - title: '链接', - // 模板 - tpl: '
      \n \n \n
      \n \n \n
      \n
      ', - // 事件绑定 - events: [ - // 插入链接 - { - selector: '#' + btnOkId, - type: 'click', - fn: function fn() { - // 执行插入链接 - var $link = $('#' + inputLinkId); - var $text = $('#' + inputTextId); - var link = $link.val(); - var text = $text.val(); - _this._insertLink(text, link); - - // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 - return true; - } - }, - // 删除链接 - { - selector: '#' + btnDelId, - type: 'click', - fn: function fn() { - // 执行删除链接 - _this._delLink(); - - // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 - return true; - } - }] - } // tab end - ] // tabs end - }); - - // 显示 panel - panel.show(); - - // 记录属性 - this.panel = panel; - }, - - // 删除当前链接 - _delLink: function _delLink() { - if (!this._active) { - return; - } - var editor = this.editor; - var $selectionELem = editor.selection.getSelectionContainerElem(); - if (!$selectionELem) { - return; - } - var selectionText = editor.selection.getSelectionText(); - editor.cmd.do('insertHTML', '' + selectionText + ''); - }, - - // 插入链接 - _insertLink: function _insertLink(text, link) { - var editor = this.editor; - var config = editor.config; - var linkCheck = config.linkCheck; - var checkResult = true; // 默认为 true - if (linkCheck && typeof linkCheck === 'function') { - checkResult = linkCheck(text, link); - } - if (checkResult === true) { - editor.cmd.do('insertHTML', '' + text + ''); - } else { - alert(checkResult); - } - }, - - // 试图改变 active 状态 - tryChangeActive: function tryChangeActive(e) { - var editor = this.editor; - var $elem = this.$elem; - var $selectionELem = editor.selection.getSelectionContainerElem(); - if (!$selectionELem) { - return; - } - if ($selectionELem.getNodeName() === 'A') { - this._active = true; - $elem.addClass('w-e-active'); - } else { - this._active = false; - $elem.removeClass('w-e-active'); - } - } -}; - -/* - italic-menu -*/ -// 构造函数 -function Italic(editor) { - this.editor = editor; - this.$elem = $('
      \n \n
      '); - this.type = 'click'; - - // 当前是否 active 状态 - this._active = false; -} - -// 原型 -Italic.prototype = { - constructor: Italic, - - // 点击事件 - onClick: function onClick(e) { - // 点击菜单将触发这里 - - var editor = this.editor; - var isSeleEmpty = editor.selection.isSelectionEmpty(); - - if (isSeleEmpty) { - // 选区是空的,插入并选中一个“空白” - editor.selection.createEmptyRange(); - } - - // 执行 italic 命令 - editor.cmd.do('italic'); - - if (isSeleEmpty) { - // 需要将选取折叠起来 - editor.selection.collapseRange(); - editor.selection.restoreSelection(); - } - }, - - // 试图改变 active 状态 - tryChangeActive: function tryChangeActive(e) { - var editor = this.editor; - var $elem = this.$elem; - if (editor.cmd.queryCommandState('italic')) { - this._active = true; - $elem.addClass('w-e-active'); - } else { - this._active = false; - $elem.removeClass('w-e-active'); - } - } -}; - -/* - redo-menu -*/ -// 构造函数 -function Redo(editor) { - this.editor = editor; - this.$elem = $('
      \n \n
      '); - this.type = 'click'; - - // 当前是否 active 状态 - this._active = false; -} - -// 原型 -Redo.prototype = { - constructor: Redo, - - // 点击事件 - onClick: function onClick(e) { - // 点击菜单将触发这里 - - var editor = this.editor; - - // 执行 redo 命令 - editor.cmd.do('redo'); - } -}; - -/* - strikeThrough-menu -*/ -// 构造函数 -function StrikeThrough(editor) { - this.editor = editor; - this.$elem = $('
      \n \n
      '); - this.type = 'click'; - - // 当前是否 active 状态 - this._active = false; -} - -// 原型 -StrikeThrough.prototype = { - constructor: StrikeThrough, - - // 点击事件 - onClick: function onClick(e) { - // 点击菜单将触发这里 - - var editor = this.editor; - var isSeleEmpty = editor.selection.isSelectionEmpty(); - - if (isSeleEmpty) { - // 选区是空的,插入并选中一个“空白” - editor.selection.createEmptyRange(); - } - - // 执行 strikeThrough 命令 - editor.cmd.do('strikeThrough'); - - if (isSeleEmpty) { - // 需要将选取折叠起来 - editor.selection.collapseRange(); - editor.selection.restoreSelection(); - } - }, - - // 试图改变 active 状态 - tryChangeActive: function tryChangeActive(e) { - var editor = this.editor; - var $elem = this.$elem; - if (editor.cmd.queryCommandState('strikeThrough')) { - this._active = true; - $elem.addClass('w-e-active'); - } else { - this._active = false; - $elem.removeClass('w-e-active'); - } - } -}; - -/* - underline-menu -*/ -// 构造函数 -function Underline(editor) { - this.editor = editor; - this.$elem = $('
      \n \n
      '); - this.type = 'click'; - - // 当前是否 active 状态 - this._active = false; -} - -// 原型 -Underline.prototype = { - constructor: Underline, - - // 点击事件 - onClick: function onClick(e) { - // 点击菜单将触发这里 - - var editor = this.editor; - var isSeleEmpty = editor.selection.isSelectionEmpty(); - - if (isSeleEmpty) { - // 选区是空的,插入并选中一个“空白” - editor.selection.createEmptyRange(); - } - - // 执行 underline 命令 - editor.cmd.do('underline'); - - if (isSeleEmpty) { - // 需要将选取折叠起来 - editor.selection.collapseRange(); - editor.selection.restoreSelection(); - } - }, - - // 试图改变 active 状态 - tryChangeActive: function tryChangeActive(e) { - var editor = this.editor; - var $elem = this.$elem; - if (editor.cmd.queryCommandState('underline')) { - this._active = true; - $elem.addClass('w-e-active'); - } else { - this._active = false; - $elem.removeClass('w-e-active'); - } - } -}; - -/* - undo-menu -*/ -// 构造函数 -function Undo(editor) { - this.editor = editor; - this.$elem = $('
      \n \n
      '); - this.type = 'click'; - - // 当前是否 active 状态 - this._active = false; -} - -// 原型 -Undo.prototype = { - constructor: Undo, - - // 点击事件 - onClick: function onClick(e) { - // 点击菜单将触发这里 - - var editor = this.editor; - - // 执行 undo 命令 - editor.cmd.do('undo'); - } -}; - -/* - menu - list -*/ -// 构造函数 -function List(editor) { - var _this = this; - - this.editor = editor; - this.$elem = $('
      '); - this.type = 'droplist'; - - // 当前是否 active 状态 - this._active = false; - - // 初始化 droplist - this.droplist = new DropList(this, { - width: 120, - $title: $('

      设置列表

      '), - type: 'list', // droplist 以列表形式展示 - list: [{ $elem: $(' 有序列表'), value: 'insertOrderedList' }, { $elem: $(' 无序列表'), value: 'insertUnorderedList' }], - onClick: function onClick(value) { - // 注意 this 是指向当前的 List 对象 - _this._command(value); - } - }); -} - -// 原型 -List.prototype = { - constructor: List, - - // 执行命令 - _command: function _command(value) { - var editor = this.editor; - var $textElem = editor.$textElem; - editor.selection.restoreSelection(); - if (editor.cmd.queryCommandState(value)) { - return; - } - editor.cmd.do(value); - - // 验证列表是否被包裹在

      之内 - var $selectionElem = editor.selection.getSelectionContainerElem(); - if ($selectionElem.getNodeName() === 'LI') { - $selectionElem = $selectionElem.parent(); - } - if (/^ol|ul$/i.test($selectionElem.getNodeName()) === false) { - return; - } - if ($selectionElem.equal($textElem)) { - // 证明是顶级标签,没有被

      包裹 - return; - } - var $parent = $selectionElem.parent(); - if ($parent.equal($textElem)) { - // $parent 是顶级标签,不能删除 - return; - } - - $selectionElem.insertAfter($parent); - $parent.remove(); - }, - - // 试图改变 active 状态 - tryChangeActive: function tryChangeActive(e) { - var editor = this.editor; - var $elem = this.$elem; - if (editor.cmd.queryCommandState('insertUnOrderedList') || editor.cmd.queryCommandState('insertOrderedList')) { - this._active = true; - $elem.addClass('w-e-active'); - } else { - this._active = false; - $elem.removeClass('w-e-active'); - } - } -}; - -/* - menu - justify -*/ -// 构造函数 -function Justify(editor) { - var _this = this; - - this.editor = editor; - this.$elem = $('

      '); - this.type = 'droplist'; - - // 当前是否 active 状态 - this._active = false; - - // 初始化 droplist - this.droplist = new DropList(this, { - width: 100, - $title: $('

      对齐方式

      '), - type: 'list', // droplist 以列表形式展示 - list: [{ $elem: $(' 靠左'), value: 'justifyLeft' }, { $elem: $(' 居中'), value: 'justifyCenter' }, { $elem: $(' 靠右'), value: 'justifyRight' }], - onClick: function onClick(value) { - // 注意 this 是指向当前的 List 对象 - _this._command(value); - } - }); -} - -// 原型 -Justify.prototype = { - constructor: Justify, - - // 执行命令 - _command: function _command(value) { - var editor = this.editor; - editor.cmd.do(value); - } -}; - -/* - menu - Forecolor -*/ -// 构造函数 -function ForeColor(editor) { - var _this = this; - - this.editor = editor; - this.$elem = $('
      '); - this.type = 'droplist'; - - // 获取配置的颜色 - var config = editor.config; - var colors = config.colors || []; - - // 当前是否 active 状态 - this._active = false; - - // 初始化 droplist - this.droplist = new DropList(this, { - width: 120, - $title: $('

      文字颜色

      '), - type: 'inline-block', // droplist 内容以 block 形式展示 - list: colors.map(function (color) { - return { $elem: $(''), value: color }; - }), - onClick: function onClick(value) { - // 注意 this 是指向当前的 ForeColor 对象 - _this._command(value); - } - }); -} - -// 原型 -ForeColor.prototype = { - constructor: ForeColor, - - // 执行命令 - _command: function _command(value) { - var editor = this.editor; - editor.cmd.do('foreColor', value); - } -}; - -/* - menu - BackColor -*/ -// 构造函数 -function BackColor(editor) { - var _this = this; - - this.editor = editor; - this.$elem = $('
      '); - this.type = 'droplist'; - - // 获取配置的颜色 - var config = editor.config; - var colors = config.colors || []; - - // 当前是否 active 状态 - this._active = false; - - // 初始化 droplist - this.droplist = new DropList(this, { - width: 120, - $title: $('

      背景色

      '), - type: 'inline-block', // droplist 内容以 block 形式展示 - list: colors.map(function (color) { - return { $elem: $(''), value: color }; - }), - onClick: function onClick(value) { - // 注意 this 是指向当前的 BackColor 对象 - _this._command(value); - } - }); -} - -// 原型 -BackColor.prototype = { - constructor: BackColor, - - // 执行命令 - _command: function _command(value) { - var editor = this.editor; - editor.cmd.do('backColor', value); - } -}; - -/* - menu - quote -*/ -// 构造函数 -function Quote(editor) { - this.editor = editor; - this.$elem = $('
      \n \n
      '); - this.type = 'click'; - - // 当前是否 active 状态 - this._active = false; -} - -// 原型 -Quote.prototype = { - constructor: Quote, - - onClick: function onClick(e) { - var editor = this.editor; - var $selectionElem = editor.selection.getSelectionContainerElem(); - var nodeName = $selectionElem.getNodeName(); - - if (!UA.isIE()) { - if (nodeName === 'BLOCKQUOTE') { - // 撤销 quote - editor.cmd.do('formatBlock', '

      '); - } else { - // 转换为 quote - editor.cmd.do('formatBlock', '

      '); - } - return; - } - - // IE 中不支持 formatBlock
      ,要用其他方式兼容 - var content = void 0, - $targetELem = void 0; - if (nodeName === 'P') { - // 将 P 转换为 quote - content = $selectionElem.text(); - $targetELem = $('
      ' + content + '
      '); - $targetELem.insertAfter($selectionElem); - $selectionElem.remove(); - return; - } - if (nodeName === 'BLOCKQUOTE') { - // 撤销 quote - content = $selectionElem.text(); - $targetELem = $('

      ' + content + '

      '); - $targetELem.insertAfter($selectionElem); - $selectionElem.remove(); - } - }, - - tryChangeActive: function tryChangeActive(e) { - var editor = this.editor; - var $elem = this.$elem; - var reg = /^BLOCKQUOTE$/i; - var cmdValue = editor.cmd.queryCommandValue('formatBlock'); - if (reg.test(cmdValue)) { - this._active = true; - $elem.addClass('w-e-active'); - } else { - this._active = false; - $elem.removeClass('w-e-active'); - } - } -}; - -/* - menu - code -*/ -// 构造函数 -function Code(editor) { - this.editor = editor; - this.$elem = $('
      \n \n
      '); - this.type = 'panel'; - - // 当前是否 active 状态 - this._active = false; -} - -// 原型 -Code.prototype = { - constructor: Code, - - onClick: function onClick(e) { - var editor = this.editor; - var $startElem = editor.selection.getSelectionStartElem(); - var $endElem = editor.selection.getSelectionEndElem(); - var isSeleEmpty = editor.selection.isSelectionEmpty(); - var selectionText = editor.selection.getSelectionText(); - var $code = void 0; - - if (!$startElem.equal($endElem)) { - // 跨元素选择,不做处理 - editor.selection.restoreSelection(); - return; - } - if (!isSeleEmpty) { - // 选取不是空,用 包裹即可 - $code = $('' + selectionText + ''); - editor.cmd.do('insertElem', $code); - editor.selection.createRangeByElem($code, false); - editor.selection.restoreSelection(); - return; - } - - // 选取是空,且没有夸元素选择,则插入
      
      -        if (this._active) {
      -            // 选中状态,将编辑内容
      -            this._createPanel($startElem.html());
      -        } else {
      -            // 未选中状态,将创建内容
      -            this._createPanel();
      -        }
      -    },
      -
      -    _createPanel: function _createPanel(value) {
      -        var _this = this;
      -
      -        // value - 要编辑的内容
      -        value = value || '';
      -        var type = !value ? 'new' : 'edit';
      -        var textId = getRandom('texxt');
      -        var btnId = getRandom('btn');
      -
      -        var panel = new Panel(this, {
      -            width: 500,
      -            // 一个 Panel 包含多个 tab
      -            tabs: [{
      -                // 标题
      -                title: '插入代码',
      -                // 模板
      -                tpl: '
      \n \n
      \n \n
      \n
      ', - // 事件绑定 - events: [ - // 插入代码 - { - selector: '#' + btnId, - type: 'click', - fn: function fn() { - var $text = $('#' + textId); - var text = $text.val() || $text.html(); - text = replaceHtmlSymbol(text); - if (type === 'new') { - // 新插入 - _this._insertCode(text); - } else { - // 编辑更新 - _this._updateCode(text); - } - - // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 - return true; - } - }] - } // first tab end - ] // tabs end - }); // new Panel end - - // 显示 panel - panel.show(); - - // 记录属性 - this.panel = panel; - }, - - // 插入代码 - _insertCode: function _insertCode(value) { - var editor = this.editor; - editor.cmd.do('insertHTML', '
      ' + value + '


      '); - }, - - // 更新代码 - _updateCode: function _updateCode(value) { - var editor = this.editor; - var $selectionELem = editor.selection.getSelectionContainerElem(); - if (!$selectionELem) { - return; - } - $selectionELem.html(value); - editor.selection.restoreSelection(); - }, - - // 试图改变 active 状态 - tryChangeActive: function tryChangeActive(e) { - var editor = this.editor; - var $elem = this.$elem; - var $selectionELem = editor.selection.getSelectionContainerElem(); - if (!$selectionELem) { - return; - } - var $parentElem = $selectionELem.parent(); - if ($selectionELem.getNodeName() === 'CODE' && $parentElem.getNodeName() === 'PRE') { - this._active = true; - $elem.addClass('w-e-active'); - } else { - this._active = false; - $elem.removeClass('w-e-active'); - } - } -}; - -/* - menu - emoticon -*/ -// 构造函数 -function Emoticon(editor) { - this.editor = editor; - this.$elem = $('
      \n \n
      '); - this.type = 'panel'; - - // 当前是否 active 状态 - this._active = false; -} - -// 原型 -Emoticon.prototype = { - constructor: Emoticon, - - onClick: function onClick() { - this._createPanel(); - }, - - _createPanel: function _createPanel() { - var _this = this; - - var editor = this.editor; - var config = editor.config; - // 获取表情配置 - var emotions = config.emotions || []; - - // 创建表情 dropPanel 的配置 - var tabConfig = []; - emotions.forEach(function (emotData) { - var emotType = emotData.type; - var content = emotData.content || []; - - // 这一组表情最终拼接出来的 html - var faceHtml = ''; - - // emoji 表情 - if (emotType === 'emoji') { - content.forEach(function (item) { - if (item) { - faceHtml += '' + item + ''; - } - }); - } - // 图片表情 - if (emotType === 'image') { - content.forEach(function (item) { - var src = item.src; - var alt = item.alt; - if (src) { - // 加一个 data-w-e 属性,点击图片的时候不再提示编辑图片 - faceHtml += '' + alt + ''; - } - }); - } - - tabConfig.push({ - title: emotData.title, - tpl: '
      ' + faceHtml + '
      ', - events: [{ - selector: 'span.w-e-item', - type: 'click', - fn: function fn(e) { - var target = e.target; - var $target = $(target); - var nodeName = $target.getNodeName(); - - var insertHtml = void 0; - if (nodeName === 'IMG') { - // 插入图片 - insertHtml = $target.parent().html(); - } else { - // 插入 emoji - insertHtml = '' + $target.html() + ''; - } - - _this._insert(insertHtml); - // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 - return true; - } - }] - }); - }); - - var panel = new Panel(this, { - width: 300, - height: 200, - // 一个 Panel 包含多个 tab - tabs: tabConfig - }); - - // 显示 panel - panel.show(); - - // 记录属性 - this.panel = panel; - }, - - // 插入表情 - _insert: function _insert(emotHtml) { - var editor = this.editor; - editor.cmd.do('insertHTML', emotHtml); - } -}; - -/* - menu - table -*/ -// 构造函数 -function Table(editor) { - this.editor = editor; - this.$elem = $('
      '); - this.type = 'panel'; - - // 当前是否 active 状态 - this._active = false; -} - -// 原型 -Table.prototype = { - constructor: Table, - - onClick: function onClick() { - if (this._active) { - // 编辑现有表格 - this._createEditPanel(); - } else { - // 插入新表格 - this._createInsertPanel(); - } - }, - - // 创建插入新表格的 panel - _createInsertPanel: function _createInsertPanel() { - var _this = this; - - // 用到的 id - var btnInsertId = getRandom('btn'); - var textRowNum = getRandom('row'); - var textColNum = getRandom('col'); - - var panel = new Panel(this, { - width: 250, - // panel 包含多个 tab - tabs: [{ - // 标题 - title: '插入表格', - // 模板 - tpl: '
      \n

      \n \u521B\u5EFA\n \n \u884C\n \n \u5217\u7684\u8868\u683C\n

      \n
      \n \n
      \n
      ', - // 事件绑定 - events: [{ - // 点击按钮,插入表格 - selector: '#' + btnInsertId, - type: 'click', - fn: function fn() { - var rowNum = parseInt($('#' + textRowNum).val()); - var colNum = parseInt($('#' + textColNum).val()); - - if (rowNum && colNum && rowNum > 0 && colNum > 0) { - // form 数据有效 - _this._insert(rowNum, colNum); - } - - // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 - return true; - } - }] - } // first tab end - ] // tabs end - }); // panel end - - // 展示 panel - panel.show(); - - // 记录属性 - this.panel = panel; - }, - - // 插入表格 - _insert: function _insert(rowNum, colNum) { - // 拼接 table 模板 - var r = void 0, - c = void 0; - var html = '
      '; - for (r = 0; r < rowNum; r++) { - html += ''; - if (r === 0) { - for (c = 0; c < colNum; c++) { - html += ''; - } - } else { - for (c = 0; c < colNum; c++) { - html += ''; - } - } - html += ''; - } - html += '
        


      '; - - // 执行命令 - var editor = this.editor; - editor.cmd.do('insertHTML', html); - - // 防止 firefox 下出现 resize 的控制点 - editor.cmd.do('enableObjectResizing', false); - editor.cmd.do('enableInlineTableEditing', false); - }, - - // 创建编辑表格的 panel - _createEditPanel: function _createEditPanel() { - var _this2 = this; - - // 可用的 id - var addRowBtnId = getRandom('add-row'); - var addColBtnId = getRandom('add-col'); - var delRowBtnId = getRandom('del-row'); - var delColBtnId = getRandom('del-col'); - var delTableBtnId = getRandom('del-table'); - - // 创建 panel 对象 - var panel = new Panel(this, { - width: 320, - // panel 包含多个 tab - tabs: [{ - // 标题 - title: '编辑表格', - // 模板 - tpl: '
      \n
      \n \n \n \n \n
      \n
      \n \n \n
      ', - // 事件绑定 - events: [{ - // 增加行 - selector: '#' + addRowBtnId, - type: 'click', - fn: function fn() { - _this2._addRow(); - // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 - return true; - } - }, { - // 增加列 - selector: '#' + addColBtnId, - type: 'click', - fn: function fn() { - _this2._addCol(); - // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 - return true; - } - }, { - // 删除行 - selector: '#' + delRowBtnId, - type: 'click', - fn: function fn() { - _this2._delRow(); - // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 - return true; - } - }, { - // 删除列 - selector: '#' + delColBtnId, - type: 'click', - fn: function fn() { - _this2._delCol(); - // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 - return true; - } - }, { - // 删除表格 - selector: '#' + delTableBtnId, - type: 'click', - fn: function fn() { - _this2._delTable(); - // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 - return true; - } - }] - }] - }); - // 显示 panel - panel.show(); - }, - - // 获取选中的单元格的位置信息 - _getLocationData: function _getLocationData() { - var result = {}; - var editor = this.editor; - var $selectionELem = editor.selection.getSelectionContainerElem(); - if (!$selectionELem) { - return; - } - var nodeName = $selectionELem.getNodeName(); - if (nodeName !== 'TD' && nodeName !== 'TH') { - return; - } - - // 获取 td index - var $tr = $selectionELem.parent(); - var $tds = $tr.children(); - var tdLength = $tds.length; - $tds.forEach(function (td, index) { - if (td === $selectionELem[0]) { - // 记录并跳出循环 - result.td = { - index: index, - elem: td, - length: tdLength - }; - return false; - } - }); - - // 获取 tr index - var $tbody = $tr.parent(); - var $trs = $tbody.children(); - var trLength = $trs.length; - $trs.forEach(function (tr, index) { - if (tr === $tr[0]) { - // 记录并跳出循环 - result.tr = { - index: index, - elem: tr, - length: trLength - }; - return false; - } - }); - - // 返回结果 - return result; - }, - - // 增加行 - _addRow: function _addRow() { - // 获取当前单元格的位置信息 - var locationData = this._getLocationData(); - if (!locationData) { - return; - } - var trData = locationData.tr; - var $currentTr = $(trData.elem); - var tdData = locationData.td; - var tdLength = tdData.length; - - // 拼接即将插入的字符串 - var newTr = document.createElement('tr'); - var tpl = '', - i = void 0; - for (i = 0; i < tdLength; i++) { - tpl += ' '; - } - newTr.innerHTML = tpl; - // 插入 - $(newTr).insertAfter($currentTr); - }, - - // 增加列 - _addCol: function _addCol() { - // 获取当前单元格的位置信息 - var locationData = this._getLocationData(); - if (!locationData) { - return; - } - var trData = locationData.tr; - var tdData = locationData.td; - var tdIndex = tdData.index; - var $currentTr = $(trData.elem); - var $trParent = $currentTr.parent(); - var $trs = $trParent.children(); - - // 遍历所有行 - $trs.forEach(function (tr) { - var $tr = $(tr); - var $tds = $tr.children(); - var $currentTd = $tds.get(tdIndex); - var name = $currentTd.getNodeName().toLowerCase(); - - // new 一个 td,并插入 - var newTd = document.createElement(name); - $(newTd).insertAfter($currentTd); - }); - }, - - // 删除行 - _delRow: function _delRow() { - // 获取当前单元格的位置信息 - var locationData = this._getLocationData(); - if (!locationData) { - return; - } - var trData = locationData.tr; - var $currentTr = $(trData.elem); - $currentTr.remove(); - }, - - // 删除列 - _delCol: function _delCol() { - // 获取当前单元格的位置信息 - var locationData = this._getLocationData(); - if (!locationData) { - return; - } - var trData = locationData.tr; - var tdData = locationData.td; - var tdIndex = tdData.index; - var $currentTr = $(trData.elem); - var $trParent = $currentTr.parent(); - var $trs = $trParent.children(); - - // 遍历所有行 - $trs.forEach(function (tr) { - var $tr = $(tr); - var $tds = $tr.children(); - var $currentTd = $tds.get(tdIndex); - // 删除 - $currentTd.remove(); - }); - }, - - // 删除表格 - _delTable: function _delTable() { - var editor = this.editor; - var $selectionELem = editor.selection.getSelectionContainerElem(); - if (!$selectionELem) { - return; - } - var $table = $selectionELem.parentUntil('table'); - if (!$table) { - return; - } - $table.remove(); - }, - - // 试图改变 active 状态 - tryChangeActive: function tryChangeActive(e) { - var editor = this.editor; - var $elem = this.$elem; - var $selectionELem = editor.selection.getSelectionContainerElem(); - if (!$selectionELem) { - return; - } - var nodeName = $selectionELem.getNodeName(); - if (nodeName === 'TD' || nodeName === 'TH') { - this._active = true; - $elem.addClass('w-e-active'); - } else { - this._active = false; - $elem.removeClass('w-e-active'); - } - } -}; - -/* - menu - video -*/ -// 构造函数 -function Video(editor) { - this.editor = editor; - this.$elem = $('
      '); - this.type = 'panel'; - - // 当前是否 active 状态 - this._active = false; -} - -// 原型 -Video.prototype = { - constructor: Video, - - onClick: function onClick() { - this._createPanel(); - }, - - _createPanel: function _createPanel() { - var _this = this; - - // 创建 id - var textValId = getRandom('text-val'); - var btnId = getRandom('btn'); - - // 创建 panel - var panel = new Panel(this, { - width: 350, - // 一个 panel 多个 tab - tabs: [{ - // 标题 - title: '插入视频', - // 模板 - tpl: '
      \n \n
      \n \n
      \n
      ', - // 事件绑定 - events: [{ - selector: '#' + btnId, - type: 'click', - fn: function fn() { - var $text = $('#' + textValId); - var val = $text.val().trim(); - - // 测试用视频地址 - // - - if (val) { - // 插入视频 - _this._insert(val); - } - - // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 - return true; - } - }] - } // first tab end - ] // tabs end - }); // panel end - - // 显示 panel - panel.show(); - - // 记录属性 - this.panel = panel; - }, - - // 插入视频 - _insert: function _insert(val) { - var editor = this.editor; - editor.cmd.do('insertHTML', val + '


      '); - } -}; - -/* - menu - img -*/ -// 构造函数 -function Image(editor) { - this.editor = editor; - var imgMenuId = getRandom('w-e-img'); - this.$elem = $('
      '); - editor.imgMenuId = imgMenuId; - this.type = 'panel'; - - // 当前是否 active 状态 - this._active = false; -} - -// 原型 -Image.prototype = { - constructor: Image, - - onClick: function onClick() { - var editor = this.editor; - var config = editor.config; - if (config.qiniu) { - return; - } - if (this._active) { - this._createEditPanel(); - } else { - this._createInsertPanel(); - } - }, - - _createEditPanel: function _createEditPanel() { - var editor = this.editor; - - // id - var width30 = getRandom('width-30'); - var width50 = getRandom('width-50'); - var width100 = getRandom('width-100'); - var delBtn = getRandom('del-btn'); - - // tab 配置 - var tabsConfig = [{ - title: '编辑图片', - tpl: '
      \n
      \n \u6700\u5927\u5BBD\u5EA6\uFF1A\n \n \n \n
      \n
      \n \n \n
      ', - events: [{ - selector: '#' + width30, - type: 'click', - fn: function fn() { - var $img = editor._selectedImg; - if ($img) { - $img.css('max-width', '30%'); - } - // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 - return true; - } - }, { - selector: '#' + width50, - type: 'click', - fn: function fn() { - var $img = editor._selectedImg; - if ($img) { - $img.css('max-width', '50%'); - } - // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 - return true; - } - }, { - selector: '#' + width100, - type: 'click', - fn: function fn() { - var $img = editor._selectedImg; - if ($img) { - $img.css('max-width', '100%'); - } - // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 - return true; - } - }, { - selector: '#' + delBtn, - type: 'click', - fn: function fn() { - var $img = editor._selectedImg; - if ($img) { - $img.remove(); - } - // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 - return true; - } - }] - }]; - - // 创建 panel 并显示 - var panel = new Panel(this, { - width: 300, - tabs: tabsConfig - }); - panel.show(); - - // 记录属性 - this.panel = panel; - }, - - _createInsertPanel: function _createInsertPanel() { - var editor = this.editor; - var uploadImg = editor.uploadImg; - var config = editor.config; - - // id - var upTriggerId = getRandom('up-trigger'); - var upFileId = getRandom('up-file'); - var linkUrlId = getRandom('link-url'); - var linkBtnId = getRandom('link-btn'); - - // tabs 的配置 - var tabsConfig = [{ - title: '上传图片', - tpl: '
      \n
      \n \n
      \n
      \n \n
      \n
      ', - events: [{ - // 触发选择图片 - selector: '#' + upTriggerId, - type: 'click', - fn: function fn() { - var $file = $('#' + upFileId); - var fileElem = $file[0]; - if (fileElem) { - fileElem.click(); - } else { - // 返回 true 可关闭 panel - return true; - } - } - }, { - // 选择图片完毕 - selector: '#' + upFileId, - type: 'change', - fn: function fn() { - var $file = $('#' + upFileId); - var fileElem = $file[0]; - if (!fileElem) { - // 返回 true 可关闭 panel - return true; - } - - // 获取选中的 file 对象列表 - var fileList = fileElem.files; - if (fileList.length) { - uploadImg.uploadImg(fileList); - } - - // 返回 true 可关闭 panel - return true; - } - }] - }, // first tab end - { - title: '网络图片', - tpl: '
      \n \n
      \n \n
      \n
      ', - events: [{ - selector: '#' + linkBtnId, - type: 'click', - fn: function fn() { - var $linkUrl = $('#' + linkUrlId); - var url = $linkUrl.val().trim(); - - if (url) { - uploadImg.insertLinkImg(url); - } - - // 返回 true 表示函数执行结束之后关闭 panel - return true; - } - }] - } // second tab end - ]; // tabs end - - // 判断 tabs 的显示 - var tabsConfigResult = []; - if ((config.uploadImgShowBase64 || config.uploadImgServer || config.customUploadImg) && window.FileReader) { - // 显示“上传图片” - tabsConfigResult.push(tabsConfig[0]); - } - if (config.showLinkImg) { - // 显示“网络图片” - tabsConfigResult.push(tabsConfig[1]); - } - - // 创建 panel 并显示 - var panel = new Panel(this, { - width: 300, - tabs: tabsConfigResult - }); - panel.show(); - - // 记录属性 - this.panel = panel; - }, - - // 试图改变 active 状态 - tryChangeActive: function tryChangeActive(e) { - var editor = this.editor; - var $elem = this.$elem; - if (editor._selectedImg) { - this._active = true; - $elem.addClass('w-e-active'); - } else { - this._active = false; - $elem.removeClass('w-e-active'); - } - } -}; - -/* - 所有菜单的汇总 -*/ - -// 存储菜单的构造函数 -var MenuConstructors = {}; - -MenuConstructors.bold = Bold; - -MenuConstructors.head = Head; - -MenuConstructors.link = Link; - -MenuConstructors.italic = Italic; - -MenuConstructors.redo = Redo; - -MenuConstructors.strikeThrough = StrikeThrough; - -MenuConstructors.underline = Underline; - -MenuConstructors.undo = Undo; - -MenuConstructors.list = List; - -MenuConstructors.justify = Justify; - -MenuConstructors.foreColor = ForeColor; - -MenuConstructors.backColor = BackColor; - -MenuConstructors.quote = Quote; - -MenuConstructors.code = Code; - -MenuConstructors.emoticon = Emoticon; - -MenuConstructors.table = Table; - -MenuConstructors.video = Video; - -MenuConstructors.image = Image; - -/* - 菜单集合 -*/ -// 构造函数 -function Menus(editor) { - this.editor = editor; - this.menus = {}; -} - -// 修改原型 -Menus.prototype = { - constructor: Menus, - - // 初始化菜单 - init: function init() { - var _this = this; - - var editor = this.editor; - var config = editor.config || {}; - var configMenus = config.menus || []; // 获取配置中的菜单 - - // 根据配置信息,创建菜单 - configMenus.forEach(function (menuKey) { - var MenuConstructor = MenuConstructors[menuKey]; - if (MenuConstructor && typeof MenuConstructor === 'function') { - // 创建单个菜单 - _this.menus[menuKey] = new MenuConstructor(editor); - } - }); - - // 添加到菜单栏 - this._addToToolbar(); - - // 绑定事件 - this._bindEvent(); - }, - - // 添加到菜单栏 - _addToToolbar: function _addToToolbar() { - var editor = this.editor; - var $toolbarElem = editor.$toolbarElem; - var menus = this.menus; - var config = editor.config; - // config.zIndex 是配置的编辑区域的 z-index,菜单的 z-index 得在其基础上 +1 - var zIndex = config.zIndex + 1; - objForEach(menus, function (key, menu) { - var $elem = menu.$elem; - if ($elem) { - // 设置 z-index - $elem.css('z-index', zIndex); - $toolbarElem.append($elem); - } - }); - }, - - // 绑定菜单 click mouseenter 事件 - _bindEvent: function _bindEvent() { - var menus = this.menus; - var editor = this.editor; - objForEach(menus, function (key, menu) { - var type = menu.type; - if (!type) { - return; - } - var $elem = menu.$elem; - var droplist = menu.droplist; - var panel = menu.panel; - - // 点击类型,例如 bold - if (type === 'click' && menu.onClick) { - $elem.on('click', function (e) { - if (editor.selection.getRange() == null) { - return; - } - menu.onClick(e); - }); - } - - // 下拉框,例如 head - if (type === 'droplist' && droplist) { - $elem.on('mouseenter', function (e) { - if (editor.selection.getRange() == null) { - return; - } - // 显示 - droplist.showTimeoutId = setTimeout(function () { - droplist.show(); - }, 200); - }).on('mouseleave', function (e) { - // 隐藏 - droplist.hideTimeoutId = setTimeout(function () { - droplist.hide(); - }, 0); - }); - } - - // 弹框类型,例如 link - if (type === 'panel' && menu.onClick) { - $elem.on('click', function (e) { - e.stopPropagation(); - if (editor.selection.getRange() == null) { - return; - } - // 在自定义事件中显示 panel - menu.onClick(e); - }); - } - }); - }, - - // 尝试修改菜单状态 - changeActive: function changeActive() { - var menus = this.menus; - objForEach(menus, function (key, menu) { - if (menu.tryChangeActive) { - setTimeout(function () { - menu.tryChangeActive(); - }, 100); - } - }); - } -}; - -/* - 粘贴信息的处理 -*/ - -// 获取粘贴的纯文本 -function getPasteText(e) { - var clipboardData = e.clipboardData || e.originalEvent && e.originalEvent.clipboardData; - var pasteText = void 0; - if (clipboardData == null) { - pasteText = window.clipboardData && window.clipboardData.getData('text'); - } else { - pasteText = clipboardData.getData('text/plain'); - } - - return replaceHtmlSymbol(pasteText); -} - -// 获取粘贴的html -function getPasteHtml(e, filterStyle) { - var clipboardData = e.clipboardData || e.originalEvent && e.originalEvent.clipboardData; - var pasteText = void 0, - pasteHtml = void 0; - if (clipboardData == null) { - pasteText = window.clipboardData && window.clipboardData.getData('text'); - } else { - pasteText = clipboardData.getData('text/plain'); - pasteHtml = clipboardData.getData('text/html'); - } - if (!pasteHtml && pasteText) { - pasteHtml = '

      ' + replaceHtmlSymbol(pasteText) + '

      '; - } - if (!pasteHtml) { - return; - } - - // 过滤word中状态过来的无用字符 - var docSplitHtml = pasteHtml.split(''); - if (docSplitHtml.length === 2) { - pasteHtml = docSplitHtml[0]; - } - - // 过滤无用标签 - pasteHtml = pasteHtml.replace(/<(meta|script|link).+?>/igm, ''); - // 去掉注释 - pasteHtml = pasteHtml.replace(//mg, ''); - // 过滤 data-xxx 属性 - pasteHtml = pasteHtml.replace(/\s?data-.+?=('|").+?('|")/igm, ''); - - if (filterStyle) { - // 过滤样式 - pasteHtml = pasteHtml.replace(/\s?(class|style)=('|").+?('|")/igm, ''); - } else { - // 保留样式 - pasteHtml = pasteHtml.replace(/\s?class=('|").+?('|")/igm, ''); - } - - return pasteHtml; -} - -// 获取粘贴的图片文件 -function getPasteImgs(e) { - var result = []; - var txt = getPasteText(e); - if (txt) { - // 有文字,就忽略图片 - return result; - } - - var clipboardData = e.clipboardData || e.originalEvent && e.originalEvent.clipboardData || {}; - var items = clipboardData.items; - if (!items) { - return result; - } - - objForEach(items, function (key, value) { - var type = value.type; - if (/image/i.test(type)) { - result.push(value.getAsFile()); - } - }); - - return result; -} - -/* - 编辑区域 -*/ - -// 获取一个 elem.childNodes 的 JSON 数据 -function getChildrenJSON($elem) { - var result = []; - var $children = $elem.childNodes() || []; // 注意 childNodes() 可以获取文本节点 - $children.forEach(function (curElem) { - var elemResult = void 0; - var nodeType = curElem.nodeType; - - // 文本节点 - if (nodeType === 3) { - elemResult = curElem.textContent; - } - - // 普通 DOM 节点 - if (nodeType === 1) { - elemResult = {}; - - // tag - elemResult.tag = curElem.nodeName.toLowerCase(); - // attr - var attrData = []; - var attrList = curElem.attributes || {}; - var attrListLength = attrList.length || 0; - for (var i = 0; i < attrListLength; i++) { - var attr = attrList[i]; - attrData.push({ - name: attr.name, - value: attr.value - }); - } - elemResult.attrs = attrData; - // children(递归) - elemResult.children = getChildrenJSON($(curElem)); - } - - result.push(elemResult); - }); - return result; -} - -// 构造函数 -function Text(editor) { - this.editor = editor; -} - -// 修改原型 -Text.prototype = { - constructor: Text, - - // 初始化 - init: function init() { - // 绑定事件 - this._bindEvent(); - }, - - // 清空内容 - clear: function clear() { - this.html('


      '); - }, - - // 获取 设置 html - html: function html(val) { - var editor = this.editor; - var $textElem = editor.$textElem; - var html = void 0; - if (val == null) { - html = $textElem.html(); - // 未选中任何内容的时候点击“加粗”或者“斜体”等按钮,就得需要一个空的占位符 ​ ,这里替换掉 - html = html.replace(/\u200b/gm, ''); - return html; - } else { - $textElem.html(val); - - // 初始化选取,将光标定位到内容尾部 - editor.initSelection(); - } - }, - - // 获取 JSON - getJSON: function getJSON() { - var editor = this.editor; - var $textElem = editor.$textElem; - return getChildrenJSON($textElem); - }, - - // 获取 设置 text - text: function text(val) { - var editor = this.editor; - var $textElem = editor.$textElem; - var text = void 0; - if (val == null) { - text = $textElem.text(); - // 未选中任何内容的时候点击“加粗”或者“斜体”等按钮,就得需要一个空的占位符 ​ ,这里替换掉 - text = text.replace(/\u200b/gm, ''); - return text; - } else { - $textElem.text('

      ' + val + '

      '); - - // 初始化选取,将光标定位到内容尾部 - editor.initSelection(); - } - }, - - // 追加内容 - append: function append(html) { - var editor = this.editor; - var $textElem = editor.$textElem; - $textElem.append($(html)); - - // 初始化选取,将光标定位到内容尾部 - editor.initSelection(); - }, - - // 绑定事件 - _bindEvent: function _bindEvent() { - // 实时保存选取 - this._saveRangeRealTime(); - - // 按回车建时的特殊处理 - this._enterKeyHandle(); - - // 清空时保留


      - this._clearHandle(); - - // 粘贴事件(粘贴文字,粘贴图片) - this._pasteHandle(); - - // tab 特殊处理 - this._tabHandle(); - - // img 点击 - this._imgHandle(); - - // 拖拽事件 - this._dragHandle(); - }, - - // 实时保存选取 - _saveRangeRealTime: function _saveRangeRealTime() { - var editor = this.editor; - var $textElem = editor.$textElem; - - // 保存当前的选区 - function saveRange(e) { - // 随时保存选区 - editor.selection.saveRange(); - // 更新按钮 ative 状态 - editor.menus.changeActive(); - } - // 按键后保存 - $textElem.on('keyup', saveRange); - $textElem.on('mousedown', function (e) { - // mousedown 状态下,鼠标滑动到编辑区域外面,也需要保存选区 - $textElem.on('mouseleave', saveRange); - }); - $textElem.on('mouseup', function (e) { - saveRange(); - // 在编辑器区域之内完成点击,取消鼠标滑动到编辑区外面的事件 - $textElem.off('mouseleave', saveRange); - }); - }, - - // 按回车键时的特殊处理 - _enterKeyHandle: function _enterKeyHandle() { - var editor = this.editor; - var $textElem = editor.$textElem; - - function insertEmptyP($selectionElem) { - var $p = $('


      '); - $p.insertBefore($selectionElem); - editor.selection.createRangeByElem($p, true); - editor.selection.restoreSelection(); - $selectionElem.remove(); - } - - // 将回车之后生成的非

      的顶级标签,改为

      - function pHandle(e) { - var $selectionElem = editor.selection.getSelectionContainerElem(); - var $parentElem = $selectionElem.parent(); - - if ($parentElem.html() === '
      ') { - // 回车之前光标所在一个

      .....

      ,忽然回车生成一个空的


      - // 而且继续回车跳不出去,因此只能特殊处理 - insertEmptyP($selectionElem); - return; - } - - if (!$parentElem.equal($textElem)) { - // 不是顶级标签 - return; - } - - var nodeName = $selectionElem.getNodeName(); - if (nodeName === 'P') { - // 当前的标签是 P ,不用做处理 - return; - } - - if ($selectionElem.text()) { - // 有内容,不做处理 - return; - } - - // 插入

      ,并将选取定位到

      ,删除当前标签 - insertEmptyP($selectionElem); - } - - $textElem.on('keyup', function (e) { - if (e.keyCode !== 13) { - // 不是回车键 - return; - } - // 将回车之后生成的非

      的顶级标签,改为

      - pHandle(e); - }); - - //

      回车时 特殊处理 - function codeHandle(e) { - var $selectionElem = editor.selection.getSelectionContainerElem(); - if (!$selectionElem) { - return; - } - var $parentElem = $selectionElem.parent(); - var selectionNodeName = $selectionElem.getNodeName(); - var parentNodeName = $parentElem.getNodeName(); - - if (selectionNodeName !== 'CODE' || parentNodeName !== 'PRE') { - // 不符合要求 忽略 - return; - } - - if (!editor.cmd.queryCommandSupported('insertHTML')) { - // 必须原生支持 insertHTML 命令 - return; - } - - // 处理:光标定位到代码末尾,联系点击两次回车,即跳出代码块 - if (editor._willBreakCode === true) { - // 此时可以跳出代码块 - // 插入

      ,并将选取定位到

      - var $p = $('


      '); - $p.insertAfter($parentElem); - editor.selection.createRangeByElem($p, true); - editor.selection.restoreSelection(); - - // 修改状态 - editor._willBreakCode = false; - - e.preventDefault(); - return; - } - - var _startOffset = editor.selection.getRange().startOffset; - - // 处理:回车时,不能插入
      而是插入 \n ,因为是在 pre 标签里面 - editor.cmd.do('insertHTML', '\n'); - editor.selection.saveRange(); - if (editor.selection.getRange().startOffset === _startOffset) { - // 没起作用,再来一遍 - editor.cmd.do('insertHTML', '\n'); - } - - var codeLength = $selectionElem.html().length; - if (editor.selection.getRange().startOffset + 1 === codeLength) { - // 说明光标在代码最后的位置,执行了回车操作 - // 记录下来,以便下次回车时候跳出 code - editor._willBreakCode = true; - } - - // 阻止默认行为 - e.preventDefault(); - } - - $textElem.on('keydown', function (e) { - if (e.keyCode !== 13) { - // 不是回车键 - // 取消即将跳转代码块的记录 - editor._willBreakCode = false; - return; - } - //
      回车时 特殊处理 - codeHandle(e); - }); - }, - - // 清空时保留


      - _clearHandle: function _clearHandle() { - var editor = this.editor; - var $textElem = editor.$textElem; - - $textElem.on('keydown', function (e) { - if (e.keyCode !== 8) { - return; - } - var txtHtml = $textElem.html().toLowerCase().trim(); - if (txtHtml === '


      ') { - // 最后剩下一个空行,就不再删除了 - e.preventDefault(); - return; - } - }); - - $textElem.on('keyup', function (e) { - if (e.keyCode !== 8) { - return; - } - var $p = void 0; - var txtHtml = $textElem.html().toLowerCase().trim(); - - // firefox 时用 txtHtml === '
      ' 判断,其他用 !txtHtml 判断 - if (!txtHtml || txtHtml === '
      ') { - // 内容空了 - $p = $('


      '); - $textElem.html(''); // 一定要先清空,否则在 firefox 下有问题 - $textElem.append($p); - editor.selection.createRangeByElem($p, false, true); - editor.selection.restoreSelection(); - } - }); - }, - - // 粘贴事件(粘贴文字 粘贴图片) - _pasteHandle: function _pasteHandle() { - var editor = this.editor; - var config = editor.config; - var pasteFilterStyle = config.pasteFilterStyle; - var pasteTextHandle = config.pasteTextHandle; - var $textElem = editor.$textElem; - - // 粘贴图片、文本的事件,每次只能执行一个 - // 判断该次粘贴事件是否可以执行 - var pasteTime = 0; - function canDo() { - var now = Date.now(); - var flag = false; - if (now - pasteTime >= 500) { - // 间隔大于 500 ms ,可以执行 - flag = true; - } - pasteTime = now; - return flag; - } - function resetTime() { - pasteTime = 0; - } - - // 粘贴文字 - $textElem.on('paste', function (e) { - if (UA.isIE()) { - return; - } else { - // 阻止默认行为,使用 execCommand 的粘贴命令 - e.preventDefault(); - } - - // 粘贴图片和文本,只能同时使用一个 - if (!canDo()) { - return; - } - - // 获取粘贴的文字 - var pasteHtml = getPasteHtml(e, pasteFilterStyle); - var pasteText = getPasteText(e); - pasteText = pasteText.replace(/\n/gm, '
      '); - - var $selectionElem = editor.selection.getSelectionContainerElem(); - if (!$selectionElem) { - return; - } - var nodeName = $selectionElem.getNodeName(); - - // code 中只能粘贴纯文本 - if (nodeName === 'CODE' || nodeName === 'PRE') { - if (pasteTextHandle && isFunction(pasteTextHandle)) { - // 用户自定义过滤处理粘贴内容 - pasteText = '' + (pasteTextHandle(pasteText) || ''); - } - editor.cmd.do('insertHTML', '

      ' + pasteText + '

      '); - return; - } - - // 先放开注释,有问题再追查 ———— - // // 表格中忽略,可能会出现异常问题 - // if (nodeName === 'TD' || nodeName === 'TH') { - // return - // } - - if (!pasteHtml) { - // 没有内容,可继续执行下面的图片粘贴 - resetTime(); - return; - } - try { - // firefox 中,获取的 pasteHtml 可能是没有
        包裹的
      • - // 因此执行 insertHTML 会报错 - if (pasteTextHandle && isFunction(pasteTextHandle)) { - // 用户自定义过滤处理粘贴内容 - pasteHtml = '' + (pasteTextHandle(pasteHtml) || ''); - } - editor.cmd.do('insertHTML', pasteHtml); - } catch (ex) { - // 此时使用 pasteText 来兼容一下 - if (pasteTextHandle && isFunction(pasteTextHandle)) { - // 用户自定义过滤处理粘贴内容 - pasteText = '' + (pasteTextHandle(pasteText) || ''); - } - editor.cmd.do('insertHTML', '

        ' + pasteText + '

        '); - } - }); - - // 粘贴图片 - $textElem.on('paste', function (e) { - if (UA.isIE()) { - return; - } else { - e.preventDefault(); - } - - // 粘贴图片和文本,只能同时使用一个 - if (!canDo()) { - return; - } - - // 获取粘贴的图片 - var pasteFiles = getPasteImgs(e); - if (!pasteFiles || !pasteFiles.length) { - return; - } - - // 获取当前的元素 - var $selectionElem = editor.selection.getSelectionContainerElem(); - if (!$selectionElem) { - return; - } - var nodeName = $selectionElem.getNodeName(); - - // code 中粘贴忽略 - if (nodeName === 'CODE' || nodeName === 'PRE') { - return; - } - - // 上传图片 - var uploadImg = editor.uploadImg; - uploadImg.uploadImg(pasteFiles); - }); - }, - - // tab 特殊处理 - _tabHandle: function _tabHandle() { - var editor = this.editor; - var $textElem = editor.$textElem; - - $textElem.on('keydown', function (e) { - if (e.keyCode !== 9) { - return; - } - if (!editor.cmd.queryCommandSupported('insertHTML')) { - // 必须原生支持 insertHTML 命令 - return; - } - var $selectionElem = editor.selection.getSelectionContainerElem(); - if (!$selectionElem) { - return; - } - var $parentElem = $selectionElem.parent(); - var selectionNodeName = $selectionElem.getNodeName(); - var parentNodeName = $parentElem.getNodeName(); - - if (selectionNodeName === 'CODE' && parentNodeName === 'PRE') { - //
         里面
        -                editor.cmd.do('insertHTML', '    ');
        -            } else {
        -                // 普通文字
        -                editor.cmd.do('insertHTML', '    ');
        -            }
        -
        -            e.preventDefault();
        -        });
        -    },
        -
        -    // img 点击
        -    _imgHandle: function _imgHandle() {
        -        var editor = this.editor;
        -        var $textElem = editor.$textElem;
        -
        -        // 为图片增加 selected 样式
        -        $textElem.on('click', 'img', function (e) {
        -            var img = this;
        -            var $img = $(img);
        -
        -            if ($img.attr('data-w-e') === '1') {
        -                // 是表情图片,忽略
        -                return;
        -            }
        -
        -            // 记录当前点击过的图片
        -            editor._selectedImg = $img;
        -
        -            // 修改选区并 restore ,防止用户此时点击退格键,会删除其他内容
        -            editor.selection.createRangeByElem($img);
        -            editor.selection.restoreSelection();
        -        });
        -
        -        // 去掉图片的 selected 样式
        -        $textElem.on('click  keyup', function (e) {
        -            if (e.target.matches('img')) {
        -                // 点击的是图片,忽略
        -                return;
        -            }
        -            // 删除记录
        -            editor._selectedImg = null;
        -        });
        -    },
        -
        -    // 拖拽事件
        -    _dragHandle: function _dragHandle() {
        -        var editor = this.editor;
        -
        -        // 禁用 document 拖拽事件
        -        var $document = $(document);
        -        $document.on('dragleave drop dragenter dragover', function (e) {
        -            e.preventDefault();
        -        });
        -
        -        // 添加编辑区域拖拽事件
        -        var $textElem = editor.$textElem;
        -        $textElem.on('drop', function (e) {
        -            e.preventDefault();
        -            var files = e.dataTransfer && e.dataTransfer.files;
        -            if (!files || !files.length) {
        -                return;
        -            }
        -
        -            // 上传图片
        -            var uploadImg = editor.uploadImg;
        -            uploadImg.uploadImg(files);
        -        });
        -    }
        -};
        -
        -/*
        -    命令,封装 document.execCommand
        -*/
        -
        -// 构造函数
        -function Command(editor) {
        -    this.editor = editor;
        -}
        -
        -// 修改原型
        -Command.prototype = {
        -    constructor: Command,
        -
        -    // 执行命令
        -    do: function _do(name, value) {
        -        var editor = this.editor;
        -
        -        // 使用 styleWithCSS
        -        if (!editor._useStyleWithCSS) {
        -            document.execCommand('styleWithCSS', null, true);
        -            editor._useStyleWithCSS = true;
        -        }
        -
        -        // 如果无选区,忽略
        -        if (!editor.selection.getRange()) {
        -            return;
        -        }
        -
        -        // 恢复选取
        -        editor.selection.restoreSelection();
        -
        -        // 执行
        -        var _name = '_' + name;
        -        if (this[_name]) {
        -            // 有自定义事件
        -            this[_name](value);
        -        } else {
        -            // 默认 command
        -            this._execCommand(name, value);
        -        }
        -
        -        // 修改菜单状态
        -        editor.menus.changeActive();
        -
        -        // 最后,恢复选取保证光标在原来的位置闪烁
        -        editor.selection.saveRange();
        -        editor.selection.restoreSelection();
        -
        -        // 触发 onchange
        -        editor.change && editor.change();
        -    },
        -
        -    // 自定义 insertHTML 事件
        -    _insertHTML: function _insertHTML(html) {
        -        var editor = this.editor;
        -        var range = editor.selection.getRange();
        -
        -        if (this.queryCommandSupported('insertHTML')) {
        -            // W3C
        -            this._execCommand('insertHTML', html);
        -        } else if (range.insertNode) {
        -            // IE
        -            range.deleteContents();
        -            range.insertNode($(html)[0]);
        -        } else if (range.pasteHTML) {
        -            // IE <= 10
        -            range.pasteHTML(html);
        -        }
        -    },
        -
        -    // 插入 elem
        -    _insertElem: function _insertElem($elem) {
        -        var editor = this.editor;
        -        var range = editor.selection.getRange();
        -
        -        if (range.insertNode) {
        -            range.deleteContents();
        -            range.insertNode($elem[0]);
        -        }
        -    },
        -
        -    // 封装 execCommand
        -    _execCommand: function _execCommand(name, value) {
        -        document.execCommand(name, false, value);
        -    },
        -
        -    // 封装 document.queryCommandValue
        -    queryCommandValue: function queryCommandValue(name) {
        -        return document.queryCommandValue(name);
        -    },
        -
        -    // 封装 document.queryCommandState
        -    queryCommandState: function queryCommandState(name) {
        -        return document.queryCommandState(name);
        -    },
        -
        -    // 封装 document.queryCommandSupported
        -    queryCommandSupported: function queryCommandSupported(name) {
        -        return document.queryCommandSupported(name);
        -    }
        -};
        -
        -/*
        -    selection range API
        -*/
        -
        -// 构造函数
        -function API(editor) {
        -    this.editor = editor;
        -    this._currentRange = null;
        -}
        -
        -// 修改原型
        -API.prototype = {
        -    constructor: API,
        -
        -    // 获取 range 对象
        -    getRange: function getRange() {
        -        return this._currentRange;
        -    },
        -
        -    // 保存选区
        -    saveRange: function saveRange(_range) {
        -        if (_range) {
        -            // 保存已有选区
        -            this._currentRange = _range;
        -            return;
        -        }
        -
        -        // 获取当前的选区
        -        var selection = window.getSelection();
        -        if (selection.rangeCount === 0) {
        -            return;
        -        }
        -        var range = selection.getRangeAt(0);
        -
        -        // 判断选区内容是否在编辑内容之内
        -        var $containerElem = this.getSelectionContainerElem(range);
        -        if (!$containerElem) {
        -            return;
        -        }
        -        var editor = this.editor;
        -        var $textElem = editor.$textElem;
        -        if ($textElem.isContain($containerElem)) {
        -            // 是编辑内容之内的
        -            this._currentRange = range;
        -        }
        -    },
        -
        -    // 折叠选区
        -    collapseRange: function collapseRange(toStart) {
        -        if (toStart == null) {
        -            // 默认为 false
        -            toStart = false;
        -        }
        -        var range = this._currentRange;
        -        if (range) {
        -            range.collapse(toStart);
        -        }
        -    },
        -
        -    // 选中区域的文字
        -    getSelectionText: function getSelectionText() {
        -        var range = this._currentRange;
        -        if (range) {
        -            return this._currentRange.toString();
        -        } else {
        -            return '';
        -        }
        -    },
        -
        -    // 选区的 $Elem
        -    getSelectionContainerElem: function getSelectionContainerElem(range) {
        -        range = range || this._currentRange;
        -        var elem = void 0;
        -        if (range) {
        -            elem = range.commonAncestorContainer;
        -            return $(elem.nodeType === 1 ? elem : elem.parentNode);
        -        }
        -    },
        -    getSelectionStartElem: function getSelectionStartElem(range) {
        -        range = range || this._currentRange;
        -        var elem = void 0;
        -        if (range) {
        -            elem = range.startContainer;
        -            return $(elem.nodeType === 1 ? elem : elem.parentNode);
        -        }
        -    },
        -    getSelectionEndElem: function getSelectionEndElem(range) {
        -        range = range || this._currentRange;
        -        var elem = void 0;
        -        if (range) {
        -            elem = range.endContainer;
        -            return $(elem.nodeType === 1 ? elem : elem.parentNode);
        -        }
        -    },
        -
        -    // 选区是否为空
        -    isSelectionEmpty: function isSelectionEmpty() {
        -        var range = this._currentRange;
        -        if (range && range.startContainer) {
        -            if (range.startContainer === range.endContainer) {
        -                if (range.startOffset === range.endOffset) {
        -                    return true;
        -                }
        -            }
        -        }
        -        return false;
        -    },
        -
        -    // 恢复选区
        -    restoreSelection: function restoreSelection() {
        -        var selection = window.getSelection();
        -        selection.removeAllRanges();
        -        selection.addRange(this._currentRange);
        -    },
        -
        -    // 创建一个空白(即 ​ 字符)选区
        -    createEmptyRange: function createEmptyRange() {
        -        var editor = this.editor;
        -        var range = this.getRange();
        -        var $elem = void 0;
        -
        -        if (!range) {
        -            // 当前无 range
        -            return;
        -        }
        -        if (!this.isSelectionEmpty()) {
        -            // 当前选区必须没有内容才可以
        -            return;
        -        }
        -
        -        try {
        -            // 目前只支持 webkit 内核
        -            if (UA.isWebkit()) {
        -                // 插入 ​
        -                editor.cmd.do('insertHTML', '​');
        -                // 修改 offset 位置
        -                range.setEnd(range.endContainer, range.endOffset + 1);
        -                // 存储
        -                this.saveRange(range);
        -            } else {
        -                $elem = $('');
        -                editor.cmd.do('insertElem', $elem);
        -                this.createRangeByElem($elem, true);
        -            }
        -        } catch (ex) {
        -            // 部分情况下会报错,兼容一下
        -        }
        -    },
        -
        -    // 根据 $Elem 设置选区
        -    createRangeByElem: function createRangeByElem($elem, toStart, isContent) {
        -        // $elem - 经过封装的 elem
        -        // toStart - true 开始位置,false 结束位置
        -        // isContent - 是否选中Elem的内容
        -        if (!$elem.length) {
        -            return;
        -        }
        -
        -        var elem = $elem[0];
        -        var range = document.createRange();
        -
        -        if (isContent) {
        -            range.selectNodeContents(elem);
        -        } else {
        -            range.selectNode(elem);
        -        }
        -
        -        if (typeof toStart === 'boolean') {
        -            range.collapse(toStart);
        -        }
        -
        -        // 存储 range
        -        this.saveRange(range);
        -    }
        -};
        -
        -/*
        -    上传进度条
        -*/
        -
        -function Progress(editor) {
        -    this.editor = editor;
        -    this._time = 0;
        -    this._isShow = false;
        -    this._isRender = false;
        -    this._timeoutId = 0;
        -    this.$textContainer = editor.$textContainerElem;
        -    this.$bar = $('
        '); -} - -Progress.prototype = { - constructor: Progress, - - show: function show(progress) { - var _this = this; - - // 状态处理 - if (this._isShow) { - return; - } - this._isShow = true; - - // 渲染 - var $bar = this.$bar; - if (!this._isRender) { - var $textContainer = this.$textContainer; - $textContainer.append($bar); - } else { - this._isRender = true; - } - - // 改变进度(节流,100ms 渲染一次) - if (Date.now() - this._time > 100) { - if (progress <= 1) { - $bar.css('width', progress * 100 + '%'); - this._time = Date.now(); - } - } - - // 隐藏 - var timeoutId = this._timeoutId; - if (timeoutId) { - clearTimeout(timeoutId); - } - timeoutId = setTimeout(function () { - _this._hide(); - }, 500); - }, - - _hide: function _hide() { - var $bar = this.$bar; - $bar.remove(); - - // 修改状态 - this._time = 0; - this._isShow = false; - this._isRender = false; - } -}; - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { - return typeof obj; -} : function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; -}; - -/* - 上传图片 -*/ - -// 构造函数 -function UploadImg(editor) { - this.editor = editor; -} - -// 原型 -UploadImg.prototype = { - constructor: UploadImg, - - // 根据 debug 弹出不同的信息 - _alert: function _alert(alertInfo, debugInfo) { - var editor = this.editor; - var debug = editor.config.debug; - var customAlert = editor.config.customAlert; - - if (debug) { - throw new Error('wangEditor: ' + (debugInfo || alertInfo)); - } else { - if (customAlert && typeof customAlert === 'function') { - customAlert(alertInfo); - } else { - alert(alertInfo); - } - } - }, - - // 根据链接插入图片 - insertLinkImg: function insertLinkImg(link) { - var _this2 = this; - - if (!link) { - return; - } - var editor = this.editor; - var config = editor.config; - - // 校验格式 - var linkImgCheck = config.linkImgCheck; - var checkResult = void 0; - if (linkImgCheck && typeof linkImgCheck === 'function') { - checkResult = linkImgCheck(link); - if (typeof checkResult === 'string') { - // 校验失败,提示信息 - alert(checkResult); - return; - } - } - - editor.cmd.do('insertHTML', ''); - - // 验证图片 url 是否有效,无效的话给出提示 - var img = document.createElement('img'); - img.onload = function () { - var callback = config.linkImgCallback; - if (callback && typeof callback === 'function') { - callback(link); - } - - img = null; - }; - img.onerror = function () { - img = null; - // 无法成功下载图片 - _this2._alert('插入图片错误', 'wangEditor: \u63D2\u5165\u56FE\u7247\u51FA\u9519\uFF0C\u56FE\u7247\u94FE\u63A5\u662F "' + link + '"\uFF0C\u4E0B\u8F7D\u8BE5\u94FE\u63A5\u5931\u8D25'); - return; - }; - img.onabort = function () { - img = null; - }; - img.src = link; - }, - - // 上传图片 - uploadImg: function uploadImg(files) { - var _this3 = this; - - if (!files || !files.length) { - return; - } - - // ------------------------------ 获取配置信息 ------------------------------ - var editor = this.editor; - var config = editor.config; - var uploadImgServer = config.uploadImgServer; - var uploadImgShowBase64 = config.uploadImgShowBase64; - - var maxSize = config.uploadImgMaxSize; - var maxSizeM = maxSize / 1024 / 1024; - var maxLength = config.uploadImgMaxLength || 10000; - var uploadFileName = config.uploadFileName || ''; - var uploadImgParams = config.uploadImgParams || {}; - var uploadImgParamsWithUrl = config.uploadImgParamsWithUrl; - var uploadImgHeaders = config.uploadImgHeaders || {}; - var hooks = config.uploadImgHooks || {}; - var timeout = config.uploadImgTimeout || 3000; - var withCredentials = config.withCredentials; - if (withCredentials == null) { - withCredentials = false; - } - var customUploadImg = config.customUploadImg; - - if (!customUploadImg) { - // 没有 customUploadImg 的情况下,需要如下两个配置才能继续进行图片上传 - if (!uploadImgServer && !uploadImgShowBase64) { - return; - } - } - - // ------------------------------ 验证文件信息 ------------------------------ - var resultFiles = []; - var errInfo = []; - arrForEach(files, function (file) { - var name = file.name; - var size = file.size; - - // chrome 低版本 name === undefined - if (!name || !size) { - return; - } - - if (/\.(jpg|jpeg|png|bmp|gif)$/i.test(name) === false) { - // 后缀名不合法,不是图片 - errInfo.push('\u3010' + name + '\u3011\u4E0D\u662F\u56FE\u7247'); - return; - } - if (maxSize < size) { - // 上传图片过大 - errInfo.push('\u3010' + name + '\u3011\u5927\u4E8E ' + maxSizeM + 'M'); - return; - } - - // 验证通过的加入结果列表 - resultFiles.push(file); - }); - // 抛出验证信息 - if (errInfo.length) { - this._alert('图片验证未通过: \n' + errInfo.join('\n')); - return; - } - if (resultFiles.length > maxLength) { - this._alert('一次最多上传' + maxLength + '张图片'); - return; - } - - // ------------------------------ 自定义上传 ------------------------------ - if (customUploadImg && typeof customUploadImg === 'function') { - customUploadImg(resultFiles, this.insertLinkImg.bind(this)); - - // 阻止以下代码执行 - return; - } - - // 添加图片数据 - var formdata = new FormData(); - arrForEach(resultFiles, function (file) { - var name = uploadFileName || file.name; - formdata.append(name, file); - }); - - // ------------------------------ 上传图片 ------------------------------ - if (uploadImgServer && typeof uploadImgServer === 'string') { - // 添加参数 - var uploadImgServerArr = uploadImgServer.split('#'); - uploadImgServer = uploadImgServerArr[0]; - var uploadImgServerHash = uploadImgServerArr[1] || ''; - objForEach(uploadImgParams, function (key, val) { - val = encodeURIComponent(val); - - // 第一,将参数拼接到 url 中 - if (uploadImgParamsWithUrl) { - if (uploadImgServer.indexOf('?') > 0) { - uploadImgServer += '&'; - } else { - uploadImgServer += '?'; - } - uploadImgServer = uploadImgServer + key + '=' + val; - } - - // 第二,将参数添加到 formdata 中 - formdata.append(key, val); - }); - if (uploadImgServerHash) { - uploadImgServer += '#' + uploadImgServerHash; - } - - // 定义 xhr - var xhr = new XMLHttpRequest(); - xhr.open('POST', uploadImgServer); - - // 设置超时 - xhr.timeout = timeout; - xhr.ontimeout = function () { - // hook - timeout - if (hooks.timeout && typeof hooks.timeout === 'function') { - hooks.timeout(xhr, editor); - } - - _this3._alert('上传图片超时'); - }; - - // 监控 progress - if (xhr.upload) { - xhr.upload.onprogress = function (e) { - var percent = void 0; - // 进度条 - var progressBar = new Progress(editor); - if (e.lengthComputable) { - percent = e.loaded / e.total; - progressBar.show(percent); - } - }; - } - - // 返回数据 - xhr.onreadystatechange = function () { - var result = void 0; - if (xhr.readyState === 4) { - if (xhr.status < 200 || xhr.status >= 300) { - // hook - error - if (hooks.error && typeof hooks.error === 'function') { - hooks.error(xhr, editor); - } - - // xhr 返回状态错误 - _this3._alert('上传图片发生错误', '\u4E0A\u4F20\u56FE\u7247\u53D1\u751F\u9519\u8BEF\uFF0C\u670D\u52A1\u5668\u8FD4\u56DE\u72B6\u6001\u662F ' + xhr.status); - return; - } - - result = xhr.responseText; - if ((typeof result === 'undefined' ? 'undefined' : _typeof(result)) !== 'object') { - try { - result = JSON.parse(result); - } catch (ex) { - // hook - fail - if (hooks.fail && typeof hooks.fail === 'function') { - hooks.fail(xhr, editor, result); - } - - _this3._alert('上传图片失败', '上传图片返回结果错误,返回结果是: ' + result); - return; - } - } - if (!hooks.customInsert && result.errno != '0') { - // hook - fail - if (hooks.fail && typeof hooks.fail === 'function') { - hooks.fail(xhr, editor, result); - } - - // 数据错误 - _this3._alert('上传图片失败', '上传图片返回结果错误,返回结果 errno=' + result.errno); - } else { - if (hooks.customInsert && typeof hooks.customInsert === 'function') { - // 使用者自定义插入方法 - hooks.customInsert(_this3.insertLinkImg.bind(_this3), result, editor); - } else { - // 将图片插入编辑器 - var data = result.data || []; - data.forEach(function (link) { - _this3.insertLinkImg(link); - }); - } - - // hook - success - if (hooks.success && typeof hooks.success === 'function') { - hooks.success(xhr, editor, result); - } - } - } - }; - - // hook - before - if (hooks.before && typeof hooks.before === 'function') { - var beforeResult = hooks.before(xhr, editor, resultFiles); - if (beforeResult && (typeof beforeResult === 'undefined' ? 'undefined' : _typeof(beforeResult)) === 'object') { - if (beforeResult.prevent) { - // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传 - this._alert(beforeResult.msg); - return; - } - } - } - - // 自定义 headers - objForEach(uploadImgHeaders, function (key, val) { - xhr.setRequestHeader(key, val); - }); - - // 跨域传 cookie - xhr.withCredentials = withCredentials; - - // 发送请求 - xhr.send(formdata); - - // 注意,要 return 。不去操作接下来的 base64 显示方式 - return; - } - - // ------------------------------ 显示 base64 格式 ------------------------------ - if (uploadImgShowBase64) { - arrForEach(files, function (file) { - var _this = _this3; - var reader = new FileReader(); - reader.readAsDataURL(file); - reader.onload = function () { - _this.insertLinkImg(this.result); - }; - }); - } - } -}; - -/* - 编辑器构造函数 -*/ - -// id,累加 -var editorId = 1; - -// 构造函数 -function Editor(toolbarSelector, textSelector) { - if (toolbarSelector == null) { - // 没有传入任何参数,报错 - throw new Error('错误:初始化编辑器时候未传入任何参数,请查阅文档'); - } - // id,用以区分单个页面不同的编辑器对象 - this.id = 'wangEditor-' + editorId++; - - this.toolbarSelector = toolbarSelector; - this.textSelector = textSelector; - - // 自定义配置 - this.customConfig = {}; -} - -// 修改原型 -Editor.prototype = { - constructor: Editor, - - // 初始化配置 - _initConfig: function _initConfig() { - // _config 是默认配置,this.customConfig 是用户自定义配置,将它们 merge 之后再赋值 - var target = {}; - this.config = Object.assign(target, config, this.customConfig); - - // 将语言配置,生成正则表达式 - var langConfig = this.config.lang || {}; - var langArgs = []; - objForEach(langConfig, function (key, val) { - // key 即需要生成正则表达式的规则,如“插入链接” - // val 即需要被替换成的语言,如“insert link” - langArgs.push({ - reg: new RegExp(key, 'img'), - val: val - - }); - }); - this.config.langArgs = langArgs; - }, - - // 初始化 DOM - _initDom: function _initDom() { - var _this = this; - - var toolbarSelector = this.toolbarSelector; - var $toolbarSelector = $(toolbarSelector); - var textSelector = this.textSelector; - - var config$$1 = this.config; - var zIndex = config$$1.zIndex; - - // 定义变量 - var $toolbarElem = void 0, - $textContainerElem = void 0, - $textElem = void 0, - $children = void 0; - - if (textSelector == null) { - // 只传入一个参数,即是容器的选择器或元素,toolbar 和 text 的元素自行创建 - $toolbarElem = $('
        '); - $textContainerElem = $('
        '); - - // 将编辑器区域原有的内容,暂存起来 - $children = $toolbarSelector.children(); - - // 添加到 DOM 结构中 - $toolbarSelector.append($toolbarElem).append($textContainerElem); - - // 自行创建的,需要配置默认的样式 - $toolbarElem.css('background-color', '#f1f1f1').css('border', '1px solid #ccc'); - $textContainerElem.css('border', '1px solid #ccc').css('border-top', 'none').css('height', '300px'); - } else { - // toolbar 和 text 的选择器都有值,记录属性 - $toolbarElem = $toolbarSelector; - $textContainerElem = $(textSelector); - // 将编辑器区域原有的内容,暂存起来 - $children = $textContainerElem.children(); - } - - // 编辑区域 - $textElem = $('
        '); - $textElem.attr('contenteditable', 'true').css('width', '100%').css('height', '100%'); - - // 初始化编辑区域内容 - if ($children && $children.length) { - $textElem.append($children); - } else { - $textElem.append($('


        ')); - } - - // 编辑区域加入DOM - $textContainerElem.append($textElem); - - // 设置通用的 class - $toolbarElem.addClass('w-e-toolbar'); - $textContainerElem.addClass('w-e-text-container'); - $textContainerElem.css('z-index', zIndex); - $textElem.addClass('w-e-text'); - - // 添加 ID - var toolbarElemId = getRandom('toolbar-elem'); - $toolbarElem.attr('id', toolbarElemId); - var textElemId = getRandom('text-elem'); - $textElem.attr('id', textElemId); - - // 记录属性 - this.$toolbarElem = $toolbarElem; - this.$textContainerElem = $textContainerElem; - this.$textElem = $textElem; - this.toolbarElemId = toolbarElemId; - this.textElemId = textElemId; - - // 记录输入法的开始和结束 - var compositionEnd = true; - $textContainerElem.on('compositionstart', function () { - // 输入法开始输入 - compositionEnd = false; - }); - $textContainerElem.on('compositionend', function () { - // 输入法结束输入 - compositionEnd = true; - }); - - // 绑定 onchange - $textContainerElem.on('click keyup', function () { - // 输入法结束才出发 onchange - compositionEnd && _this.change && _this.change(); - }); - $toolbarElem.on('click', function () { - this.change && this.change(); - }); - - //绑定 onfocus 与 onblur 事件 - if (config$$1.onfocus || config$$1.onblur) { - // 当前编辑器是否是焦点状态 - this.isFocus = false; - - $(document).on('click', function (e) { - //判断当前点击元素是否在编辑器内 - var isChild = $textElem.isContain($(e.target)); - - //判断当前点击元素是否为工具栏 - var isToolbar = $toolbarElem.isContain($(e.target)); - var isMenu = $toolbarElem[0] == e.target ? true : false; - - if (!isChild) { - //若为选择工具栏中的功能,则不视为成blur操作 - if (isToolbar && !isMenu) { - return; - } - - if (_this.isFocus) { - _this.onblur && _this.onblur(); - } - _this.isFocus = false; - } else { - if (!_this.isFocus) { - _this.onfocus && _this.onfocus(); - } - _this.isFocus = true; - } - }); - } - }, - - // 封装 command - _initCommand: function _initCommand() { - this.cmd = new Command(this); - }, - - // 封装 selection range API - _initSelectionAPI: function _initSelectionAPI() { - this.selection = new API(this); - }, - - // 添加图片上传 - _initUploadImg: function _initUploadImg() { - this.uploadImg = new UploadImg(this); - }, - - // 初始化菜单 - _initMenus: function _initMenus() { - this.menus = new Menus(this); - this.menus.init(); - }, - - // 添加 text 区域 - _initText: function _initText() { - this.txt = new Text(this); - this.txt.init(); - }, - - // 初始化选区,将光标定位到内容尾部 - initSelection: function initSelection(newLine) { - var $textElem = this.$textElem; - var $children = $textElem.children(); - if (!$children.length) { - // 如果编辑器区域无内容,添加一个空行,重新设置选区 - $textElem.append($('


        ')); - this.initSelection(); - return; - } - - var $last = $children.last(); - - if (newLine) { - // 新增一个空行 - var html = $last.html().toLowerCase(); - var nodeName = $last.getNodeName(); - if (html !== '
        ' && html !== '' || nodeName !== 'P') { - // 最后一个元素不是


        ,添加一个空行,重新设置选区 - $textElem.append($('


        ')); - this.initSelection(); - return; - } - } - - this.selection.createRangeByElem($last, false, true); - this.selection.restoreSelection(); - }, - - // 绑定事件 - _bindEvent: function _bindEvent() { - // -------- 绑定 onchange 事件 -------- - var onChangeTimeoutId = 0; - var beforeChangeHtml = this.txt.html(); - var config$$1 = this.config; - - // onchange 触发延迟时间 - var onchangeTimeout = config$$1.onchangeTimeout; - onchangeTimeout = parseInt(onchangeTimeout, 10); - if (!onchangeTimeout || onchangeTimeout <= 0) { - onchangeTimeout = 200; - } - - var onchange = config$$1.onchange; - if (onchange && typeof onchange === 'function') { - // 触发 change 的有三个场景: - // 1. $textContainerElem.on('click keyup') - // 2. $toolbarElem.on('click') - // 3. editor.cmd.do() - this.change = function () { - // 判断是否有变化 - var currentHtml = this.txt.html(); - - if (currentHtml.length === beforeChangeHtml.length) { - // 需要比较每一个字符 - if (currentHtml === beforeChangeHtml) { - return; - } - } - - // 执行,使用节流 - if (onChangeTimeoutId) { - clearTimeout(onChangeTimeoutId); - } - onChangeTimeoutId = setTimeout(function () { - // 触发配置的 onchange 函数 - onchange(currentHtml); - beforeChangeHtml = currentHtml; - }, onchangeTimeout); - }; - } - - // -------- 绑定 onblur 事件 -------- - var onblur = config$$1.onblur; - if (onblur && typeof onblur === 'function') { - this.onblur = function () { - var currentHtml = this.txt.html(); - onblur(currentHtml); - }; - } - - // -------- 绑定 onfocus 事件 -------- - var onfocus = config$$1.onfocus; - if (onfocus && typeof onfocus === 'function') { - this.onfocus = function () { - onfocus(); - }; - } - }, - - // 创建编辑器 - create: function create() { - // 初始化配置信息 - this._initConfig(); - - // 初始化 DOM - this._initDom(); - - // 封装 command API - this._initCommand(); - - // 封装 selection range API - this._initSelectionAPI(); - - // 添加 text - this._initText(); - - // 初始化菜单 - this._initMenus(); - - // 添加 图片上传 - this._initUploadImg(); - - // 初始化选区,将光标定位到内容尾部 - this.initSelection(true); - - // 绑定事件 - this._bindEvent(); - }, - - // 解绑所有事件(暂时不对外开放) - _offAllEvent: function _offAllEvent() { - $.offAll(); - } -}; - -// 检验是否浏览器环境 -try { - document; -} catch (ex) { - throw new Error('请在浏览器环境下运行'); -} - -// polyfill -polyfill(); - -// 这里的 `inlinecss` 将被替换成 css 代码的内容,详情可去 ./gulpfile.js 中搜索 `inlinecss` 关键字 -var inlinecss = '.w-e-toolbar,.w-e-text-container,.w-e-menu-panel { padding: 0; margin: 0; box-sizing: border-box;}.w-e-toolbar *,.w-e-text-container *,.w-e-menu-panel * { padding: 0; margin: 0; box-sizing: border-box;}.w-e-clear-fix:after { content: ""; display: table; clear: both;}.w-e-toolbar .w-e-droplist { position: absolute; left: 0; top: 0; background-color: #fff; border: 1px solid #f1f1f1; border-right-color: #ccc; border-bottom-color: #ccc;}.w-e-toolbar .w-e-droplist .w-e-dp-title { text-align: center; color: #999; line-height: 2; border-bottom: 1px solid #f1f1f1; font-size: 13px;}.w-e-toolbar .w-e-droplist ul.w-e-list { list-style: none; line-height: 1;}.w-e-toolbar .w-e-droplist ul.w-e-list li.w-e-item { color: #333; padding: 5px 0;}.w-e-toolbar .w-e-droplist ul.w-e-list li.w-e-item:hover { background-color: #f1f1f1;}.w-e-toolbar .w-e-droplist ul.w-e-block { list-style: none; text-align: left; padding: 5px;}.w-e-toolbar .w-e-droplist ul.w-e-block li.w-e-item { display: inline-block; *display: inline; *zoom: 1; padding: 3px 5px;}.w-e-toolbar .w-e-droplist ul.w-e-block li.w-e-item:hover { background-color: #f1f1f1;}@font-face { font-family: \'w-e-icon\'; src: url(data:application/x-font-woff;charset=utf-8;base64,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) format(\'truetype\'); font-weight: normal; font-style: normal;}[class^="w-e-icon-"],[class*=" w-e-icon-"] { /* use !important to prevent issues with browser extensions that change fonts */ font-family: \'w-e-icon\' !important; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; line-height: 1; /* Better Font Rendering =========== */ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;}.w-e-icon-close:before { content: "\\f00d";}.w-e-icon-upload2:before { content: "\\e9c6";}.w-e-icon-trash-o:before { content: "\\f014";}.w-e-icon-header:before { content: "\\f1dc";}.w-e-icon-pencil2:before { content: "\\e906";}.w-e-icon-paint-brush:before { content: "\\f1fc";}.w-e-icon-image:before { content: "\\e90d";}.w-e-icon-play:before { content: "\\e912";}.w-e-icon-location:before { content: "\\e947";}.w-e-icon-undo:before { content: "\\e965";}.w-e-icon-redo:before { content: "\\e966";}.w-e-icon-quotes-left:before { content: "\\e977";}.w-e-icon-list-numbered:before { content: "\\e9b9";}.w-e-icon-list2:before { content: "\\e9bb";}.w-e-icon-link:before { content: "\\e9cb";}.w-e-icon-happy:before { content: "\\e9df";}.w-e-icon-bold:before { content: "\\ea62";}.w-e-icon-underline:before { content: "\\ea63";}.w-e-icon-italic:before { content: "\\ea64";}.w-e-icon-strikethrough:before { content: "\\ea65";}.w-e-icon-table2:before { content: "\\ea71";}.w-e-icon-paragraph-left:before { content: "\\ea77";}.w-e-icon-paragraph-center:before { content: "\\ea78";}.w-e-icon-paragraph-right:before { content: "\\ea79";}.w-e-icon-terminal:before { content: "\\f120";}.w-e-icon-page-break:before { content: "\\ea68";}.w-e-icon-cancel-circle:before { content: "\\ea0d";}.w-e-toolbar { display: -webkit-box; display: -ms-flexbox; display: flex; padding: 0 5px; /* flex-wrap: wrap; */ /* 单个菜单 */}.w-e-toolbar .w-e-menu { position: relative; text-align: center; padding: 5px 10px; cursor: pointer;}.w-e-toolbar .w-e-menu i { color: #999;}.w-e-toolbar .w-e-menu:hover i { color: #333;}.w-e-toolbar .w-e-active i { color: #1e88e5;}.w-e-toolbar .w-e-active:hover i { color: #1e88e5;}.w-e-text-container .w-e-panel-container { position: absolute; top: 0; left: 50%; border: 1px solid #ccc; border-top: 0; box-shadow: 1px 1px 2px #ccc; color: #333; background-color: #fff; /* 为 emotion panel 定制的样式 */ /* 上传图片的 panel 定制样式 */}.w-e-text-container .w-e-panel-container .w-e-panel-close { position: absolute; right: 0; top: 0; padding: 5px; margin: 2px 5px 0 0; cursor: pointer; color: #999;}.w-e-text-container .w-e-panel-container .w-e-panel-close:hover { color: #333;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-title { list-style: none; display: -webkit-box; display: -ms-flexbox; display: flex; font-size: 14px; margin: 2px 10px 0 10px; border-bottom: 1px solid #f1f1f1;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-title .w-e-item { padding: 3px 5px; color: #999; cursor: pointer; margin: 0 3px; position: relative; top: 1px;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-title .w-e-active { color: #333; border-bottom: 1px solid #333; cursor: default; font-weight: 700;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content { padding: 10px 15px 10px 15px; font-size: 16px; /* 输入框的样式 */ /* 按钮的样式 */}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input:focus,.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea:focus,.w-e-text-container .w-e-panel-container .w-e-panel-tab-content button:focus { outline: none;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea { width: 100%; border: 1px solid #ccc; padding: 5px;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea:focus { border-color: #1e88e5;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text] { border: none; border-bottom: 1px solid #ccc; font-size: 14px; height: 20px; color: #333; text-align: left;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text].small { width: 30px; text-align: center;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text].block { display: block; width: 100%; margin: 10px 0;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text]:focus { border-bottom: 2px solid #1e88e5;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button { font-size: 14px; color: #1e88e5; border: none; padding: 5px 10px; background-color: #fff; cursor: pointer; border-radius: 3px;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.left { float: left; margin-right: 10px;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.right { float: right; margin-left: 10px;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.gray { color: #999;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.red { color: #c24f4a;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button:hover { background-color: #f1f1f1;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container:after { content: ""; display: table; clear: both;}.w-e-text-container .w-e-panel-container .w-e-emoticon-container .w-e-item { cursor: pointer; font-size: 18px; padding: 0 3px; display: inline-block; *display: inline; *zoom: 1;}.w-e-text-container .w-e-panel-container .w-e-up-img-container { text-align: center;}.w-e-text-container .w-e-panel-container .w-e-up-img-container .w-e-up-btn { display: inline-block; *display: inline; *zoom: 1; color: #999; cursor: pointer; font-size: 60px; line-height: 1;}.w-e-text-container .w-e-panel-container .w-e-up-img-container .w-e-up-btn:hover { color: #333;}.w-e-text-container { position: relative;}.w-e-text-container .w-e-progress { position: absolute; background-color: #1e88e5; bottom: 0; left: 0; height: 1px;}.w-e-text { padding: 0 10px; overflow-y: scroll;}.w-e-text p,.w-e-text h1,.w-e-text h2,.w-e-text h3,.w-e-text h4,.w-e-text h5,.w-e-text table,.w-e-text pre { margin: 10px 0; line-height: 1.5;}.w-e-text ul,.w-e-text ol { margin: 10px 0 10px 20px;}.w-e-text blockquote { display: block; border-left: 8px solid #d0e5f2; padding: 5px 10px; margin: 10px 0; line-height: 1.4; font-size: 100%; background-color: #f1f1f1;}.w-e-text code { display: inline-block; *display: inline; *zoom: 1; background-color: #f1f1f1; border-radius: 3px; padding: 3px 5px; margin: 0 3px;}.w-e-text pre code { display: block;}.w-e-text table { border-top: 1px solid #ccc; border-left: 1px solid #ccc;}.w-e-text table td,.w-e-text table th { border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; padding: 3px 5px;}.w-e-text table th { border-bottom: 2px solid #ccc; text-align: center;}.w-e-text:focus { outline: none;}.w-e-text img { cursor: pointer;}.w-e-text img:hover { box-shadow: 0 0 5px #333;}'; - -// 将 css 代码添加到