潘志宝
6 天以前 12024e7c6f22f7bf68e877f6a688ba7bde0fe9c2
提交 | 用户 | 时间
820397 1 <script lang="ts" setup>
H 2 import { PropType } from 'vue'
3 import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
4 import { i18nChangeLanguage, IDomEditor, IEditorConfig } from '@wangeditor/editor'
5 import { propTypes } from '@/utils/propTypes'
6 import { isNumber } from '@/utils/is'
7 import { ElMessage } from 'element-plus'
8 import { useLocaleStore } from '@/store/modules/locale'
9 import { getAccessToken, getTenantId } from '@/utils/auth'
221c1c 10 import { getUploadUrl } from '@/components/UploadFile/src/useUpload'
820397 11
H 12 defineOptions({ name: 'Editor' })
13
14 type InsertFnType = (url: string, alt: string, href: string) => void
15
16 const localeStore = useLocaleStore()
17
18 const currentLocale = computed(() => localeStore.getCurrentLocale)
19
20 i18nChangeLanguage(unref(currentLocale).lang)
21
22 const props = defineProps({
23   editorId: propTypes.string.def('wangeEditor-1'),
24   height: propTypes.oneOfType([Number, String]).def('500px'),
25   editorConfig: {
26     type: Object as PropType<Partial<IEditorConfig>>,
27     default: () => undefined
28   },
29   readonly: propTypes.bool.def(false),
30   modelValue: propTypes.string.def('')
31 })
32
33 const emit = defineEmits(['change', 'update:modelValue'])
34
35 // 编辑器实例,必须用 shallowRef
36 const editorRef = shallowRef<IDomEditor>()
37
38 const valueHtml = ref('')
39
40 watch(
41   () => props.modelValue,
42   (val: string) => {
43     if (val === unref(valueHtml)) return
44     valueHtml.value = val
45   },
46   {
47     immediate: true
48   }
49 )
50
51 // 监听
52 watch(
53   () => valueHtml.value,
54   (val: string) => {
55     emit('update:modelValue', val)
56   }
57 )
58
59 const handleCreated = (editor: IDomEditor) => {
60   editorRef.value = editor
61 }
62
63 // 编辑器配置
64 const editorConfig = computed((): IEditorConfig => {
65   return Object.assign(
66     {
67       placeholder: '请输入内容...',
68       readOnly: props.readonly,
69       customAlert: (s: string, t: string) => {
70         switch (t) {
71           case 'success':
72             ElMessage.success(s)
73             break
74           case 'info':
75             ElMessage.info(s)
76             break
77           case 'warning':
78             ElMessage.warning(s)
79             break
80           case 'error':
81             ElMessage.error(s)
82             break
83           default:
84             ElMessage.info(s)
85             break
86         }
87       },
88       autoFocus: false,
89       scroll: true,
90       MENU_CONF: {
91         ['uploadImage']: {
221c1c 92           server: getUploadUrl(),
820397 93           // 单个文件的最大体积限制,默认为 2M
H 94           maxFileSize: 5 * 1024 * 1024,
95           // 最多可上传几个文件,默认为 100
96           maxNumberOfFiles: 10,
97           // 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
98           allowedFileTypes: ['image/*'],
99
100           // 自定义增加 http  header
101           headers: {
102             Accept: '*',
103             Authorization: 'Bearer ' + getAccessToken(),
104             'tenant-id': getTenantId()
105           },
106
107           // 超时时间,默认为 10 秒
108           timeout: 5 * 1000, // 5 秒
109
110           // form-data fieldName,后端接口参数名称,默认值wangeditor-uploaded-image
111           fieldName: 'file',
112
113           // 上传之前触发
114           onBeforeUpload(file: File) {
115             // console.log(file)
116             return file
117           },
118           // 上传进度的回调函数
119           onProgress(progress: number) {
120             // progress 是 0-100 的数字
121             console.log('progress', progress)
122           },
123           onSuccess(file: File, res: any) {
124             console.log('onSuccess', file, res)
125           },
126           onFailed(file: File, res: any) {
127             alert(res.message)
128             console.log('onFailed', file, res)
129           },
130           onError(file: File, err: any, res: any) {
131             alert(err.message)
132             console.error('onError', file, err, res)
133           },
134           // 自定义插入图片
135           customInsert(res: any, insertFn: InsertFnType) {
136             insertFn(res.data, 'image', res.data)
137           }
138         },
139         ['uploadVideo']: {
221c1c 140           server: getUploadUrl(),
820397 141           // 单个文件的最大体积限制,默认为 10M
H 142           maxFileSize: 10 * 1024 * 1024,
143           // 最多可上传几个文件,默认为 100
144           maxNumberOfFiles: 10,
145           // 选择文件时的类型限制,默认为 ['video/*'] 。如不想限制,则设置为 []
146           allowedFileTypes: ['video/*'],
147
148           // 自定义增加 http  header
149           headers: {
150             Accept: '*',
151             Authorization: 'Bearer ' + getAccessToken(),
152             'tenant-id': getTenantId()
153           },
154
155           // 超时时间,默认为 30 秒
156           timeout: 15 * 1000, // 15 秒
157
158           // form-data fieldName,后端接口参数名称,默认值wangeditor-uploaded-image
159           fieldName: 'file',
160
161           // 上传之前触发
162           onBeforeUpload(file: File) {
163             // console.log(file)
164             return file
165           },
166           // 上传进度的回调函数
167           onProgress(progress: number) {
168             // progress 是 0-100 的数字
169             console.log('progress', progress)
170           },
171           onSuccess(file: File, res: any) {
172             console.log('onSuccess', file, res)
173           },
174           onFailed(file: File, res: any) {
175             alert(res.message)
176             console.log('onFailed', file, res)
177           },
178           onError(file: File, err: any, res: any) {
179             alert(err.message)
180             console.error('onError', file, err, res)
181           },
182           // 自定义插入图片
183           customInsert(res: any, insertFn: InsertFnType) {
184             insertFn(res.data, 'mp4', res.data)
185           }
186         }
187       },
188       uploadImgShowBase64: true
189     },
190     props.editorConfig || {}
191   )
192 })
193
194 const editorStyle = computed(() => {
195   return {
196     height: isNumber(props.height) ? `${props.height}px` : props.height
197   }
198 })
199
200 // 回调函数
201 const handleChange = (editor: IDomEditor) => {
202   emit('change', editor)
203 }
204
205 // 组件销毁时,及时销毁编辑器
206 onBeforeUnmount(() => {
207   const editor = unref(editorRef.value)
208
209   // 销毁,并移除 editor
210   editor?.destroy()
211 })
212
213 const getEditorRef = async (): Promise<IDomEditor> => {
214   await nextTick()
215   return unref(editorRef.value) as IDomEditor
216 }
217
218 defineExpose({
219   getEditorRef
220 })
221 </script>
222
223 <template>
224   <div class="border-1 border-solid border-[var(--tags-view-border-color)] z-10">
225     <!-- 工具栏 -->
226     <Toolbar
227       :editor="editorRef"
228       :editorId="editorId"
229       class="border-0 b-b-1 border-solid border-[var(--tags-view-border-color)]"
230     />
231     <!-- 编辑器 -->
232     <Editor
233       v-model="valueHtml"
234       :defaultConfig="editorConfig"
235       :editorId="editorId"
236       :style="editorStyle"
237       @on-change="handleChange"
238       @on-created="handleCreated"
239     />
240   </div>
241 </template>
242
243 <style src="@wangeditor/editor/dist/css/style.css"></style>