@sy-common/wang-editor 1.0.0-beta.2 → 1.0.0-beta.21

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sy-common/wang-editor",
3
- "version": "1.0.0-beta.2",
3
+ "version": "1.0.0-beta.21",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "author": "lambo",
@@ -9,13 +9,15 @@
9
9
  "access": "public",
10
10
  "registry": "https://registry.npmjs.org/"
11
11
  },
12
- "devDependencies": {
13
- "@lambo-design/core": "^4.7.1-beta.140",
12
+ "dependencies": {
14
13
  "@wangeditor-next/editor": "^5.6.0",
15
14
  "@wangeditor-next/editor-for-vue2": "^1.0.2"
16
15
  },
16
+ "devDependencies": {
17
+ "@lambo-design/core": "^4.7.1-beta.140"
18
+ },
17
19
  "scripts": {
18
- "release-upload-file": "pnpm release-beta && git push --follow-tags && pnpm re-publish",
20
+ "release": "pnpm release-beta && git push --follow-tags && pnpm re-publish",
19
21
  "release-major": "standard-version --release-as major",
20
22
  "release-minor": "standard-version --release-as minor",
21
23
  "release-patch": "standard-version --release-as patch",
@@ -0,0 +1,177 @@
1
+ /**
2
+ * 分割线颜色菜单插件
3
+ */
4
+
5
+ const MENU_KEY = 'hrColor'
6
+
7
+ // 颜色列表
8
+ const COLOR_LIST = [
9
+ '',
10
+ 'rgb(0, 0, 0)',
11
+ 'rgb(38, 38, 38)',
12
+ 'rgb(89, 89, 89)',
13
+ 'rgb(140, 140, 140)',
14
+ 'rgb(191, 191, 191)',
15
+ 'rgb(225, 60, 57)',
16
+ 'rgb(231, 95, 51)',
17
+ 'rgb(235, 144, 58)',
18
+ 'rgb(245, 219, 77)',
19
+ 'rgb(114, 192, 64)',
20
+ 'rgb(89, 191, 192)',
21
+ 'rgb(66, 144, 247)',
22
+ 'rgb(54, 88, 226)',
23
+ 'rgb(106, 57, 201)',
24
+ 'rgb(216, 68, 147)',
25
+ ]
26
+
27
+ // 图标 SVG:分割线 + 彩色条
28
+ const HR_COLOR_SVG = '<svg viewBox="0 0 1092 1024"><path d="M0 51.2m51.2 0l989.866667 0q51.2 0 51.2 51.2l0 0q0 51.2-51.2 51.2l-989.866667 0q-51.2 0-51.2-51.2l0 0q0 51.2 51.2-51.2Z" fill="#999"/><path d="M0 460.8m51.2 0l170.666667 0q51.2 0 51.2 51.2l0 0q0 51.2-51.2 51.2l-170.666667 0q-51.2 0-51.2-51.2l0 0q0 51.2 51.2-51.2Z" fill="#ff4d4f"/><path d="M273 460.8m51.2 0l170.666667 0q51.2 0 51.2 51.2l0 0q0 51.2-51.2 51.2l-170.666667 0q-51.2 0-51.2-51.2l0 0q0 51.2 51.2-51.2Z" fill="#faad14"/><path d="M546 460.8m51.2 0l170.666667 0q51.2 0 51.2 51.2l0 0q0 51.2-51.2 51.2l-170.666667 0q-51.2 0-51.2-51.2l0 0q0 51.2 51.2-51.2Z" fill="#52c41a"/><path d="M819 460.8m51.2 0l170.666667 0q51.2 0 51.2 51.2l0 0q0 51.2-51.2 51.2l-170.666667 0q-51.2 0-51.2-51.2l0 0q0 51.2 51.2-51.2Z" fill="#1890ff"/><path d="M0 870.4m51.2 0l989.866667 0q51.2 0 51.2 51.2l0 0q0 51.2-51.2 51.2l-989.866667 0q-51.2 0-51.2-51.2l0 0q0 51.2 51.2-51.2Z" fill="#999"/></svg>'
29
+
30
+ function checkHrSelected(editor) {
31
+ if (editor.isDisabled()) return false
32
+ if (!editor.selection) return false
33
+ try {
34
+ const nodeGen = editor.nodes({ match: n => n.type === 'divider', universal: true })
35
+ for (const [node] of nodeGen) {
36
+ if (node) return true
37
+ }
38
+ } catch (e) {}
39
+ return false
40
+ }
41
+
42
+ function getDividerCurrentColor(editor) {
43
+ try {
44
+ const [nodeEntry] = editor.nodes({ match: n => n.type === 'divider', universal: true })
45
+ if (!nodeEntry) return ''
46
+ const [node] = nodeEntry
47
+ const domNode = editor.toDOMNode(node)
48
+ if (domNode) {
49
+ const hrElement = domNode.querySelector('hr') || domNode
50
+ return hrElement.getAttribute('data-divider-color') || ''
51
+ }
52
+ } catch (e) {}
53
+ return ''
54
+ }
55
+
56
+ function setDividerColor(editor, color) {
57
+ try {
58
+ const [nodeEntry] = editor.nodes({ match: n => n.type === 'divider', universal: true })
59
+ if (!nodeEntry) return
60
+ const [node] = nodeEntry
61
+
62
+ const domNode = editor.toDOMNode(node)
63
+ if (domNode) {
64
+ const hrElement = domNode.querySelector('hr') || domNode
65
+ if (color) {
66
+ hrElement.style.border = 'none'
67
+ hrElement.style.borderTop = '2px solid ' + color
68
+ hrElement.style.margin = '10px 0'
69
+ hrElement.setAttribute('data-divider-color', color)
70
+ } else {
71
+ hrElement.style.border = ''
72
+ hrElement.style.borderTop = ''
73
+ hrElement.style.margin = ''
74
+ hrElement.removeAttribute('data-divider-color')
75
+ }
76
+ }
77
+ } catch (e) {
78
+ console.warn('setDividerColor error:', e)
79
+ }
80
+ editor.emit('change')
81
+ }
82
+
83
+ // 创建颜色选择面板
84
+ function createColorPanel() {
85
+ const $content = document.createElement('div')
86
+ $content.style.cssText = 'padding: 10px; display: flex; flex-wrap: wrap; gap: 4px; width: 200px;'
87
+
88
+ COLOR_LIST.forEach(color => {
89
+ const $item = document.createElement('button')
90
+ $item.type = 'button'
91
+ $item.style.cssText = color
92
+ ? 'width: 24px; height: 24px; border: 1px solid #d9d9d9; border-radius: 4px; cursor: pointer; background-color: ' + color + ';'
93
+ : 'width: 24px; height: 24px; border: 2px dashed #d9d9d9; border-radius: 4px; cursor: pointer; background: transparent;'
94
+ $item.setAttribute('data-color', color || '')
95
+ $content.appendChild($item)
96
+ })
97
+
98
+ return $content
99
+ }
100
+
101
+ // 从 HTML 提取所有 hr 的颜色
102
+ function extractHrColorsFromHtml(html) {
103
+ const colors = []
104
+ const tempDiv = document.createElement('div')
105
+ tempDiv.innerHTML = html
106
+ const hrs = tempDiv.querySelectorAll('hr')
107
+ hrs.forEach(hr => {
108
+ const style = hr.getAttribute('style') || ''
109
+ const colorMatch = style.match(/border-top\s*:\s*\d+px\s+solid\s+(rgb\([^)]+\)|#[a-fA-F0-9]+)/i)
110
+ colors.push(colorMatch ? colorMatch[1] : '')
111
+ })
112
+ return colors
113
+ }
114
+
115
+ function registerHrColorMenu(Boot) {
116
+ const menuConf = {
117
+ key: MENU_KEY,
118
+ factory() {
119
+ let $panel = null
120
+
121
+ return {
122
+ title: '分割线颜色',
123
+ iconSvg: HR_COLOR_SVG,
124
+ tag: 'button',
125
+ showDropPanel: true,
126
+
127
+ isDisabled(editor) {
128
+ return !checkHrSelected(editor)
129
+ },
130
+
131
+ isActive(editor) {
132
+ return false
133
+ },
134
+
135
+ getValue(editor) {
136
+ return getDividerCurrentColor(editor)
137
+ },
138
+
139
+ exec(editor, value) {
140
+ setDividerColor(editor, value)
141
+ },
142
+
143
+ getPanelContentElem(editor) {
144
+ if (!$panel) {
145
+ $panel = createColorPanel()
146
+ $panel.querySelectorAll('button').forEach(btn => {
147
+ btn.addEventListener('click', () => {
148
+ const color = btn.getAttribute('data-color')
149
+ setDividerColor(editor, color)
150
+ editor.hidePanelOrModal()
151
+ })
152
+ })
153
+ }
154
+ return $panel
155
+ }
156
+ }
157
+ }
158
+ }
159
+
160
+ try {
161
+ Boot.registerMenu(menuConf)
162
+ } catch (e) {
163
+ if (!e.message.includes('already') && !e.message.includes('duplicate')) {
164
+ console.warn('HrColorMenu register warning:', e.message)
165
+ }
166
+ }
167
+ }
168
+
169
+ export {
170
+ MENU_KEY,
171
+ COLOR_LIST,
172
+ registerHrColorMenu,
173
+ checkHrSelected,
174
+ getDividerCurrentColor,
175
+ setDividerColor,
176
+ extractHrColorsFromHtml
177
+ }
package/src/index.vue CHANGED
@@ -1,17 +1,17 @@
1
1
  <template>
2
- <div >
2
+ <div style="z-index: 999">
3
3
  <!-- 工具栏 -->
4
4
  <Toolbar
5
- :editor="editor"
6
- :defaultConfig="toolbarConfig"
5
+ :editor="editor"
6
+ :defaultConfig="toolbarConfig"
7
7
  />
8
8
  <!-- 编辑器 -->
9
9
  <Editor
10
- style="height: 400px; overflow-y: hidden;"
11
- :defaultConfig="editorConfig"
12
- v-model="html"
13
- @onChange="onChange"
14
- @onCreated="onCreated"
10
+ :style="editorStyle"
11
+ :defaultConfig="editorConfig"
12
+ v-model="html"
13
+ @onChange="onChange"
14
+ @onCreated="onCreated"
15
15
  />
16
16
  </div>
17
17
  </template>
@@ -19,11 +19,16 @@
19
19
  <script>
20
20
  import '@wangeditor-next/editor/dist/css/style.css'
21
21
  import {oneOf} from '@lambo-design/shared/utils/platform';
22
- import { Editor, Toolbar } from '@wangeditor-next/editor-for-vue2'
22
+ import {Editor, Toolbar} from '@wangeditor-next/editor-for-vue2'
23
+ import {Boot} from '@wangeditor-next/editor'
24
+ import {registerHrColorMenu, MENU_KEY, extractHrColorsFromHtml} from './hr-color-menu'
25
+
26
+ // 注册分割线颜色菜单(模块级别,只执行一次)
27
+ registerHrColorMenu(Boot)
23
28
 
24
29
  export default {
25
30
  name: 'WangEditor',
26
- components: { Editor, Toolbar },
31
+ components: {Editor, Toolbar},
27
32
  props: {
28
33
  value: {
29
34
  type: String,
@@ -89,32 +94,143 @@ export default {
89
94
  default: false
90
95
  },
91
96
 
97
+ readOnly: {
98
+ type: Boolean,
99
+ default: false
100
+ },
101
+ /**
102
+ * @description: 隐藏菜单
103
+ */
104
+ hideMenu: {
105
+ type: Array,
106
+ default: () => []
107
+ },
108
+
109
+ height: {
110
+ type: [Number, String],
111
+ default: 400
112
+ }
92
113
  },
93
114
  data() {
94
115
  return {
95
116
  editor: null,
96
117
  html: '',
118
+ hrCount: 0, // 追踪分割线数量
97
119
  toolbarConfig: {
98
- // toolbarKeys: [ /* 显示哪些菜单,如何排序、分组 */ ],
99
- // excludeKeys: [ /* 隐藏哪些菜单 */ ],
120
+ insertKeys: {
121
+ index: 24, // 在分割线菜单后面插入
122
+ keys: [MENU_KEY]
123
+ }
100
124
  },
101
125
  editorConfig: {
102
126
  placeholder: '请输入内容...',
103
127
  MENU_CONF: {
104
-
128
+ fontFamily: {
129
+ fontFamilyList: [
130
+ "黑体",
131
+ {
132
+ name: "仿宋",
133
+ value: "仿宋"
134
+ },
135
+ "仿宋_GB2312",
136
+ "楷体",
137
+ "楷体_GB2312",
138
+ "标楷体",
139
+ "华文仿宋",
140
+ "华文楷体",
141
+ {
142
+ name: "宋体",
143
+ value: "宋体"
144
+ }, "隶书", "方正小标宋简体", "思源宋体‌", "微软雅黑", "Arial", "Tahoma", "Verdana", "Times New Roman", "Courier New"]
145
+ },
146
+ color: {
147
+ colors: [
148
+ "rgb(0, 0, 0)",
149
+ "rgb(38, 38, 38)",
150
+ "rgb(89, 89, 89)",
151
+ "rgb(140, 140, 140)",
152
+ "rgb(191, 191, 191)",
153
+ "rgb(217, 217, 217)",
154
+ "rgb(233, 233, 233)",
155
+ "rgb(245, 245, 245)",
156
+ "rgb(250, 250, 250)",
157
+ "rgb(255, 255, 255)",
158
+ "rgb(225, 60, 57)",
159
+ "rgb(231, 95, 51)",
160
+ "rgb(235, 144, 58)",
161
+ "rgb(245, 219, 77)",
162
+ "rgb(114, 192, 64)",
163
+ "rgb(89, 191, 192)",
164
+ "rgb(66, 144, 247)",
165
+ "rgb(54, 88, 226)",
166
+ "rgb(106, 57, 201)",
167
+ "rgb(216, 68, 147)",
168
+ "rgb(251, 233, 230)",
169
+ "rgb(252, 237, 225)",
170
+ "rgb(252, 239, 212)",
171
+ "rgb(252, 251, 207)",
172
+ "rgb(231, 246, 213)",
173
+ "rgb(218, 244, 240)",
174
+ "rgb(217, 237, 250)",
175
+ "rgb(224, 232, 250)",
176
+ "rgb(237, 225, 248)",
177
+ "rgb(246, 226, 234)",
178
+ "rgb(255, 163, 158)",
179
+ "rgb(255, 187, 150)",
180
+ "rgb(255, 213, 145)",
181
+ "rgb(255, 251, 143)",
182
+ "rgb(183, 235, 143)",
183
+ "rgb(135, 232, 222)",
184
+ "rgb(145, 213, 255)",
185
+ "rgb(173, 198, 255)",
186
+ "rgb(211, 173, 247)",
187
+ "rgb(255, 173, 210)",
188
+ "rgb(255, 77, 79)",
189
+ "rgb(255, 122, 69)",
190
+ "rgb(255, 169, 64)",
191
+ "rgb(255, 236, 61)",
192
+ "rgb(115, 209, 61)",
193
+ "rgb(54, 207, 201)",
194
+ "rgb(64, 169, 255)",
195
+ "rgb(89, 126, 247)",
196
+ "rgb(146, 84, 222)",
197
+ "rgb(247, 89, 171)",
198
+ "rgb(207, 19, 34)",
199
+ "rgb(212, 56, 13)",
200
+ "rgb(212, 107, 8)",
201
+ "rgb(212, 177, 6)",
202
+ "rgb(56, 158, 13)",
203
+ "rgb(8, 151, 156)",
204
+ "rgb(9, 109, 217)",
205
+ "rgb(29, 57, 196)",
206
+ "rgb(83, 29, 171)",
207
+ "rgb(196, 29, 127)",
208
+ "rgb(130, 0, 20)",
209
+ "rgb(135, 20, 0)",
210
+ "rgb(135, 56, 0)",
211
+ "rgb(97, 71, 0)",
212
+ "rgb(19, 82, 0)",
213
+ "rgb(0, 71, 79)",
214
+ "rgb(0, 58, 140)",
215
+ "rgb(6, 17, 120)",
216
+ "rgb(34, 7, 94)",
217
+ "rgb(120, 6, 80)",
218
+ "rgb(250,64,6)"
219
+ ]
220
+ },
105
221
  uploadImage: {
106
222
  //上传图片配置
107
- server: this.ossServerContext+this.ossFilePutUrl, //上传接口地址
223
+ server: this.ossServerContext + this.ossFilePutUrl, //上传接口地址
108
224
  fieldName: 'file', //上传文件名
109
225
  methods: 'post',
110
226
  metaWithUrl: true, // 参数拼接到 url 上
111
227
  //自定义插入图片
112
- customInsert:(res, insertFn)=>{
228
+ customInsert: (res, insertFn) => {
113
229
  let self = this;
114
230
  const imgInfo = res.data[0] || {}
115
- const { fileId, fileName, contentType } = imgInfo
231
+ const {fileId, fileName, contentType} = imgInfo
116
232
  insertFn(self.ossServerContext + self.ossFileGetImgUrl + fileId, fileName, self.ossServerContext + self.ossFileGetImgUrl + fileId)
117
- } ,
233
+ },
118
234
 
119
235
  },
120
236
  }
@@ -124,37 +240,191 @@ export default {
124
240
  watch: {
125
241
  value: {
126
242
  handler: function (newVal, oldVal) {
127
- // console.log('watch',newVal+" "+oldVal)
128
- if (oldVal === '') {
243
+ // 初次赋值或从空内容变为有内容时处理
244
+ const isEmpty = !newVal || newVal === '<p><br></p>'
245
+ const wasEmpty = !oldVal || oldVal === '<p><br></p>'
246
+
247
+ if (!isEmpty && wasEmpty) {
129
248
  if (this.valueType === 'html') {
130
- this.editor.setHtml(newVal)
249
+ let html = newVal;
250
+
251
+ // 先从 HTML 提取所有 hr 的颜色
252
+ const hrColors = extractHrColorsFromHtml(html)
253
+
254
+ // 正则匹配 <table>...</table> 区域
255
+ const tableRegex = /(<table)([\s\S]*?)(<\/table>)/gi;
256
+ // 替换表格区域中的 borderWidth: **px;
257
+ html = html.replace(tableRegex, (match, startTag, content, endTag) => {
258
+ // 只对表格内容进行替换
259
+ const updatedContent = content.replace(/border-width:\s*(\d+)px;/g, 'border-width: $1;');
260
+ return `${startTag}${updatedContent}${endTag}`;
261
+ });
262
+
263
+ // 标记已存表格
264
+ const tempDiv = document.createElement('div'); // 创建临时容器解析 HTML
265
+ tempDiv.innerHTML = html;
266
+ const tables = tempDiv.querySelectorAll('table');
267
+ tables.forEach(table => {
268
+ table.setAttribute('data-processed', 'true');
269
+ });
270
+ // 更新处理后的 HTML
271
+ this.editor.setHtml(tempDiv.innerHTML)
272
+
273
+ // setHtml 后设置 hr 颜色到 DOM
274
+ if (hrColors.length > 0) {
275
+ // 用 setTimeout 等待 DOM 渲染完成
276
+ setTimeout(() => {
277
+ try {
278
+ const container = this.editor.getEditableContainer()
279
+ if (!container) return
280
+ const hrs = container.querySelectorAll('hr')
281
+ hrs.forEach((hr, index) => {
282
+ const color = hrColors[index] || ''
283
+ if (color) {
284
+ hr.style.border = 'none'
285
+ hr.style.borderTop = '2px solid ' + color
286
+ hr.style.margin = '10px 0'
287
+ hr.setAttribute('data-divider-color', color)
288
+ }
289
+ })
290
+ } catch (e) {
291
+ console.warn('设置 hr 颜色失败:', e)
292
+ }
293
+ }, 100)
294
+ }
131
295
  } else {
132
296
  this.editor.insertText(newVal)
133
297
  }
134
298
  }
135
299
  }
136
300
  },
301
+
302
+ readOnly: {
303
+ handler(newVal){
304
+ this.editorConfig.readOnly = newVal
305
+ if(newVal){
306
+ this.toolbarConfig.toolbarKeys = ['fullScreen']
307
+ }
308
+ },
309
+ immediate: true,
310
+ },
311
+
312
+ hideMenu: {
313
+ handler(newVal){
314
+ this.toolbarConfig.excludeKeys = newVal
315
+ },
316
+ immediate: true,
317
+ deep: true
318
+ }
137
319
  },
138
320
  computed: {
139
- // editorId() {
140
- // return `editor${this._uid}`
141
- // }
321
+ editorStyle() {
322
+ let finalHeight = this.height;
323
+ // 如果是数字,自动拼接 px 单位
324
+ if (typeof finalHeight === 'number') {
325
+ finalHeight = `${finalHeight}px`;
326
+ }
327
+
328
+ return {
329
+ height: finalHeight,
330
+ 'overflow-y': 'hidden'
331
+ }
332
+ }
142
333
  },
143
334
  methods: {
144
335
 
145
336
  onCreated(editor) {
146
337
  this.editor = Object.seal(editor) // 【注意】一定要用 Object.seal() 否则会报错
147
- // 如果本地有存储加载本地存储内容
338
+
148
339
  let html = this.value
149
- if (html) this.editor.setHtml(html)
340
+ if (html) {
341
+ this.editor.setHtml(html)
342
+ // 处理已有颜色的 hr 元素,从 style 中提取颜色
343
+ this.$nextTick(() => {
344
+ try {
345
+ const container = this.editor.getEditableContainer()
346
+ if (!container) return
347
+ const hrs = container.querySelectorAll('hr')
348
+ // 初始化 hrCount,记录已有分割线数量
349
+ this.hrCount = hrs.length
350
+ hrs.forEach(hr => {
351
+ const style = hr.getAttribute('style') || ''
352
+ // 匹配 border 中的颜色
353
+ const colorMatch = style.match(/border\s*:[^;]*solid\s+(rgb\([^)]+\)|#[a-fA-F0-9]+)/i)
354
+ if (colorMatch) {
355
+ hr.setAttribute('data-divider-color', colorMatch[1])
356
+ }
357
+ })
358
+ } catch (e) {
359
+ console.warn('处理已存在 hr 颜色失败:', e)
360
+ }
361
+ })
362
+ }
150
363
  },
151
364
  onChange(editor) {
152
365
  let self = this;
153
366
  let html = this.editor.getHtml()
154
- if (html.includes('table')){
155
- html = html.replace(/<table /g,'<table class="wangeditor-styled-table" style= "border-collapse: collapse;"'); // 添加边框)
367
+
368
+ // 创建一个临时的 div 容器来解析 HTML
369
+ const tempDiv = document.createElement('div');
370
+ tempDiv.innerHTML = html;
371
+
372
+ // 从编辑器 DOM 获取所有 hr 的颜色,写入输出 HTML
373
+ const editorContainer = this.editor.getEditableContainer()
374
+ const editorHrs = editorContainer ? editorContainer.querySelectorAll('hr') : []
375
+ const outputHrs = tempDiv.querySelectorAll('hr')
376
+
377
+ // 检测新增的分割线,设置默认颜色
378
+ const DEFAULT_HR_COLOR = 'rgb(250, 64, 6)'
379
+ if (editorHrs.length > this.hrCount) {
380
+ // 有新增的分割线
381
+ for (let i = this.hrCount; i < editorHrs.length; i++) {
382
+ const hr = editorHrs[i]
383
+ hr.style.border = 'none'
384
+ hr.style.borderTop = '2px solid ' + DEFAULT_HR_COLOR
385
+ hr.style.margin = '10px 0'
386
+ hr.setAttribute('data-divider-color', DEFAULT_HR_COLOR)
387
+ }
388
+ this.hrCount = editorHrs.length
156
389
  }
157
- console.log(html)
390
+
391
+ editorHrs.forEach((hr, index) => {
392
+ const color = hr.getAttribute('data-divider-color') || ''
393
+ if (color && outputHrs[index]) {
394
+ outputHrs[index].setAttribute('style', 'border: none; border-top: 2px solid ' + color + '; margin: 10px 0;')
395
+ }
396
+ })
397
+
398
+ // 处理 table 元素 -- 查找新增的表格并添加默认样式
399
+ const tables = tempDiv.querySelectorAll('table:not([data-processed])');
400
+ tables.forEach(table => {
401
+ const currentStyle = table.getAttribute('style') || '';
402
+ const newStyle = `border-collapse: collapse;border-style: solid; border-color: rgb(204, 204, 204);border-width: 1;${currentStyle}`.trim();
403
+ table.setAttribute('class', 'wangeditor-styled-table');
404
+ table.setAttribute('style', newStyle);
405
+
406
+ // 处理表头
407
+ const thCells = table.querySelectorAll('th');
408
+ thCells.forEach(cell => {
409
+ const cellCurrentStyle = cell.getAttribute('style') || '';
410
+ const cellNewStyle = `background-color: rgb(245, 242, 240);border-style: solid; border-color: rgb(204, 204, 204);border-width: 1;padding: 3px 5px;${cellCurrentStyle}`.trim();
411
+ cell.setAttribute('style', cellNewStyle);
412
+ });
413
+
414
+ // 处理单元格
415
+ const tdCells = table.querySelectorAll('td');
416
+ tdCells.forEach(cell => {
417
+ const cellCurrentStyle = cell.getAttribute('style') || '';
418
+ const cellNewStyle = `border-style: solid; border-color: rgb(204, 204, 204);border-width: 1;padding: 3px 5px;${cellCurrentStyle}`.trim();
419
+ cell.setAttribute('style', cellNewStyle);
420
+ });
421
+
422
+ // 标记已处理
423
+ table.setAttribute('data-processed', 'true');
424
+ });
425
+
426
+ // 更新处理后的 HTML
427
+ html = tempDiv.innerHTML;
158
428
  this.$emit('input', self.valueType === 'html' ? html : editor.getText())
159
429
  this.$emit('on-change', html, editor.getText())
160
430
  },
@@ -187,3 +457,10 @@ export default {
187
457
 
188
458
  }
189
459
  </script>
460
+
461
+ <style lang="less" scoped>
462
+ /deep/ .table-container {
463
+ width: fit-content !important;
464
+ margin: 10px auto !important;
465
+ }
466
+ </style>