沈丘营商办后台前端项目
346149741
2024-06-18 9fb6a0ff49c2af567be2e3adaf93c4c301b3f102
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
<template>
  <div style="width: 100%; border: 1px solid #ccc; padding-bottom: 2px">
    <Toolbar :editor="editorRef" :defaultConfig="toolbarConfig" :mode="mode" />
    <Editor
      style="min-height: 380px; overflow-y: scroll"
      v-model="html"
      :defaultConfig="editorConfig"
      :mode="mode"
      @onCreated="handleCreated"
      @onChange="handleChange"
      @onDestroyed="handleDestroyed"
      @onFocus="handleFocus"
      @onBlur="handleBlur"
      @customAlert="customAlert"
      @customPaste="customPaste"
    />
  </div>
</template>
<script setup lang="ts">
import { IDomEditor, IEditorConfig } from "@wangeditor/editor";
import "@wangeditor/editor/dist/css/style.css"; // 引入 css
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { getToken } from "@/utils/auth";
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const baseUrl = import.meta.env.VITE_APP_BASE;
const uploadImgUrl = ref(import.meta.env.VITE_APP_BASE_API + "/tool/file/upload"); // 上传的图片服务器地址
const props = defineProps({
  modelValue: {
    type: String,
    default: "",
  },
});
 
const emits = defineEmits(["update:modelValue"]);
// onMounted(() => {
//   if (props.modelValue) {
//     editorRef.value!.setHtml(props.modelValue);
//   }
// });
// console.log("uploadImgUrl======>", uploadImgUrl);
type InsertFnType = (url: string, alt: string, href: string) => void; //定义插入函数的类型
type InsertVidepFnType = (url: string, poster: string) => void;
const state = reactive({
  html: "",
  toolbarConfig: {},
  mode: "default", // or 'simple'
});
 
// 初始化 MENU_CONF 属性
const editorConfig: Partial<IEditorConfig> = {
  // TS 语法
  placeholder: "请输入内容...", //占位内容
  MENU_CONF: {
    uploadImage: {
      //自定义上传图片
      server: uploadImgUrl.value,
      maxFileSize: 100 * 1024 * 1024, // 100M
      fieldName: "file",
      // 自定义增加 http  header
      headers: {
        Authorization: "Bearer " + getToken(),
        ContentType: "application/json;charset=utf-8",
      },
      // 自定义插入图片
      customInsert(res: any, insertFn: InsertFnType) {
        // TS 语法
        // customInsert(res, insertFn) {                  // JS 语法
        // res 即服务端的返回结果
        // console.log("res=============>", res);
        // 从 res 中找到 url alt href ,然后插入图片
        insertFn(baseUrl + res.fileName, res.name, baseUrl + res.fileName);
      },
    },
    uploadVideo: {
      server: uploadImgUrl.value,
      fieldName: "file",
      allowedFileTypes: ["video/*"],
      // 单个文件的最大体积限制,默认为 10M
      maxFileSize: 500 * 1024 * 1024, // 500M
      // 最多可上传几个文件,默认为 5
      maxNumberOfFiles: 1,
      headers: {
        Authorization: "Bearer " + getToken(),
        ContentType: "application/json;charset=utf-8",
      },
      customInsert(res: any, insertFn: InsertVidepFnType) {
        insertFn(baseUrl + res.fileName, "");
      },
      // 单个文件上传成功之后
      onSuccess(file: File, res: any) {
        // TS 语法
        // onSuccess(file, res) {          // JS 语法
        console.log(`${file.name} 上传成功`, res);
        proxy.$modal.msgSuccess(`${file.name} 上传成功`);
      },
 
      // 上传错误,或者触发 timeout 超时
      onError(file: File, err: any, res: any) {
        // TS 语法
        // onError(file, err, res) {               // JS 语法
        proxy.$modal.msgError(`${file.name} 上传出错`, err, res.msg);
      },
    },
  },
  // 其他属性...
};
const editorRef = shallowRef();
 
const { html, toolbarConfig, mode } = toRefs(state);
 
// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
  const editor = editorRef.value;
  if (editor == null) return;
  editor.destroy();
});
 
const handleCreated = (editor: IDomEditor) => {
  editorRef.value = editor;
  if (props.modelValue) {
    editorRef.value!.setHtml(props.modelValue);
  }
  // editorRef.value.txt.html(props.modelValue);
  console.log("created", editor);
};
 
watch(
  () => props.modelValue,
  (newval, oldval) => {
    editorRef.value.setHtml(newval);
  }
);
 
const handleChange = (editor: { children: IDomEditor }) => {
  // console.log("change:", editor.children);
  emits("update:modelValue", state.html);
  //   console.log("-------->", state.html);
};
const handleDestroyed = (editor: IDomEditor) => {
  console.log("destroyed", editor);
};
const handleFocus = (editor: IDomEditor) => {
  console.log("focus", editor);
};
const handleBlur = (editor: IDomEditor) => {
  console.log("blur", editor);
};
const customAlert = (info: IDomEditor, type: IDomEditor) => {
  alert(`【自定义提示】${type} - ${info}`);
};
const customPaste = (editor: { insertText: (arg0: string) => void }, event: { preventDefault: () => void }, callback: (arg0: boolean) => void) => {
  console.log("ClipboardEvent 粘贴事件对象", event);
  // const html = event.clipboardData.getData('text/html') // 获取粘贴的 html
  // const text = event.clipboardData.getData('text/plain') // 获取粘贴的纯文本
  // const rtf = event.clipboardData.getData('text/rtf') // 获取 rtf 数据(如从 word wsp 复制粘贴)
 
  // 自定义插入内容
  //   editor.insertText("xxx");
 
  // 返回 false ,阻止默认粘贴行为
  //   event.preventDefault();
  //   callback(false); // 返回值(注意,vue 事件的返回值,不能用 return)
 
  // 返回 true ,继续默认的粘贴行为
  callback(true);
};
</script>
 
<style></style>