|
| 1 | +<script setup> |
| 2 | +import { ref, reactive } from 'vue' |
| 3 | +import { QuillEditor } from '@vueup/vue-quill' |
| 4 | +import '@vueup/vue-quill/dist/vue-quill.snow.css' |
| 5 | +import { getAccessToken } from '@/utils/auth' |
| 6 | +import editorOptions from './quill-options' |
| 7 | +
|
| 8 | +const BASE_URL = import.meta.env.VITE_BASE_URL |
| 9 | +
|
| 10 | +const message = useMessage() |
| 11 | +
|
| 12 | +const props = defineProps({ |
| 13 | + /* 公众号账号编号 */ |
| 14 | + accountId: { |
| 15 | + type: Number, |
| 16 | + required: true |
| 17 | + }, |
| 18 | + /* 编辑器的内容 */ |
| 19 | + value: { |
| 20 | + type: String, |
| 21 | + default: '' |
| 22 | + }, |
| 23 | + /* 图片大小 */ |
| 24 | + maxSize: { |
| 25 | + type: Number, |
| 26 | + default: 4000 // kb |
| 27 | + } |
| 28 | +}) |
| 29 | +
|
| 30 | +const emit = defineEmits(['input']) |
| 31 | +
|
| 32 | +const myQuillEditorRef = ref() |
| 33 | +
|
| 34 | +const content = ref(props.value.replace(/data-src/g, 'src')) |
| 35 | +
|
| 36 | +const loading = ref(false) // 根据图片上传状态来确定是否显示loading动画,刚开始是false,不显示 |
| 37 | +
|
| 38 | +const actionUrl = ref(BASE_URL + '/admin-api/mp/material/upload-news-image') // 这里写你要上传的图片服务器地址 |
| 39 | +const headers = ref({ Authorization: 'Bearer ' + getAccessToken() }) // 设置上传的请求头部 |
| 40 | +const uploadData = reactive({ |
| 41 | + type: 'image', // TODO 芋艿:试试要不要换成 thumb |
| 42 | + accountId: props.accountId |
| 43 | +}) |
| 44 | +
|
| 45 | +const onEditorChange = () => { |
| 46 | + //内容改变事件 |
| 47 | + emit('input', content.value) |
| 48 | +} |
| 49 | +
|
| 50 | +// 富文本图片上传前 |
| 51 | +const beforeUpload = () => { |
| 52 | + // 显示 loading 动画 |
| 53 | + loading.value = true |
| 54 | +} |
| 55 | +
|
| 56 | +// 图片上传成功 |
| 57 | +// 注意!由于微信公众号的图片有访问限制,所以会显示“此图片来自微信公众号,未经允许不可引用” |
| 58 | +const uploadSuccess = (res) => { |
| 59 | + // res为图片服务器返回的数据 |
| 60 | + // 获取富文本组件实例 |
| 61 | + const quill = myQuillEditorRef.value.quill |
| 62 | + // 如果上传成功 |
| 63 | + const link = res.data |
| 64 | + if (link) { |
| 65 | + // 获取光标所在位置 |
| 66 | + let length = quill.getSelection().index |
| 67 | + // 插入图片 res.info为服务器返回的图片地址 |
| 68 | + quill.insertEmbed(length, 'image', link) |
| 69 | + // 调整光标到最后 |
| 70 | + quill.setSelection(length + 1) |
| 71 | + } else { |
| 72 | + message.error('图片插入失败') |
| 73 | + } |
| 74 | + // loading 动画消失 |
| 75 | + loading.value = false |
| 76 | +} |
| 77 | +
|
| 78 | +// 富文本图片上传失败 |
| 79 | +const uploadError = () => { |
| 80 | + // loading 动画消失 |
| 81 | + loading.value = false |
| 82 | + message.error('图片插入失败') |
| 83 | +} |
| 84 | +</script> |
| 85 | + |
| 86 | +<template> |
| 87 | + <div id="wxEditor"> |
| 88 | + <div v-loading="loading" element-loading-text="请稍等,图片上传中"> |
| 89 | + <!-- 图片上传组件辅助--> |
| 90 | + <el-upload |
| 91 | + class="avatar-uploader" |
| 92 | + name="file" |
| 93 | + :action="actionUrl" |
| 94 | + :headers="headers" |
| 95 | + :show-file-list="false" |
| 96 | + :data="uploadData" |
| 97 | + :on-success="uploadSuccess" |
| 98 | + :on-error="uploadError" |
| 99 | + :before-upload="beforeUpload" |
| 100 | + /> |
| 101 | + <QuillEditor |
| 102 | + class="editor" |
| 103 | + v-model="content" |
| 104 | + ref="quillEditorRef" |
| 105 | + :options="editorOptions" |
| 106 | + @change="onEditorChange($event)" |
| 107 | + /> |
| 108 | + </div> |
| 109 | + </div> |
| 110 | +</template> |
| 111 | + |
| 112 | +<style> |
| 113 | +.editor { |
| 114 | + line-height: normal !important; |
| 115 | + height: 500px; |
| 116 | +} |
| 117 | +
|
| 118 | +.ql-snow .ql-tooltip[data-mode='link']::before { |
| 119 | + content: '请输入链接地址:'; |
| 120 | +} |
| 121 | +
|
| 122 | +.ql-snow .ql-tooltip.ql-editing a.ql-action::after { |
| 123 | + border-right: 0; |
| 124 | + content: '保存'; |
| 125 | + padding-right: 0; |
| 126 | +} |
| 127 | +
|
| 128 | +.ql-snow .ql-tooltip[data-mode='video']::before { |
| 129 | + content: '请输入视频地址:'; |
| 130 | +} |
| 131 | +
|
| 132 | +.ql-snow .ql-picker.ql-size .ql-picker-label::before, |
| 133 | +.ql-snow .ql-picker.ql-size .ql-picker-item::before { |
| 134 | + content: '14px'; |
| 135 | +} |
| 136 | +
|
| 137 | +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='small']::before, |
| 138 | +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='small']::before { |
| 139 | + content: '10px'; |
| 140 | +} |
| 141 | +
|
| 142 | +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='large']::before, |
| 143 | +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='large']::before { |
| 144 | + content: '18px'; |
| 145 | +} |
| 146 | +
|
| 147 | +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='huge']::before, |
| 148 | +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='huge']::before { |
| 149 | + content: '32px'; |
| 150 | +} |
| 151 | +
|
| 152 | +.ql-snow .ql-picker.ql-header .ql-picker-label::before, |
| 153 | +.ql-snow .ql-picker.ql-header .ql-picker-item::before { |
| 154 | + content: '文本'; |
| 155 | +} |
| 156 | +
|
| 157 | +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='1']::before, |
| 158 | +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='1']::before { |
| 159 | + content: '标题1'; |
| 160 | +} |
| 161 | +
|
| 162 | +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='2']::before, |
| 163 | +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='2']::before { |
| 164 | + content: '标题2'; |
| 165 | +} |
| 166 | +
|
| 167 | +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='3']::before, |
| 168 | +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='3']::before { |
| 169 | + content: '标题3'; |
| 170 | +} |
| 171 | +
|
| 172 | +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='4']::before, |
| 173 | +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='4']::before { |
| 174 | + content: '标题4'; |
| 175 | +} |
| 176 | +
|
| 177 | +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='5']::before, |
| 178 | +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='5']::before { |
| 179 | + content: '标题5'; |
| 180 | +} |
| 181 | +
|
| 182 | +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='6']::before, |
| 183 | +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='6']::before { |
| 184 | + content: '标题6'; |
| 185 | +} |
| 186 | +
|
| 187 | +.ql-snow .ql-picker.ql-font .ql-picker-label::before, |
| 188 | +.ql-snow .ql-picker.ql-font .ql-picker-item::before { |
| 189 | + content: '标准字体'; |
| 190 | +} |
| 191 | +
|
| 192 | +.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='serif']::before, |
| 193 | +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='serif']::before { |
| 194 | + content: '衬线字体'; |
| 195 | +} |
| 196 | +
|
| 197 | +.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='monospace']::before, |
| 198 | +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='monospace']::before { |
| 199 | + content: '等宽字体'; |
| 200 | +} |
| 201 | +</style> |
0 commit comments