index.vue 10 KB

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