@sy-common/wang-editor 1.0.0-beta.23 → 1.0.0-beta.24

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.vue +337 -317
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sy-common/wang-editor",
3
- "version": "1.0.0-beta.23",
3
+ "version": "1.0.0-beta.24",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "author": "lambo",
package/src/index.vue CHANGED
@@ -1,317 +1,337 @@
1
- <template>
2
- <div style="z-index: 999">
3
- <!-- 工具栏 -->
4
- <Toolbar
5
- :editor="editor"
6
- :defaultConfig="toolbarConfig"
7
- />
8
- <!-- 编辑器 -->
9
- <Editor
10
- :style="editorStyle"
11
- :defaultConfig="editorConfig"
12
- v-model="html"
13
- @onChange="onChange"
14
- @onCreated="onCreated"
15
- />
16
- </div>
17
- </template>
18
-
19
- <script>
20
- import '@wangeditor-next/editor/dist/css/style.css'
21
- import {oneOf} from '@lambo-design/shared/utils/platform';
22
- import {Editor, Toolbar} from '@wangeditor-next/editor-for-vue2'
23
- import {Boot} from '@wangeditor-next/editor'
24
- import {registerMenu} from './customHrMenu'
25
- // 注册分割线颜色菜单(模块级别,只执行一次)
26
- registerMenu(Boot)
27
-
28
- export default {
29
- name: 'WangEditor',
30
- components: {Editor, Toolbar},
31
- props: {
32
- value: {
33
- type: String,
34
- default: ''
35
- },
36
- /**
37
- * 绑定的值的类型, enum: ['html', 'text']
38
- */
39
- valueType: {
40
- type: String,
41
- default: 'html',
42
- validator: (val) => {
43
- return oneOf(val, ['html', 'text'])
44
- }
45
- },
46
- /**
47
- * @description 设置change事件触发时间间隔
48
- */
49
- changeInterval: {
50
- type: Number,
51
- default: 200
52
- },
53
- /**
54
- * @description 是否开启本地存储
55
- */
56
- cache: {
57
- type: Boolean,
58
- default: true
59
- },
60
- /**
61
- * @description 是否使用 base64 保存图片
62
- */
63
- uploadImgShowBase64: {
64
- type: Boolean,
65
- default: false
66
- },
67
- /**
68
- * 上传图片上下文
69
- */
70
- ossServerContext: {
71
- type: String,
72
- default: ''
73
- },
74
- /**
75
- * 上传图片Url地址
76
- */
77
- ossFilePutUrl: {
78
- type: String,
79
- default: "/oss/file/put"
80
- },
81
- /**
82
- * 获取图片url地址
83
- */
84
- ossFileGetImgUrl: {
85
- type: String,
86
- default: "/oss/file/get/"
87
- },
88
- /**
89
- * @description 是否保留粘贴内容的样式
90
- */
91
- preservePasteStyle: {
92
- type: Boolean,
93
- default: false
94
- },
95
-
96
- readOnly: {
97
- type: Boolean,
98
- default: false
99
- },
100
- /**
101
- * @description: 隐藏菜单
102
- */
103
- hideMenu: {
104
- type: Array,
105
- default: () => []
106
- },
107
-
108
- height: {
109
- type: [Number, String],
110
- default: 400
111
- }
112
- },
113
- data() {
114
- return {
115
- editor: null,
116
- html: '',
117
- hrCount: 0, // 追踪分割线数量
118
- toolbarConfig: {
119
- insertKeys: {
120
- index: 24, // 在分割线菜单后面插入
121
- keys: ['customHrMenu']
122
- }
123
- },
124
- editorConfig: {
125
- placeholder: '请输入内容...',
126
- MENU_CONF: {
127
- fontFamily: {
128
- fontFamilyList: [
129
- "黑体",
130
- {
131
- name: "仿宋",
132
- value: "仿宋"
133
- },
134
- "仿宋_GB2312",
135
- "楷体",
136
- "楷体_GB2312",
137
- "标楷体",
138
- "华文仿宋",
139
- "华文楷体",
140
- {
141
- name: "宋体",
142
- value: "宋体"
143
- }, "隶书", "方正小标宋简体", "思源宋体‌", "微软雅黑", "Arial", "Tahoma", "Verdana", "Times New Roman", "Courier New"]
144
- },
145
- color: {
146
- colors: [
147
- "rgb(0, 0, 0)",
148
- "rgb(38, 38, 38)",
149
- "rgb(89, 89, 89)",
150
- "rgb(140, 140, 140)",
151
- "rgb(191, 191, 191)",
152
- "rgb(217, 217, 217)",
153
- "rgb(233, 233, 233)",
154
- "rgb(245, 245, 245)",
155
- "rgb(250, 250, 250)",
156
- "rgb(255, 255, 255)",
157
- "rgb(225, 60, 57)",
158
- "rgb(231, 95, 51)",
159
- "rgb(235, 144, 58)",
160
- "rgb(245, 219, 77)",
161
- "rgb(114, 192, 64)",
162
- "rgb(89, 191, 192)",
163
- "rgb(66, 144, 247)",
164
- "rgb(54, 88, 226)",
165
- "rgb(106, 57, 201)",
166
- "rgb(216, 68, 147)",
167
- "rgb(251, 233, 230)",
168
- "rgb(252, 237, 225)",
169
- "rgb(252, 239, 212)",
170
- "rgb(252, 251, 207)",
171
- "rgb(231, 246, 213)",
172
- "rgb(218, 244, 240)",
173
- "rgb(217, 237, 250)",
174
- "rgb(224, 232, 250)",
175
- "rgb(237, 225, 248)",
176
- "rgb(246, 226, 234)",
177
- "rgb(255, 163, 158)",
178
- "rgb(255, 187, 150)",
179
- "rgb(255, 213, 145)",
180
- "rgb(255, 251, 143)",
181
- "rgb(183, 235, 143)",
182
- "rgb(135, 232, 222)",
183
- "rgb(145, 213, 255)",
184
- "rgb(173, 198, 255)",
185
- "rgb(211, 173, 247)",
186
- "rgb(255, 173, 210)",
187
- "rgb(255, 77, 79)",
188
- "rgb(255, 122, 69)",
189
- "rgb(255, 169, 64)",
190
- "rgb(255, 236, 61)",
191
- "rgb(115, 209, 61)",
192
- "rgb(54, 207, 201)",
193
- "rgb(64, 169, 255)",
194
- "rgb(89, 126, 247)",
195
- "rgb(146, 84, 222)",
196
- "rgb(247, 89, 171)",
197
- "rgb(207, 19, 34)",
198
- "rgb(212, 56, 13)",
199
- "rgb(212, 107, 8)",
200
- "rgb(212, 177, 6)",
201
- "rgb(56, 158, 13)",
202
- "rgb(8, 151, 156)",
203
- "rgb(9, 109, 217)",
204
- "rgb(29, 57, 196)",
205
- "rgb(83, 29, 171)",
206
- "rgb(196, 29, 127)",
207
- "rgb(130, 0, 20)",
208
- "rgb(135, 20, 0)",
209
- "rgb(135, 56, 0)",
210
- "rgb(97, 71, 0)",
211
- "rgb(19, 82, 0)",
212
- "rgb(0, 71, 79)",
213
- "rgb(0, 58, 140)",
214
- "rgb(6, 17, 120)",
215
- "rgb(34, 7, 94)",
216
- "rgb(120, 6, 80)",
217
- "rgb(250,64,6)"
218
- ]
219
- },
220
- uploadImage: {
221
- //上传图片配置
222
- server: this.ossServerContext + this.ossFilePutUrl, //上传接口地址
223
- fieldName: 'file', //上传文件名
224
- methods: 'post',
225
- metaWithUrl: true, // 参数拼接到 url 上
226
- //自定义插入图片
227
- customInsert: (res, insertFn) => {
228
- let self = this;
229
- const imgInfo = res.data[0] || {}
230
- const {fileId, fileName, contentType} = imgInfo
231
- insertFn(self.ossServerContext + self.ossFileGetImgUrl + fileId, fileName, self.ossServerContext + self.ossFileGetImgUrl + fileId)
232
- },
233
-
234
- },
235
- }
236
- }
237
- }
238
- },
239
- watch: {
240
- value: {
241
- handler: function (newVal, oldVal) {
242
- const isEmpty = !newVal || newVal === '<p><br></p>'
243
- const wasEmpty = !oldVal || oldVal === '<p><br></p>'
244
-
245
- if (!isEmpty && wasEmpty) {
246
- if (this.valueType === 'html') {
247
- let html = newVal
248
- this.editor.setHtml(html)
249
- } else {
250
- this.editor.insertText(newVal)
251
- }
252
- }
253
- }
254
- },
255
-
256
- readOnly: {
257
- handler(newVal){
258
- this.editorConfig.readOnly = newVal
259
- if(newVal){
260
- this.toolbarConfig.toolbarKeys = ['fullScreen']
261
- }
262
- },
263
- immediate: true,
264
- },
265
-
266
- hideMenu: {
267
- handler(newVal){
268
- this.toolbarConfig.excludeKeys = newVal
269
- },
270
- immediate: true,
271
- deep: true
272
- }
273
- },
274
- computed: {
275
- editorStyle() {
276
- let finalHeight = this.height;
277
- // 如果是数字,自动拼接 px 单位
278
- if (typeof finalHeight === 'number') {
279
- finalHeight = `${finalHeight}px`;
280
- }
281
-
282
- return {
283
- height: finalHeight,
284
- 'overflow-y': 'hidden'
285
- }
286
- }
287
- },
288
- methods: {
289
-
290
- onCreated(editor) {
291
- this.editor = Object.seal(editor)
292
- if (this.value) {
293
- this.editor.setHtml(this.value)
294
- }
295
- },
296
- onChange(editor) {
297
- let html = editor.getHtml()
298
- this.$emit('input', this.valueType === 'html' ? html : editor.getText())
299
- this.$emit('on-change', html, editor.getText())
300
- },
301
- },
302
-
303
- beforeDestroy() {
304
- const editor = this.editor
305
- if (editor == null) return
306
- editor.destroy() // 组件销毁时,及时销毁 editor ,重要!!!
307
- },
308
-
309
- }
310
- </script>
311
-
312
- <style lang="less" scoped>
313
- /deep/ .table-container {
314
- width: fit-content !important;
315
- margin: 10px auto !important;
316
- }
317
- </style>
1
+ <template>
2
+ <div style="z-index: 999">
3
+ <!-- 工具栏 -->
4
+ <Toolbar
5
+ :editor="editor"
6
+ :defaultConfig="toolbarConfig"
7
+ />
8
+ <!-- 编辑器 -->
9
+ <Editor
10
+ :style="editorStyle"
11
+ :defaultConfig="editorConfig"
12
+ v-model="html"
13
+ @onChange="onChange"
14
+ @onCreated="onCreated"
15
+ />
16
+ </div>
17
+ </template>
18
+
19
+ <script>
20
+ import '@wangeditor-next/editor/dist/css/style.css'
21
+ import {oneOf} from '@lambo-design/shared/utils/platform';
22
+ import {Editor, Toolbar} from '@wangeditor-next/editor-for-vue2'
23
+ import {Boot} from '@wangeditor-next/editor'
24
+ import {registerMenu} from './customHrMenu'
25
+ // 注册分割线颜色菜单(模块级别,只执行一次)
26
+ registerMenu(Boot)
27
+
28
+ export default {
29
+ name: 'WangEditor',
30
+ components: {Editor, Toolbar},
31
+ props: {
32
+ value: {
33
+ type: String,
34
+ default: ''
35
+ },
36
+ /**
37
+ * 绑定的值的类型, enum: ['html', 'text']
38
+ */
39
+ valueType: {
40
+ type: String,
41
+ default: 'html',
42
+ validator: (val) => {
43
+ return oneOf(val, ['html', 'text'])
44
+ }
45
+ },
46
+ /**
47
+ * @description 设置change事件触发时间间隔
48
+ */
49
+ changeInterval: {
50
+ type: Number,
51
+ default: 200
52
+ },
53
+ /**
54
+ * @description 是否开启本地存储
55
+ */
56
+ cache: {
57
+ type: Boolean,
58
+ default: true
59
+ },
60
+ /**
61
+ * @description 是否使用 base64 保存图片
62
+ */
63
+ uploadImgShowBase64: {
64
+ type: Boolean,
65
+ default: false
66
+ },
67
+ /**
68
+ * 上传图片上下文
69
+ */
70
+ ossServerContext: {
71
+ type: String,
72
+ default: ''
73
+ },
74
+ /**
75
+ * 上传图片Url地址
76
+ */
77
+ ossFilePutUrl: {
78
+ type: String,
79
+ default: "/oss/file/put"
80
+ },
81
+ /**
82
+ * 获取图片url地址
83
+ */
84
+ ossFileGetImgUrl: {
85
+ type: String,
86
+ default: "/oss/file/get/"
87
+ },
88
+ /**
89
+ * @description 是否保留粘贴内容的样式
90
+ */
91
+ preservePasteStyle: {
92
+ type: Boolean,
93
+ default: false
94
+ },
95
+
96
+ readOnly: {
97
+ type: Boolean,
98
+ default: false
99
+ },
100
+ /**
101
+ * @description: 隐藏菜单
102
+ */
103
+ hideMenu: {
104
+ type: Array,
105
+ default: () => []
106
+ },
107
+
108
+ height: {
109
+ type: [Number, String],
110
+ default: 400
111
+ }
112
+ },
113
+ data() {
114
+ return {
115
+ editor: null,
116
+ html: '',
117
+ hrCount: 0, // 追踪分割线数量
118
+ toolbarConfig: {
119
+ insertKeys: {
120
+ index: 24, // 在分割线菜单后面插入
121
+ keys: ['customHrMenu']
122
+ }
123
+ },
124
+ editorConfig: {
125
+ placeholder: '请输入内容...',
126
+ MENU_CONF: {
127
+ fontFamily: {
128
+ fontFamilyList: [
129
+ "黑体",
130
+ {
131
+ name: "仿宋",
132
+ value: "仿宋"
133
+ },
134
+ "仿宋_GB2312",
135
+ "楷体",
136
+ "楷体_GB2312",
137
+ "标楷体",
138
+ "华文仿宋",
139
+ "华文楷体",
140
+ {
141
+ name: "宋体",
142
+ value: "宋体"
143
+ }, "隶书", "方正小标宋简体", "思源宋体‌", "微软雅黑", "Arial", "Tahoma", "Verdana", "Times New Roman", "Courier New"]
144
+ },
145
+ color: {
146
+ colors: [
147
+ "rgb(0, 0, 0)",
148
+ "rgb(38, 38, 38)",
149
+ "rgb(89, 89, 89)",
150
+ "rgb(140, 140, 140)",
151
+ "rgb(191, 191, 191)",
152
+ "rgb(217, 217, 217)",
153
+ "rgb(233, 233, 233)",
154
+ "rgb(245, 245, 245)",
155
+ "rgb(250, 250, 250)",
156
+ "rgb(255, 255, 255)",
157
+ "rgb(225, 60, 57)",
158
+ "rgb(231, 95, 51)",
159
+ "rgb(235, 144, 58)",
160
+ "rgb(245, 219, 77)",
161
+ "rgb(114, 192, 64)",
162
+ "rgb(89, 191, 192)",
163
+ "rgb(66, 144, 247)",
164
+ "rgb(54, 88, 226)",
165
+ "rgb(106, 57, 201)",
166
+ "rgb(216, 68, 147)",
167
+ "rgb(251, 233, 230)",
168
+ "rgb(252, 237, 225)",
169
+ "rgb(252, 239, 212)",
170
+ "rgb(252, 251, 207)",
171
+ "rgb(231, 246, 213)",
172
+ "rgb(218, 244, 240)",
173
+ "rgb(217, 237, 250)",
174
+ "rgb(224, 232, 250)",
175
+ "rgb(237, 225, 248)",
176
+ "rgb(246, 226, 234)",
177
+ "rgb(255, 163, 158)",
178
+ "rgb(255, 187, 150)",
179
+ "rgb(255, 213, 145)",
180
+ "rgb(255, 251, 143)",
181
+ "rgb(183, 235, 143)",
182
+ "rgb(135, 232, 222)",
183
+ "rgb(145, 213, 255)",
184
+ "rgb(173, 198, 255)",
185
+ "rgb(211, 173, 247)",
186
+ "rgb(255, 173, 210)",
187
+ "rgb(255, 77, 79)",
188
+ "rgb(255, 122, 69)",
189
+ "rgb(255, 169, 64)",
190
+ "rgb(255, 236, 61)",
191
+ "rgb(115, 209, 61)",
192
+ "rgb(54, 207, 201)",
193
+ "rgb(64, 169, 255)",
194
+ "rgb(89, 126, 247)",
195
+ "rgb(146, 84, 222)",
196
+ "rgb(247, 89, 171)",
197
+ "rgb(207, 19, 34)",
198
+ "rgb(212, 56, 13)",
199
+ "rgb(212, 107, 8)",
200
+ "rgb(212, 177, 6)",
201
+ "rgb(56, 158, 13)",
202
+ "rgb(8, 151, 156)",
203
+ "rgb(9, 109, 217)",
204
+ "rgb(29, 57, 196)",
205
+ "rgb(83, 29, 171)",
206
+ "rgb(196, 29, 127)",
207
+ "rgb(130, 0, 20)",
208
+ "rgb(135, 20, 0)",
209
+ "rgb(135, 56, 0)",
210
+ "rgb(97, 71, 0)",
211
+ "rgb(19, 82, 0)",
212
+ "rgb(0, 71, 79)",
213
+ "rgb(0, 58, 140)",
214
+ "rgb(6, 17, 120)",
215
+ "rgb(34, 7, 94)",
216
+ "rgb(120, 6, 80)",
217
+ "rgb(250,64,6)"
218
+ ]
219
+ },
220
+ uploadImage: {
221
+ //上传图片配置
222
+ server: this.ossServerContext + this.ossFilePutUrl, //上传接口地址
223
+ fieldName: 'file', //上传文件名
224
+ methods: 'post',
225
+ metaWithUrl: true, // 参数拼接到 url 上
226
+ //自定义插入图片
227
+ customInsert: (res, insertFn) => {
228
+ let self = this;
229
+ const imgInfo = res.data[0] || {}
230
+ const {fileId, fileName, contentType} = imgInfo
231
+ insertFn(self.ossServerContext + self.ossFileGetImgUrl + fileId, fileName, self.ossServerContext + self.ossFileGetImgUrl + fileId)
232
+ },
233
+
234
+ },
235
+ }
236
+ }
237
+ }
238
+ },
239
+ watch: {
240
+ value: {
241
+ handler: function (newVal, oldVal) {
242
+ const isEmpty = !newVal || newVal === '<p><br></p>'
243
+ const wasEmpty = !oldVal || oldVal === '<p><br></p>'
244
+
245
+ if (!isEmpty && wasEmpty) {
246
+ if (this.valueType === 'html') {
247
+ this.editor.setHtml(this.normalizeTableBorderWidth(newVal));
248
+ } else {
249
+ this.editor.insertText(newVal)
250
+ }
251
+ }
252
+ }
253
+ },
254
+
255
+ readOnly: {
256
+ handler(newVal){
257
+ this.editorConfig.readOnly = newVal
258
+ if(newVal){
259
+ this.toolbarConfig.toolbarKeys = ['fullScreen']
260
+ }
261
+ },
262
+ immediate: true,
263
+ },
264
+
265
+ hideMenu: {
266
+ handler(newVal){
267
+ this.toolbarConfig.excludeKeys = newVal
268
+ },
269
+ immediate: true,
270
+ deep: true
271
+ }
272
+ },
273
+ computed: {
274
+ editorStyle() {
275
+ let finalHeight = this.height;
276
+ // 如果是数字,自动拼接 px 单位
277
+ if (typeof finalHeight === 'number') {
278
+ finalHeight = `${finalHeight}px`;
279
+ }
280
+
281
+ return {
282
+ height: finalHeight,
283
+ 'overflow-y': 'hidden'
284
+ }
285
+ }
286
+ },
287
+ methods: {
288
+
289
+ normalizeTableBorderWidth(value) {
290
+ let html = value;
291
+ // 正则匹配 <table>...</table> 区域
292
+ const tableRegex = /(<table)([\s\S]*?)(<\/table>)/gi;
293
+ // 替换表格区域中的 border-width: **px;
294
+ html = html.replace(tableRegex, (match, startTag, content, endTag) => {
295
+ // 只对表格内容进行替换
296
+ const updatedContent = content.replace(/border-width:\s*(\d+)px;/g, 'border-width: $1;');
297
+ return `${startTag}${updatedContent}${endTag}`;
298
+ });
299
+
300
+ // 标记已存表格
301
+ const tempDiv = document.createElement('div'); // 创建临时容器解析 HTML
302
+ tempDiv.innerHTML = html;
303
+ const tables = tempDiv.querySelectorAll('table');
304
+ tables.forEach(table => {
305
+ table.setAttribute('data-processed', 'true');
306
+ });
307
+ return tempDiv.innerHTML;
308
+ },
309
+
310
+ onCreated(editor) {
311
+ this.editor = Object.seal(editor)
312
+ if (this.value) {
313
+ this.editor.setHtml(this.normalizeTableBorderWidth(this.value))
314
+ }
315
+ },
316
+ onChange(editor) {
317
+ let html = editor.getHtml()
318
+ this.$emit('input', this.valueType === 'html' ? html : editor.getText())
319
+ this.$emit('on-change', html, editor.getText())
320
+ },
321
+ },
322
+
323
+ beforeDestroy() {
324
+ const editor = this.editor
325
+ if (editor == null) return
326
+ editor.destroy() // 组件销毁时,及时销毁 editor ,重要!!!
327
+ },
328
+
329
+ }
330
+ </script>
331
+
332
+ <style lang="less" scoped>
333
+ /deep/ .table-container {
334
+ width: fit-content !important;
335
+ margin: 10px auto !important;
336
+ }
337
+ </style>