独墅湖高教创新区危化品智慧管控平台(新危化品)
zhouwx
2025-04-17 a8593f5ca77a934b31bbdd3b919d8e41796cb920
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
<template>
    <div style="height: 600px">
        <we-editor
            toolbar-class="toolbar"
            editable-class="editable"
            toolbar-style="border: 1px solid #d9d9d9"
            editable-style="border: 1px solid #d9d9d9"
            :toolbar-option="toolbar"
            :editable-option="editable"
            :toolbar-reloadbefore="onToolbarReloadBefore"
            :editable-reloadbefore="onEditableReloadBefore"
            v-model="formData.jarr"
            v-model:json="formData.jstr"
            v-model:html="formData.html"
        />
    </div>
</template>
<script>
import '@wangeditor/editor/dist/css/style.css'
 
import { WeEditor, useWangEditor } from 'wangeditor5-for-vue3'
import {defineComponent, onBeforeUnmount, ref, shallowReactive, shallowRef, watch} from 'vue'
import {ElMessage} from "element-plus";
import {getToken} from "@/utils/auth";
import {nextTick} from 'vue'
export default defineComponent( {
    name: "wangeditor",
    components: { WeEditor },
    props: {
        propData :String
    },
    setup(prop) {
        //编辑器配置
        const editableOption = {
            config:{
                placeholder:"请在这里输入内容",
                hoverbarKeys: {
                    attachment: {
                        menuKeys: ['downloadAttachment'], // “下载附件”菜单
                    },
                },
                MENU_CONF:{
                    // 配置默认字号
                    fontSize:{
                        fontSizeList: [
                            // 元素支持两种形式
                            //   1. 字符串;
                            //   2. { name: 'xxx', value: 'xxx' }
                            '16px',
                            '20px',
                            { name: '26px', value: '26px' },
                            '40px',
                        ]
                    },
                    // 配置上传图片
                    uploadImage:{
                        // 请求路径
                        server: import.meta.env.VITE_APP_BASE_API +  "/system/common/uploadFile",
                        // 后端接收的文件名称
                        fieldName: "file",
                        maxFileSize: 1 * 1024 * 1024, // 1M
                        // 上传的图片类型
                        allowedFileTypes: ["image/*"],
                        // 小于该值就插入 base64 格式(而不上传),默认为 0
                        base64LimitSize: 10 * 1024, // 10MB
                        // 自定义插入返回格式【后端返回的格式】
                        customInsert(res, insertFn) {
                            if(res.code != 200){
                                ElMessage.error("上传文件失败,"+res.message)
                                return
                            }
                            const url = import.meta.env.VITE_APP_BASE_API + "/" +res.data.path
                            insertFn(url)
                        },
                        // 携带的数据
                        meta: {
                            Authorization: getToken()
                        },
                        // 将 meta 拼接到 url 参数中,默认 false
                        metaWithUrl: true,
                        // 单个文件上传成功之后
                        onSuccess(file, res) {
                            if(res.code == 200){
                                ElMessage.success(`${file.name} 上传成功`)
                                return
                            }else {
                                ElMessage.warning(`${file.name} 上传出了点异常`)
                                return
                            }
                            // console.log(`${file.name} 上传成功`, res)
                            //ElMessage.success(`${file.name} 上传成功`, res)
                        },
                        // 单个文件上传失败
                        onFailed(file, res) {
                            console.log(res)
                            ElMessage.error(`${file.name} 上传失败`)
                        },
                        // 上传错误,或者触发 timeout 超时
                        onError(file, err, res) {
                            console.log(err, res)
                            ElMessage.error(`${file.name} 上传出错`)
                        },
                    },
                    // 上传附件
                    uploadAttachment: {
                        server: import.meta.env.VITE_APP_BASE_API +  "/system/common/uploadFile",
                        fieldName: 'file',
                        maxFileSize: 100 * 1024 * 1024, // 100M
                        // 携带的数据
                        meta: {
                            Authorization: getToken()
                        },
                        // 成功回调
                        onSuccess(file, res) {
                            if (res.errno === 0) {
                                ElMessage.success(`${file}附件上传成功`)
                            }
                        },
                        // 失败回调
                        onFailed(file, res) {
                            if (res.errno === 1) {
                                ElMessage.success(`${file}附件上传失败,` + res.message)
                            }
                        },
                        // 上传成功后,用户自定义插入文件
                        customInsert(res, file, insertFn) {
                          console.log('customInsert', res)
                            const url = import.meta.env.VITE_APP_BASE_API + "/" +res.data.path
                            if (!url) throw new Error(`url is empty`)
                            // 插入附件到编辑器
                            insertFn(`${file.name}`, url)
                        },
                        // 插入到编辑器后的回调
                        onInsertedAttachment(elem) {
                            console.log("elem",elem)
                        }
                    }
                }
            }
        }
 
        // 菜单栏配置
        const toolbarOption = {
            mode: 'simple', // 指定简介模式
            config:{
                toolbarKeys:[
                    "fontSize",'header1', 'header2', 'header3','header4','|',
                    'blockquote',"code","codeBlock",'|',
                    'bold', 'underline', 'italic', 'through', 'color', 'bgColor', 'clearStyle', '|',
                    'bulletedList', 'numberedList', 'todo', 'justifyLeft','justifyCenter', 'justifyRight', '|',
                    'insertLink',
                    {
                        key: 'group-image',
                        title: '图片',
                        iconSvg: "<svg viewBox=\"0 0 1024 1024\"><path d=\"M959.877 128l0.123 0.123v767.775l-0.123 0.122H64.102l-0.122-0.122V128.123l0.122-0.123h895.775zM960 64H64C28.795 64 0 92.795 0 128v768c0 35.205 28.795 64 64 64h896c35.205 0 64-28.795 64-64V128c0-35.205-28.795-64-64-64zM832 288.01c0 53.023-42.988 96.01-96.01 96.01s-96.01-42.987-96.01-96.01S682.967 192 735.99 192 832 234.988 832 288.01zM896 832H128V704l224.01-384 256 320h64l224.01-192z\"></path></svg>",
                        menuKeys: ['insertImage', 'uploadImage']
                    },
                    "insertTable",
                    "|",
                    "undo","redo"
                ],
                // 插入哪些菜单
                insertKeys: {
                    index: 27, // 自定义插入的位置
                    keys: ['uploadAttachment'], // “上传附件”菜单
                },
            }
        }
 
 
        // 防抖时长。当会触发重载的配置项发生变化 365ms 后,编辑器会重载
        const reloadDelary = 365
 
        // 对于上面的三个对象,经过 useWangEditor 处理后,返回的 editable 和 toolbar 分别对应编辑器和菜单栏的配置项
        const { editable, toolbar ,syncContent,clearContent } = useWangEditor(
            editableOption,
            toolbarOption,
            reloadDelary,
        {
                delay: 3000, // 无操作 3s 后才会同步表单数据
                config: {
                    placeholder: '表单提交前使用 syncContent API 强制同步数据,确保数据不被丢失',
                },
            }
        )
        // 获取数据
        const formData = shallowReactive({ html: '' })
 
        // 监听父组件传来的参数
        watch(prop, (val) => {
            // 监听从父组件接收的所有参数,只要有参数变化就会触发
            console.log('props接收的值', val)
            formData.html = prop.propData
        }, {
           immediate:true
        })
 
        function submit() {
            // 强制同步 v-model 数据
            syncContent()
            // 表单验证
            if(formData.html!=''){
                this.$emit('childFn',formData.html)
            }else {
                // ElMessage.error("请在编辑器内编写内容...")
            }
        }
        function setData(val) {
            console.log("val",val)
        }
 
        function clear() {
            clearContent()
        }
 
 
        // 在可编辑的重新加载之前
        function onEditableReloadBefore(inst) {
            console.log(inst)
            console.log('editable 即将重载: ' + new Date().toLocaleString())
        }
 
        // 在工具栏上重新加载之前
        function onToolbarReloadBefore(inst) {
            console.log(inst)
            console.log('toolbar 即将重载: ' + new Date().toLocaleString())
        }
        return { editable, toolbar, formData, submit, clear, prop, onEditableReloadBefore, onToolbarReloadBefore }
    },
})
</script>
<style>
/*工具栏样式*/
.toolbar{
    border: 1px solid #d9d9d9;margin-bottom: 10px;
}
/*编辑器样式*/
.editable{
    margin-top: -11px;
    border: 1px solid #d9d9d9;
    height: 500px;
    //width: 50%;
    //margin: 30px auto 150px auto;
    background-color: #fff;
    box-shadow: 0 2px 10px rgb(0 0 0 / 12%);
    //border: 1px solid #e8e8e8;
}
</style>