zydx-plus 1.16.65 → 1.16.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -2
- package/src/components/editor2/src/editor.vue +176 -46
- package/src/index.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zydx-plus",
|
|
3
|
-
"version": "1.16.
|
|
3
|
+
"version": "1.16.66",
|
|
4
4
|
"description": "Vue.js",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -29,7 +29,10 @@
|
|
|
29
29
|
"@wangeditor/plugin-formula": "^1.0.11",
|
|
30
30
|
"katex": "^0.15.6",
|
|
31
31
|
"simple-mind-map": "^0.5.8",
|
|
32
|
-
"html2json": "^1.0.2"
|
|
32
|
+
"html2json": "^1.0.2",
|
|
33
|
+
"@tiptap/extension-image": "^2.0.3",
|
|
34
|
+
"@tiptap/starter-kit": "^2.0.3",
|
|
35
|
+
"@tiptap/vue-3": "^2.0.3"
|
|
33
36
|
},
|
|
34
37
|
"peerDependencies": {
|
|
35
38
|
"vue": "^3.2.13"
|
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="ed-head">
|
|
3
|
-
<div class="ed-
|
|
4
|
-
|
|
5
|
-
<
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
<div class="ed-title">{{ title }}</div>
|
|
4
|
+
<div class="ed-but">
|
|
5
|
+
<div class="ed-head-but" v-for="(item,index) in toolbar">
|
|
6
|
+
<button v-if="item.key === 'but'" class="but" @click="item.onClick" :style="{color: (item.active)? '#00ff00' :'#000'}">{{ item.title }}</button>
|
|
7
|
+
|
|
8
|
+
<label v-else-if="item.key === 'upImg' || item.key === 'uploadAtt'">
|
|
9
|
+
<input type="file" @change="upload($event,item.key)" :accept="(item.key === 'upImg')?'image/*':'application/*'" style="display: none;">
|
|
10
|
+
<span class="but">{{ item.title }}</span>
|
|
11
|
+
</label>
|
|
12
|
+
<button v-else class="but" @click="toolTap(item.key)">{{ item.title }}</button>
|
|
13
|
+
</div>
|
|
10
14
|
</div>
|
|
11
15
|
</div>
|
|
12
16
|
<div class="ed-cont">
|
|
13
|
-
<
|
|
17
|
+
<editor-content class="editor" :style="heightStyle" :editor="editor" />
|
|
18
|
+
<div class="editor-but" v-if="butText !== ''">
|
|
19
|
+
<button class="but" @click="complete">{{ butText }}</button>
|
|
20
|
+
</div>
|
|
14
21
|
<div class="enclosure" v-if="uploadAttData.length > 0">
|
|
15
22
|
<p>附件列表:</p>
|
|
16
23
|
<div class="enclosure-list" v-for="(item,index) in uploadAttData">
|
|
17
24
|
<div class="enclosure-item">
|
|
18
|
-
<span>{{ index + 1 }}. {{ item.
|
|
25
|
+
<span>{{ index + 1 }}. {{ item.fileName }}</span>
|
|
19
26
|
</div>
|
|
20
27
|
<div class="enclosure-item en-but">
|
|
21
28
|
<button class="but" @click="see(index)">查看</button>
|
|
22
|
-
<button class="but">下载</button>
|
|
29
|
+
<button class="but" @click="download(index)">下载</button>
|
|
23
30
|
<button class="but" @click="del(index)">删除</button>
|
|
24
31
|
</div>
|
|
25
32
|
</div>
|
|
@@ -28,35 +35,76 @@
|
|
|
28
35
|
</template>
|
|
29
36
|
<script>
|
|
30
37
|
import { html2json, json2html } from 'html2json'
|
|
38
|
+
import { Editor, EditorContent } from '@tiptap/vue-3'
|
|
39
|
+
import StarterKit from '@tiptap/starter-kit'
|
|
40
|
+
import Image from '@tiptap/extension-image'
|
|
31
41
|
export default {
|
|
32
42
|
name: 'zydx-xiao-editor',
|
|
43
|
+
components: {
|
|
44
|
+
EditorContent
|
|
45
|
+
},
|
|
33
46
|
data() {
|
|
34
47
|
return {
|
|
35
48
|
uploadAttData: [],
|
|
49
|
+
editor: null,
|
|
50
|
+
heightStyle: {}
|
|
36
51
|
};
|
|
37
52
|
},
|
|
53
|
+
beforeUnmount() {
|
|
54
|
+
this.editor.destroy()
|
|
55
|
+
},
|
|
38
56
|
props: {
|
|
39
57
|
data: {
|
|
40
58
|
type: Object,
|
|
41
59
|
default: () => {}
|
|
42
60
|
},
|
|
43
|
-
|
|
61
|
+
toolbar: {
|
|
62
|
+
type: Array,
|
|
63
|
+
default: []
|
|
64
|
+
},
|
|
65
|
+
title: {
|
|
44
66
|
type: String,
|
|
45
|
-
default: '
|
|
67
|
+
default: ''
|
|
46
68
|
},
|
|
47
|
-
|
|
69
|
+
readOnly: {
|
|
70
|
+
type: Boolean,
|
|
71
|
+
default: true
|
|
72
|
+
},
|
|
73
|
+
butText: {
|
|
48
74
|
type: String,
|
|
49
|
-
default: '
|
|
75
|
+
default: ''
|
|
50
76
|
},
|
|
51
|
-
|
|
52
|
-
type:
|
|
53
|
-
default:
|
|
77
|
+
height: {
|
|
78
|
+
type: String,
|
|
79
|
+
default: '200px'
|
|
80
|
+
},
|
|
81
|
+
uploadImage: {
|
|
82
|
+
type: Object,
|
|
83
|
+
default: {}
|
|
84
|
+
},
|
|
85
|
+
uploadAttachment: {
|
|
86
|
+
type: Object,
|
|
87
|
+
default: {}
|
|
54
88
|
}
|
|
55
89
|
},
|
|
90
|
+
emits: ['see','complete'],
|
|
56
91
|
mounted() {
|
|
57
92
|
if(this.data === undefined) return
|
|
58
93
|
this.uploadAttData = this.data.enclosure
|
|
59
|
-
|
|
94
|
+
this.heightStyle = (this.height === '100%')? {height: '100%'} : {'min-height': this.height}
|
|
95
|
+
this.editor = new Editor({
|
|
96
|
+
content: json2html({node: "root",child: this.data.html}),
|
|
97
|
+
editable: this.readOnly,
|
|
98
|
+
extensions: [
|
|
99
|
+
StarterKit,
|
|
100
|
+
Image.configure({
|
|
101
|
+
inline: true,
|
|
102
|
+
HTMLAttributes: {
|
|
103
|
+
width: '100%'
|
|
104
|
+
}
|
|
105
|
+
}),
|
|
106
|
+
],
|
|
107
|
+
})
|
|
60
108
|
},
|
|
61
109
|
methods: {
|
|
62
110
|
del(index) {
|
|
@@ -65,44 +113,109 @@ export default {
|
|
|
65
113
|
see(index) {
|
|
66
114
|
this.$emit('see', this.uploadAttData[index])
|
|
67
115
|
},
|
|
116
|
+
uploadFile(file) {
|
|
117
|
+
return new Promise((rl,re) => {
|
|
118
|
+
const meta = Object.keys(this.uploadImage.meta)
|
|
119
|
+
const param = new FormData()
|
|
120
|
+
param.append('file', file)
|
|
121
|
+
for(let i = 0; i < meta.length; i++) {
|
|
122
|
+
param.append(meta[i], this.uploadImage.meta[meta[i]])
|
|
123
|
+
}
|
|
124
|
+
const xhr = new XMLHttpRequest()
|
|
125
|
+
xhr.open('POST', this.uploadImage.server)
|
|
126
|
+
const headers = Object.keys(this.uploadImage.headers)
|
|
127
|
+
for(let i = 0; i < headers.length; i++) {
|
|
128
|
+
xhr.setRequestHeader(headers[i], this.uploadImage.headers[headers[i]])
|
|
129
|
+
}
|
|
130
|
+
xhr.onreadystatechange = () => {
|
|
131
|
+
if(xhr.readyState === 4) {
|
|
132
|
+
if(xhr.status === 200) {
|
|
133
|
+
rl(JSON.parse(xhr.responseText))
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
xhr.send(param)
|
|
138
|
+
})
|
|
139
|
+
},
|
|
68
140
|
upload(e,v) {
|
|
69
141
|
const file = e.target.files[0]
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
142
|
+
this.uploadFile(file).then(r => {
|
|
143
|
+
if(v === 'uploadAtt') {
|
|
144
|
+
this.uploadAttData.push(r.data)
|
|
145
|
+
}else {
|
|
146
|
+
const url = this.uploadImage.url + r.data.filePath
|
|
147
|
+
const html = [
|
|
148
|
+
{
|
|
149
|
+
node: "element",
|
|
150
|
+
tag: "p",
|
|
151
|
+
child: [{
|
|
152
|
+
attr: {
|
|
153
|
+
src: url,
|
|
154
|
+
width:"100%"
|
|
155
|
+
},
|
|
156
|
+
tag: 'img',
|
|
157
|
+
node: "element",
|
|
158
|
+
}]
|
|
159
|
+
}
|
|
160
|
+
]
|
|
161
|
+
this.insertContent(html)
|
|
81
162
|
}
|
|
82
|
-
}
|
|
163
|
+
})
|
|
83
164
|
e.target.value = ''
|
|
84
165
|
},
|
|
166
|
+
insertContent(v) {
|
|
167
|
+
for(let i=0; i< v.length; i++) {
|
|
168
|
+
let html = json2html(v[i])
|
|
169
|
+
this.editor.chain().focus().insertContentAt(this.selection(),html).run()
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
download(index) {
|
|
173
|
+
const url = this.uploadImage.url + this.uploadAttData[index].filePath
|
|
174
|
+
let a = document.createElement('a');
|
|
175
|
+
a.style = 'display: none';
|
|
176
|
+
a.download = this.uploadAttData[index].filename;
|
|
177
|
+
a.href = url;
|
|
178
|
+
document.body.appendChild(a);
|
|
179
|
+
a.click();
|
|
180
|
+
document.body.removeChild(a);
|
|
181
|
+
},
|
|
182
|
+
selection() {
|
|
183
|
+
const { from } = this.editor.state.selection
|
|
184
|
+
return from
|
|
185
|
+
},
|
|
186
|
+
complete() {
|
|
187
|
+
this.$emit('complete', this.getData())
|
|
188
|
+
if(this.uploadAttData.length > 0) {
|
|
189
|
+
this.$emit('complete', {
|
|
190
|
+
html: this.getData(),
|
|
191
|
+
enclosure: this.uploadAttData
|
|
192
|
+
})
|
|
193
|
+
}else {
|
|
194
|
+
this.$emit('complete', {html: this.getData()})
|
|
195
|
+
}
|
|
196
|
+
},
|
|
85
197
|
// 获取编辑器内容
|
|
86
198
|
getContent(el) {
|
|
87
199
|
// 编辑器内容转json
|
|
88
|
-
|
|
200
|
+
if(this.uploadAttData.length > 0) {
|
|
201
|
+
el({
|
|
202
|
+
html: this.getData(),
|
|
203
|
+
enclosure: this.uploadAttData
|
|
204
|
+
})
|
|
205
|
+
}else {
|
|
206
|
+
el({html: this.getData()})
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
getData() {
|
|
210
|
+
const html = this.editor.getHTML()
|
|
89
211
|
const json = html2json(html)
|
|
90
|
-
json.child
|
|
91
|
-
if(x.tag === undefined) {
|
|
92
|
-
x.tag = 'p'
|
|
93
|
-
x.node = 'element'
|
|
94
|
-
x.child = [{ text: x.text }]
|
|
95
|
-
}
|
|
96
|
-
if(x.tag === 'div') x.tag = 'p'
|
|
97
|
-
return x
|
|
98
|
-
})
|
|
99
|
-
el({
|
|
100
|
-
html: json.child,
|
|
101
|
-
enclosure: this.uploadAttData
|
|
102
|
-
})
|
|
212
|
+
return json.child
|
|
103
213
|
},
|
|
104
214
|
toolTap(v) {
|
|
105
|
-
|
|
215
|
+
if(v === 'h1') this.editor.chain().focus().toggleHeading({level:1}).run()
|
|
216
|
+
if(v === 'h2') this.editor.chain().focus().toggleHeading({level:2}).run()
|
|
217
|
+
if(v === 'h3') this.editor.chain().focus().toggleHeading({level:3}).run()
|
|
218
|
+
if(v === 'p') this.editor.chain().focus().setParagraph().run()
|
|
106
219
|
}
|
|
107
220
|
}
|
|
108
221
|
}
|
|
@@ -110,9 +223,23 @@ export default {
|
|
|
110
223
|
</script>
|
|
111
224
|
|
|
112
225
|
<style scoped>
|
|
226
|
+
.editor-but{
|
|
227
|
+
text-align: right;
|
|
228
|
+
margin: 10px 0;
|
|
229
|
+
}
|
|
230
|
+
.ed-head{
|
|
231
|
+
display: flex;
|
|
232
|
+
justify-content: center;
|
|
233
|
+
}
|
|
113
234
|
.ed-head-but{
|
|
114
235
|
display: inline-block;
|
|
115
236
|
}
|
|
237
|
+
.ed-title{
|
|
238
|
+
flex: 1;
|
|
239
|
+
text-align: left;
|
|
240
|
+
line-height: 22px;
|
|
241
|
+
font-size: 14px;
|
|
242
|
+
}
|
|
116
243
|
.enclosure-list{
|
|
117
244
|
display: flex;
|
|
118
245
|
justify-content: space-between;
|
|
@@ -137,7 +264,10 @@ export default {
|
|
|
137
264
|
border: 1px solid #ccc;
|
|
138
265
|
border-radius: 3px;
|
|
139
266
|
padding: 20px;
|
|
140
|
-
|
|
267
|
+
outline: none;
|
|
268
|
+
}
|
|
269
|
+
.editor img{
|
|
270
|
+
max-width: 100%;
|
|
141
271
|
}
|
|
142
272
|
.ed-head{
|
|
143
273
|
text-align: right;
|