index.vue 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. <template>
  2. <div>
  3. <div class="mdeditor-box">
  4. <MarkdownPro ref="md1" v-model="content" :height="height" :toolbars="toolbars" :is-custom-fullscreen="transfer" @on-custom="customClick"></MarkdownPro>
  5. <img-upload ref="myUpload" class="teditor-upload" type="callback" @on-callback="editorImage" num="50" style="display:none;"></img-upload>
  6. <Upload
  7. name="files"
  8. ref="fileUpload"
  9. class="teditor-upload"
  10. :action="actionUrl"
  11. :data="params"
  12. multiple
  13. :format="uploadFormat"
  14. :show-upload-list="false"
  15. :max-size="maxSize"
  16. :on-progress="handleProgress"
  17. :on-success="handleSuccess"
  18. :on-error="handleError"
  19. :on-format-error="handleFormatError"
  20. :on-exceeded-size="handleMaxSize"
  21. :before-upload="handleBeforeUpload">
  22. </Upload>
  23. </div>
  24. <Modal v-model="transfer" class="mdeditor-transfer" footer-hide fullscreen transfer :closable="false">
  25. <div class="mdeditor-transfer-body">
  26. <MarkdownPro ref="md2" v-if="transfer" v-model="content" :toolbars="toolbars" :is-custom-fullscreen="transfer" height="100%" @on-custom="customClick"></MarkdownPro>
  27. </div>
  28. </Modal>
  29. <Modal v-model="html2md" title="html转markdown" okText="转换成markdown" width="680" class-name="simple-modal" @on-ok="htmlOk" transfer>
  30. <Input type="textarea" v-model="htmlValue" :rows="14" placeholder="请输入html代码..." />
  31. </Modal>
  32. </div>
  33. </template>
  34. <style lang="scss">
  35. .mdeditor-transfer {
  36. background-color: #ffffff;
  37. .ivu-modal-header {
  38. display: none;
  39. }
  40. .ivu-modal-close {
  41. top: 7px;
  42. }
  43. .mdeditor-transfer-body {
  44. position: absolute;
  45. top: 0;
  46. left: 0;
  47. width: 100%;
  48. height: 100%;
  49. padding: 0;
  50. margin: 0;
  51. }
  52. }
  53. </style>
  54. <style lang="scss" scoped>
  55. .mdeditor-box {
  56. position: relative;
  57. }
  58. </style>
  59. <script>
  60. import MarkdownPro from './pro';
  61. import ImgUpload from "../ImgUpload";
  62. export default {
  63. name: 'MDEditor',
  64. components: {ImgUpload, MarkdownPro},
  65. props: {
  66. value: {
  67. default: ''
  68. },
  69. height: {
  70. default: 380,
  71. },
  72. toolbars: {
  73. type: Object,
  74. default: () => {
  75. return {
  76. strong: true,
  77. italic: true,
  78. overline: true,
  79. h1: true,
  80. h2: true,
  81. h3: true,
  82. h4: false,
  83. h5: false,
  84. h6: false,
  85. hr: true,
  86. quote: true,
  87. ul: true,
  88. ol: true,
  89. code: true,
  90. link: true,
  91. image: false,
  92. uploadImage: false,
  93. table: true,
  94. checked: true,
  95. notChecked: true,
  96. split: true,
  97. preview: true,
  98. fullscreen: false,
  99. theme: false,
  100. exportmd: false,
  101. importmd: false,
  102. save: false,
  103. clear: false,
  104. custom_image: true,
  105. custom_uploadImage: true,
  106. custom_uploadFile: true,
  107. custom_fullscreen: true,
  108. };
  109. }
  110. }
  111. },
  112. data() {
  113. return {
  114. content: '',
  115. transfer: false,
  116. html2md: false,
  117. htmlValue: '',
  118. uploadIng: 0,
  119. uploadFormat: ['jpg', 'jpeg', 'png', 'gif', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'esp', 'pdf', 'rar', 'zip', 'gz'],
  120. actionUrl: $A.apiUrl('system/fileupload'),
  121. params: { token: $A.getToken() },
  122. maxSize: 10240
  123. };
  124. },
  125. mounted() {
  126. this.content = this.value;
  127. },
  128. activated() {
  129. this.content = this.value;
  130. },
  131. watch: {
  132. value(newValue) {
  133. if (newValue == null) {
  134. newValue = "";
  135. }
  136. this.content = newValue;
  137. },
  138. content(val) {
  139. this.$emit('input', val);
  140. },
  141. },
  142. methods: {
  143. editorImage(lists) {
  144. for (let i = 0; i < lists.length; i++) {
  145. let item = lists[i];
  146. if (typeof item === 'object' && typeof item.url === "string") {
  147. if (this.transfer) {
  148. this.$refs.md2.insertContent('\n![image](' + item.url + ')');
  149. } else {
  150. this.$refs.md1.insertContent('\n![image](' + item.url + ')');
  151. }
  152. }
  153. }
  154. },
  155. customClick(act) {
  156. switch (act) {
  157. case "image-browse": {
  158. this.$refs.myUpload.browsePicture();
  159. break;
  160. }
  161. case "image-upload": {
  162. this.$refs.myUpload.handleClick();
  163. break;
  164. }
  165. case "file-upload": {
  166. this.$refs.fileUpload.handleClick();
  167. break;
  168. }
  169. case "fullscreen": {
  170. this.transfer = !this.transfer;
  171. break;
  172. }
  173. case "html2md": {
  174. this.html2md = true;
  175. break;
  176. }
  177. }
  178. },
  179. htmlOk() {
  180. this.loadScript(window.location.origin + '/js/html2md.js', () => {
  181. if (typeof toMarkdown !== 'function') {
  182. alert("组件加载失败!");
  183. return;
  184. }
  185. if (this.transfer) {
  186. this.$refs.md2.insertContent('\n' + toMarkdown(this.htmlValue, { gfm: true }));
  187. } else {
  188. this.$refs.md1.insertContent('\n' + toMarkdown(this.htmlValue, { gfm: true }));
  189. }
  190. this.htmlValue = "";
  191. });
  192. },
  193. loadScript(url, callback) {
  194. let script = document.createElement("script");
  195. script.type = "text/javascript";
  196. if (script.readyState) {
  197. script.onreadystatechange = () => {
  198. if (script.readyState === "loaded" || script.readyState === "complete") {
  199. script.onreadystatechange = null;
  200. callback();
  201. }
  202. };
  203. } else {
  204. script.onload = () => {
  205. callback();
  206. };
  207. }
  208. script.src = url;
  209. document.body.appendChild(script);
  210. },
  211. /********************文件上传部分************************/
  212. handleProgress() {
  213. //开始上传
  214. this.uploadIng++;
  215. },
  216. handleSuccess(res, file) {
  217. //上传完成
  218. this.uploadIng--;
  219. if (res.ret === 1) {
  220. let con = `[${res.data.name} (${$A.bytesToSize(res.data.size * 1024)})](${res.data.url})`;
  221. if (this.transfer) {
  222. this.$refs.md2.insertContent(con);
  223. } else {
  224. this.$refs.md1.insertContent(con);
  225. }
  226. } else {
  227. this.$Modal.warning({
  228. title: this.$L('上传失败'),
  229. content: this.$L('文件 % 上传失败,%', file.name, res.msg)
  230. });
  231. }
  232. },
  233. handleError() {
  234. //上传错误
  235. this.uploadIng--;
  236. },
  237. handleFormatError(file) {
  238. //上传类型错误
  239. this.$Modal.warning({
  240. title: this.$L('文件格式不正确'),
  241. content: this.$L('文件 % 格式不正确,仅支持上传:%', file.name, this.uploadFormat.join(','))
  242. });
  243. },
  244. handleMaxSize(file) {
  245. //上传大小错误
  246. this.$Modal.warning({
  247. title: this.$L('超出文件大小限制'),
  248. content: this.$L('文件 % 太大,不能超过%。', file.name, $A.bytesToSize(this.maxSize * 1024))
  249. });
  250. },
  251. handleBeforeUpload() {
  252. //上传前判断
  253. this.params = {
  254. token: $A.getToken(),
  255. };
  256. return true;
  257. },
  258. }
  259. }
  260. </script>