index.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <!--
  2. * @Author: Gui
  3. * @Date: 2023-03-01 19:20:44
  4. * @LastEditors: guicheng 1625811865@qq.com
  5. * @LastEditTime: 2024-06-20 15:03:36
  6. * @Description: kxs files
  7. * @filePath:
  8. -->
  9. <script setup lang="ts">
  10. import "@wangeditor/editor/dist/css/style.css"; // 引入 css
  11. import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
  12. import { onBeforeUnmount, ref, shallowRef, onMounted, watch } from "vue";
  13. import Ossupload from "@/utils/OSSupload";
  14. const props = defineProps<{}>();
  15. type Res = {
  16. url?: string;
  17. describe?: string;
  18. };
  19. const mode = "default";
  20. // 编辑器实例,必须用 shallowRef
  21. const editorRef = shallowRef();
  22. // 内容 HTML
  23. const valueHtml = ref("");
  24. // 模拟异步获取内容
  25. onMounted(() => { });
  26. const toolbarConfig: any = { excludeKeys: "fullScreen" };
  27. const editorConfig = {
  28. placeholder: "请输入内容...",
  29. MENU_CONF: {}
  30. };
  31. // 组件销毁时,也及时销毁编辑器
  32. onBeforeUnmount(() => {
  33. const editor = editorRef.value;
  34. if (editor == null) return;
  35. editor.destroy();
  36. });
  37. const handleCreated = editor => {
  38. editorRef.value = editor; // 记录 editor 实例,重要!
  39. };
  40. // 自定义校验图片
  41. function customCheckImageFn(src) {
  42. // JS 语法
  43. if (!src) {
  44. return;
  45. }
  46. if (src.indexOf("http") !== 0) {
  47. return "图片网址必须以 http/https 开头";
  48. }
  49. return true;
  50. // 返回值有三种选择:
  51. // 1. 返回 true ,说明检查通过,编辑器将正常插入图片
  52. // 2. 返回一个字符串,说明检查未通过,编辑器会阻止插入。会 alert 出错误信息(即返回的字符串)
  53. // 3. 返回 undefined(即没有任何返回),说明检查未通过,编辑器会阻止插入。但不会提示任何信息
  54. }
  55. // 转换图片链接
  56. function customParseImageSrc(src) {
  57. // JS 语法
  58. if (src.indexOf("http") !== 0) {
  59. return `http://${src}`;
  60. }
  61. return src;
  62. } // 插入图片
  63. editorConfig.MENU_CONF["insertImage"] = {
  64. onInsertedImage(imageNode) {
  65. // JS 语法
  66. if (imageNode == null) return;
  67. const { src, alt, url, href } = imageNode;
  68. console.log("inserted image", src, alt, url, href);
  69. },
  70. checkImage: customCheckImageFn, // 也支持 async 函数
  71. parseImageSrc: customParseImageSrc // 也支持 async 函数
  72. };
  73. // 编辑图片
  74. editorConfig.MENU_CONF["editImage"] = {
  75. // TS 语法
  76. onUpdatedImage(imageNode) {
  77. // JS 语法
  78. if (imageNode == null) return;
  79. const { src, alt, url } = imageNode;
  80. console.log("updated image", src, alt, url);
  81. },
  82. checkImage: customCheckImageFn, // 也支持 async 函数
  83. parseImageSrc: customParseImageSrc // 也支持 async 函数
  84. };
  85. // Image
  86. editorConfig.MENU_CONF["uploadImage"] = {
  87. // 自定义上传
  88. async customUpload(file, insertFn) {
  89. Ossupload(file, "KxsAdmin/Editor").then((res: Res) => {
  90. insertFn(res.url, res.describe);
  91. });
  92. }
  93. };
  94. // Video
  95. editorConfig.MENU_CONF["uploadVideo"] = {
  96. // 自定义上传
  97. async customUpload(file, insertFn) {
  98. // JS 语法
  99. // file 即选中的文件
  100. // 自己实现上传,并得到视频 url poster
  101. // 最后插入视频
  102. Ossupload(file, "KxsAdmin/Video").then((res: Res) => {
  103. insertFn(res.url, res.describe);
  104. });
  105. }
  106. };
  107. defineExpose({
  108. valueHtml
  109. });
  110. // const buttonclick = function () {
  111. // const _source = editorRef.value.getText();
  112. // console.log(_source);
  113. // editorRef.value.setHtml(_source);
  114. // };
  115. // const buttonclick1 = function () {
  116. // const _source = editorRef.value
  117. // .getHtml()
  118. // .replace(/</g, "&lt;")
  119. // .replace(/>/g, "&gt;")
  120. // .replace(/ /g, "&nbsp;");
  121. // console.log(_source);
  122. // editorRef.value.setHtml(_source);
  123. // };
  124. </script>
  125. <template>
  126. <!-- <el-button type="primary" @click="buttonclick">转文字</el-button>
  127. <el-button type="primary" @click="buttonclick1">转代码</el-button> -->
  128. <div class="wangeditor">
  129. <Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig" :mode="mode" />
  130. <Editor style="height: 700px; overflow-y: hidden" v-model="valueHtml" :defaultConfig="editorConfig" :mode="mode"
  131. @onCreated="handleCreated" />
  132. </div>
  133. </template>
  134. <style lang="css">
  135. .editor-content-view p,
  136. .editor-content-view li {
  137. white-space: pre-wrap;
  138. /* 保留空格 */
  139. }
  140. .editor-content-view blockquote {
  141. border-left: 8px solid #d0e5f2;
  142. padding: 10px 10px;
  143. margin: 10px 0;
  144. background-color: #f1f1f1;
  145. }
  146. .editor-content-view code {
  147. font-family: monospace;
  148. background-color: #eee;
  149. padding: 3px;
  150. border-radius: 3px;
  151. }
  152. .editor-content-view pre>code {
  153. display: block;
  154. padding: 10px;
  155. }
  156. .editor-content-view table {
  157. border-collapse: collapse;
  158. }
  159. .editor-content-view td,
  160. .editor-content-view th {
  161. border: 1px solid #ccc;
  162. min-width: 50px;
  163. height: 20px;
  164. }
  165. .editor-content-view th {
  166. background-color: #f1f1f1;
  167. }
  168. .editor-content-view ul,
  169. .editor-content-view ol {
  170. padding-left: 20px;
  171. }
  172. .editor-content-view input[type="checkbox"] {
  173. margin-right: 5px;
  174. }
  175. </style>