|
1 | 1 | <template> |
2 | | - <div class="tinymce-container" :style="{ width: containerWidth }"> |
| 2 | + <div :class="prefixCls" :style="{ width: containerWidth }"> |
| 3 | + <ImgUpload |
| 4 | + @uploading="handleImageUploading" |
| 5 | + @done="handleDone" |
| 6 | + v-if="showImageUpload" |
| 7 | + v-show="editorRef" |
| 8 | + /> |
3 | 9 | <textarea :id="tinymceId" ref="elRef" :style="{ visibility: 'hidden' }"></textarea> |
4 | 10 | </div> |
5 | 11 | </template> |
|
24 | 30 | import { bindHandlers } from './helper'; |
25 | 31 | import lineHeight from './lineHeight'; |
26 | 32 | import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated'; |
| 33 | + import ImgUpload from './ImgUpload.vue'; |
| 34 | + import { useDesign } from '/@/hooks/web/useDesign'; |
27 | 35 |
|
28 | 36 | const CDN_URL = 'https://cdn.bootcdn.net/ajax/libs/tinymce/5.5.1'; |
29 | 37 |
|
|
33 | 41 | name: 'Tinymce', |
34 | 42 | inheritAttrs: false, |
35 | 43 | props: basicProps, |
| 44 | + components: { ImgUpload }, |
36 | 45 | emits: ['change', 'update:modelValue'], |
37 | 46 | setup(props, { emit, attrs }) { |
38 | 47 | const editorRef = ref<any>(null); |
39 | 48 | const tinymceId = ref<string>(snowUuid('tiny-vue')); |
40 | 49 | const elRef = ref<Nullable<HTMLElement>>(null); |
41 | 50 |
|
| 51 | + const { prefixCls } = useDesign('tinymce-container'); |
| 52 | +
|
42 | 53 | const tinymceContent = computed(() => { |
43 | 54 | return props.modelValue; |
44 | 55 | }); |
|
140 | 151 | bindHandlers(e, attrs, unref(editorRef)); |
141 | 152 | } |
142 | 153 |
|
143 | | - function setValue(editor: any, val: string, prevVal: string) { |
| 154 | + function setValue(editor: Recordable, val: string, prevVal?: string) { |
144 | 155 | if ( |
145 | 156 | editor && |
146 | 157 | typeof val === 'string' && |
|
179 | 190 | }); |
180 | 191 | } |
181 | 192 |
|
| 193 | + function handleImageUploading(name: string) { |
| 194 | + const editor = unref(editorRef); |
| 195 | + if (!editor) return; |
| 196 | + const content = editor?.getContent() ?? ''; |
| 197 | + setValue(editor, `${content}\n${getImgName(name)}`); |
| 198 | + } |
| 199 | +
|
| 200 | + function handleDone(name: string, url: string) { |
| 201 | + const editor = unref(editorRef); |
| 202 | + if (!editor) return; |
| 203 | +
|
| 204 | + const content = editor?.getContent() ?? ''; |
| 205 | + const val = content?.replace(getImgName(name), `<img src="${url}"/>`) ?? ''; |
| 206 | + setValue(editor, val); |
| 207 | + } |
| 208 | +
|
| 209 | + function getImgName(name: string) { |
| 210 | + return `[uploading:${name}]`; |
| 211 | + } |
| 212 | +
|
182 | 213 | return { |
| 214 | + prefixCls, |
183 | 215 | containerWidth, |
184 | 216 | initOptions, |
185 | 217 | tinymceContent, |
186 | 218 | tinymceScriptSrc, |
187 | 219 | elRef, |
188 | 220 | tinymceId, |
| 221 | + handleImageUploading, |
| 222 | + handleDone, |
| 223 | + editorRef, |
189 | 224 | }; |
190 | 225 | }, |
191 | 226 | }); |
192 | 227 | </script> |
193 | 228 |
|
194 | | -<style lang="less" scoped> |
195 | | - .tinymce-container { |
196 | | - position: relative; |
197 | | - line-height: normal; |
| 229 | +<style lang="less" scoped></style> |
198 | 230 |
|
199 | | - .mce-fullscreen { |
200 | | - z-index: 10000; |
201 | | - } |
202 | | - } |
| 231 | +<style lang="less"> |
| 232 | + @prefix-cls: ~'@{namespace}-tinymce-container'; |
203 | 233 |
|
204 | | - .editor-custom-btn-container { |
205 | | - position: absolute; |
206 | | - top: 6px; |
207 | | - right: 6px; |
| 234 | + .@{prefix-cls} { |
| 235 | + position: relative; |
| 236 | + line-height: normal; |
208 | 237 |
|
209 | | - &.fullscreen { |
210 | | - position: fixed; |
211 | | - z-index: 10000; |
| 238 | + textarea { |
| 239 | + z-index: -1; |
| 240 | + visibility: hidden; |
212 | 241 | } |
213 | 242 | } |
214 | | -
|
215 | | - .editor-upload-btn { |
216 | | - display: inline-block; |
217 | | - } |
218 | | -
|
219 | | - textarea { |
220 | | - z-index: -1; |
221 | | - visibility: hidden; |
222 | | - } |
223 | 243 | </style> |
0 commit comments