cf4e0175f4f44a1396ae3594c0e1de4c153eaa3c.svn-base 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. <template>
  2. <div>
  3. <div class="j-markdown-editor" :id="id"/>
  4. <div v-if="isShow">
  5. <j-modal
  6. title="图片上传"
  7. :visible.sync="dialogVisible"
  8. width="30%"
  9. :before-close="handleClose"
  10. @ok="handleOk">
  11. <a-tabs default-active-key="1" @change="handleChange">
  12. <a-tab-pane tab="本地图片上传" key="1" :forceRender="true">
  13. <j-upload v-model="fileList" :number="1"></j-upload>
  14. <div style="margin-top: 20px">
  15. <a-input v-model="remark" placeholder="请填写备注"></a-input>
  16. </div>
  17. </a-tab-pane>
  18. <a-tab-pane tab="网络图片地址" key="2" :forceRender="true">
  19. <a-input v-model="networkPic" placeholder="请填写网络图片地址"></a-input>
  20. <a-input style="margin-top: 20px" v-model="remark" placeholder="请填写备注"></a-input>
  21. </a-tab-pane>
  22. </a-tabs>
  23. </j-modal>
  24. </div>
  25. </div>
  26. </template>
  27. <script>
  28. import 'codemirror/lib/codemirror.css'
  29. import '@toast-ui/editor/dist/toastui-editor.css';
  30. import '@toast-ui/editor/dist/i18n/zh-cn';
  31. import Editor from '@toast-ui/editor';
  32. import defaultOptions from './default-options'
  33. import JUpload from '@/components/jeecg/JUpload'
  34. import { getFileAccessHttpUrl } from '@/api/manage'
  35. export default {
  36. name: 'JMarkdownEditor',
  37. components: {
  38. JUpload,
  39. },
  40. props: {
  41. value: {
  42. type: String,
  43. default: ''
  44. },
  45. id: {
  46. type: String,
  47. required: false,
  48. default() {
  49. return 'markdown-editor-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
  50. }
  51. },
  52. options: {
  53. type: Object,
  54. default() {
  55. return defaultOptions
  56. }
  57. },
  58. mode: {
  59. type: String,
  60. default: 'markdown'
  61. },
  62. height: {
  63. type: String,
  64. required: false,
  65. default: '300px'
  66. },
  67. language: {
  68. type: String,
  69. required: false,
  70. default: 'zh-CN'
  71. }
  72. },
  73. data() {
  74. return {
  75. editor: null,
  76. isShow:false,
  77. activeIndex:"1",
  78. dialogVisible:false,
  79. index:"1",
  80. fileList:[],
  81. remark:"",
  82. imageName:"",
  83. imageUrl:"",
  84. networkPic:""
  85. }
  86. },
  87. computed: {
  88. editorOptions() {
  89. const options = Object.assign({}, defaultOptions, this.options)
  90. options.initialEditType = this.mode
  91. options.height = this.height
  92. options.language = this.language
  93. return options
  94. }
  95. },
  96. watch: {
  97. value(newValue, preValue) {
  98. if (newValue !== preValue && newValue !== this.editor.getMarkdown()) {
  99. this.editor.setMarkdown(newValue)
  100. }
  101. },
  102. language(val) {
  103. this.destroyEditor()
  104. this.initEditor()
  105. },
  106. height(newValue) {
  107. this.editor.height(newValue)
  108. },
  109. mode(newValue) {
  110. this.editor.changeMode(newValue)
  111. }
  112. },
  113. mounted() {
  114. this.initEditor()
  115. },
  116. destroyed() {
  117. this.destroyEditor()
  118. },
  119. methods: {
  120. initEditor() {
  121. this.editor = new Editor({
  122. el: document.getElementById(this.id),
  123. ...this.editorOptions
  124. })
  125. if (this.value) {
  126. this.editor.setMarkdown(this.value)
  127. }
  128. this.editor.on('change', () => {
  129. this.$emit('change', this.editor.getMarkdown())
  130. })
  131. //--begin 添加自定义上传按钮
  132. /*
  133. * 添加自定义按钮
  134. */
  135. //获取编辑器上的功能条
  136. let toolbar = this.editor.getUI().getToolbar();
  137. let fileDom = this.$refs.files;
  138. //添加图片点击事件
  139. this.editor.eventManager.addEventType('isShowClickEvent');
  140. this.editor.eventManager.listen('isShowClickEvent', () => {
  141. this.isShow = true
  142. this.dialogVisible = true
  143. });
  144. //addImageBlobHook图片上传、剪切、拖拽都会走此方法
  145. // 删除默认监听事件
  146. this.editor.eventManager.removeEventHandler('addImageBlobHook')
  147. // 添加自定义监听事件
  148. this.editor.eventManager.listen('addImageBlobHook', (blob, callback) => {
  149. this.upload(blob, url => {
  150. callback(url)
  151. })
  152. })
  153. // 添加自定义按钮 第二个参数代表位置,不传默认放在最后
  154. toolbar.insertItem(15,{
  155. type: 'button',
  156. options:{
  157. name: 'customize',
  158. className: 'tui-image tui-toolbar-icons',
  159. event: 'isShowClickEvent',
  160. tooltip: '上传图片',
  161. }
  162. //
  163. });
  164. //--end 添加自定义上传按钮
  165. },
  166. destroyEditor() {
  167. if (!this.editor) return
  168. this.editor.off('change')
  169. this.editor.remove()
  170. },
  171. setMarkdown(value) {
  172. this.editor.setMarkdown(value)
  173. },
  174. getMarkdown() {
  175. return this.editor.getMarkdown()
  176. },
  177. setHtml(value) {
  178. this.editor.setHtml(value)
  179. },
  180. getHtml() {
  181. return this.editor.getHtml()
  182. },
  183. handleOk(){
  184. if(this.index=='1'){
  185. this.imageUrl = getFileAccessHttpUrl(this.fileList)
  186. if(this.remark){
  187. this.addImgToMd(this.imageUrl,this.remark)
  188. }else{
  189. this.addImgToMd(this.imageUrl,"")
  190. }
  191. }else{
  192. if(this.remark){
  193. this.addImgToMd(this.networkPic,this.remark)
  194. }else{
  195. this.addImgToMd(this.networkPic,"")
  196. }
  197. }
  198. this.index="1"
  199. this.fileList=[]
  200. this.imageName="";
  201. this.imageUrl="";
  202. this.remark=""
  203. this.networkPic=""
  204. this.dialogVisible=false
  205. this.isShow=false;
  206. },
  207. handleClose(done) {
  208. done();
  209. },
  210. handleChange(val){
  211. this.fileList=[]
  212. this.remark=""
  213. this.imageName=""
  214. this.imageUrl=""
  215. this.networkPic=""
  216. this.index=val
  217. },
  218. //添加图片到markdown
  219. addImgToMd(data,name) {
  220. let editor = this.editor.getCodeMirror();
  221. let editorHtml = this.editor.getCurrentModeEditor();
  222. let isMarkdownMode = this.editor.isMarkdownMode();
  223. if (isMarkdownMode) {
  224. editor.replaceSelection(`![${name}](${data})`);
  225. } else {
  226. let range = editorHtml.getRange();
  227. let img = document.createElement('img');
  228. img.src = `${data}`;
  229. img.alt = name;
  230. range.insertNode(img);
  231. }
  232. },
  233. },
  234. model: {
  235. prop: 'value',
  236. event: 'change'
  237. }
  238. }
  239. </script>
  240. <style scoped lang="less">
  241. .j-markdown-editor {
  242. /deep/ .tui-editor-defaultUI {
  243. .te-mode-switch,
  244. .tui-scrollsync
  245. {
  246. line-height: 1.5;
  247. }
  248. }
  249. }
  250. </style>