vue-editify 0.1.3 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,1214 +1,1214 @@
1
- <template>
2
- <Layer v-model="show" ref="layer" :node="node" border placement="bottom-start" @show="layerShow" :useRange="type == 'text'">
3
- <div class="editify-toolbar" ref="toolbar" :style="config.style">
4
- <!-- 链接工具条 -->
5
- <template v-if="type == 'link'">
6
- <div class="editify-toolbar-link">
7
- <div class="editify-toolbar-link-label">{{ $editTrans('linkAddress') }}</div>
8
- <input @change="modifyLink" @focus="handleInputFocus" @blur="handleInputBlur" :placeholder="$editTrans('linkUrlEnterPlaceholder')" v-model.trim="linkConfig.url" type="url" />
9
- <div class="editify-toolbar-link-footer">
10
- <Checkbox @change="modifyLink" v-model="linkConfig.newOpen" :label="$editTrans('newWindowOpen')" :color="$parent.color" :size="10"></Checkbox>
11
- <div class="editify-toolbar-link-operations">
12
- <span @click="removeLink">{{ $editTrans('removeLink') }}</span>
13
- <a :href="linkConfig.url" target="_blank" :style="{ color: $parent.color }">{{ $editTrans('viewLink') }}</a>
14
- </div>
15
- </div>
16
- </div>
17
- </template>
18
- <!-- 图片工具条 -->
19
- <template v-else-if="type == 'image'">
20
- <!-- 设置宽度30% -->
21
- <Button @operate="setWidth('30%')" name="set30Width" :title="$editTrans('width30')" :tooltip="config.tooltip" :color="$parent.color"> 30% </Button>
22
- <!-- 设置宽度50% -->
23
- <Button @operate="setWidth('50%')" name="set50Width" :title="$editTrans('width50')" :tooltip="config.tooltip" :color="$parent.color"> 50% </Button>
24
- <!-- 设置宽度100% -->
25
- <Button rightBorder @operate="setWidth('100%')" name="set100Width" :title="$editTrans('width100')" :tooltip="config.tooltip" :color="$parent.color"> 100% </Button>
26
- <!-- 设置宽度auto -->
27
- <Button @operate="setWidth('auto')" name="setAutoWidth" :title="$editTrans('auto')" :tooltip="config.tooltip" :color="$parent.color">
28
- <Icon value="auto-width"></Icon>
29
- </Button>
30
- <!-- 删除图片 -->
31
- <Button @operate="deleteElement('img')" name="deleteImage" :title="$editTrans('deleteImage')" :tooltip="config.tooltip" :color="$parent.color">
32
- <Icon value="delete"></Icon>
33
- </Button>
34
- </template>
35
- <!-- 视频工具条 -->
36
- <template v-else-if="type == 'video'">
37
- <!-- 设置宽度30% -->
38
- <Button @operate="setWidth('30%')" name="set30Width" :title="$editTrans('width30')" :tooltip="config.tooltip" :color="$parent.color"> 30% </Button>
39
- <!-- 设置宽度50% -->
40
- <Button @operate="setWidth('50%')" name="set50Width" :title="$editTrans('width50')" :tooltip="config.tooltip" :color="$parent.color"> 50% </Button>
41
- <!-- 设置宽度100% -->
42
- <Button @operate="setWidth('100%')" name="set100Width" :title="$editTrans('width100')" :tooltip="config.tooltip" :color="$parent.color"> 100% </Button>
43
- <!-- 设置宽度auto -->
44
- <Button rightBorder @operate="setWidth('auto')" name="setAutoWidth" :title="$editTrans('auto')" :tooltip="config.tooltip" :color="$parent.color">
45
- <Icon value="auto-width"></Icon>
46
- </Button>
47
- <!-- 自动播放 -->
48
- <Button @operate="setVideo" name="autoplay" :title="videoConfig.autoplay ? $editTrans('disabledAutoplay') : $editTrans('autoplay')" :tooltip="config.tooltip" :color="$parent.color">
49
- <Icon :value="videoConfig.autoplay ? 'autoplay' : 'stop'"></Icon>
50
- </Button>
51
- <!-- 循环播放 -->
52
- <Button @operate="setVideo" name="loop" :title="videoConfig.loop ? $editTrans('disabledLoop') : $editTrans('loop')" :tooltip="config.tooltip" :color="$parent.color">
53
- <Icon :value="videoConfig.loop ? 'loop' : 'single'"></Icon>
54
- </Button>
55
- <!-- 是否静音 -->
56
- <Button @operate="setVideo" name="muted" :title="videoConfig.muted ? $editTrans('unmuted') : $editTrans('muted')" :tooltip="config.tooltip" :color="$parent.color">
57
- <Icon :value="videoConfig.muted ? 'muted' : 'unmuted'"></Icon>
58
- </Button>
59
- <!-- 是否显示控制器 -->
60
- <Button leftBorder @operate="setVideo" name="controls" :title="$editTrans('controls')" :tooltip="config.tooltip" :color="$parent.color">
61
- <Icon value="controls"></Icon>
62
- </Button>
63
- <!-- 删除视频 -->
64
- <Button @operate="deleteElement('video')" name="deleteVideo" :title="$editTrans('deleteVideo')" :tooltip="config.tooltip" :color="$parent.color">
65
- <Icon value="delete"></Icon>
66
- </Button>
67
- </template>
68
- <!-- 表格工具条 -->
69
- <template v-else-if="type == 'table'">
70
- <!-- 表格前插入段落 -->
71
- <Button @operate="insertParagraphWithTable('up')" name="textWrapUp" :title="$editTrans('textWrapUp')" :tooltip="config.tooltip" :color="$parent.color">
72
- <Icon value="text-wrap" class="editify-icon-rotate"></Icon>
73
- </Button>
74
- <!-- 表格后插入段落 -->
75
- <Button @operate="insertParagraphWithTable('down')" rightBorder name="textWrapDown" :title="$editTrans('textWrapDown')" :tooltip="config.tooltip" :color="$parent.color">
76
- <Icon value="text-wrap"></Icon>
77
- </Button>
78
- <!-- 向前插入行 -->
79
- <Button @operate="insertTableRow('up')" name="insertRowTop" :title="$editTrans('insertRowTop')" :tooltip="config.tooltip" :color="$parent.color">
80
- <Icon value="insert-row-top"></Icon>
81
- </Button>
82
- <!-- 向后插入行 -->
83
- <Button @operate="insertTableRow('down')" name="insertRowBottom" :title="$editTrans('insertRowBottom')" :tooltip="config.tooltip" :color="$parent.color">
84
- <Icon value="insert-row-bottom"></Icon>
85
- </Button>
86
- <!-- 删除行 -->
87
- <Button @operate="deleteTableRow" rightBorder name="deleteRow" :title="$editTrans('deleteRow')" :tooltip="config.tooltip" :color="$parent.color">
88
- <Icon value="delete-row"></Icon>
89
- </Button>
90
- <!-- 向前插入列 -->
91
- <Button @operate="insertTableColumn('left')" name="insertColumnLeft" :title="$editTrans('insertColumnLeft')" :tooltip="config.tooltip" :color="$parent.color">
92
- <Icon value="insert-column-left"></Icon>
93
- </Button>
94
- <!-- 向后插入列 -->
95
- <Button @operate="insertTableColumn('right')" name="insertColumnRight" :title="$editTrans('insertColumnRight')" :tooltip="config.tooltip" :color="$parent.color">
96
- <Icon value="insert-column-right"></Icon>
97
- </Button>
98
- <!-- 删除列 -->
99
- <Button @operate="deleteTableColumn" rightBorder name="deleteColumn" :title="$editTrans('deleteColumn')" :tooltip="config.tooltip" :color="$parent.color">
100
- <Icon value="delete-column"></Icon>
101
- </Button>
102
- <!-- 删除表格 -->
103
- <Button @operate="deleteElement('table')" name="deleteTable" :title="$editTrans('deleteTable')" :tooltip="config.tooltip" :color="$parent.color">
104
- <Icon value="delete-table"></Icon>
105
- </Button>
106
- </template>
107
- <!-- 代码块工具条 -->
108
- <template v-if="type == 'codeBlock'">
109
- <!-- 代码块前插入段落 -->
110
- <Button @operate="insertParagraphWithPre('up')" name="textWrapUp" :title="$editTrans('textWrapUp')" :tooltip="config.tooltip" :color="$parent.color">
111
- <Icon value="text-wrap" class="editify-icon-rotate"></Icon>
112
- </Button>
113
- <!-- 代码块后插入段落 -->
114
- <Button @operate="insertParagraphWithPre('down')" name="textWrapDown" :title="$editTrans('textWrapDown')" :tooltip="config.tooltip" :color="$parent.color">
115
- <Icon value="text-wrap"></Icon>
116
- </Button>
117
- <!-- 代码块语言选择 -->
118
- <Button v-if="languageConfig.show" name="languages" type="display" :title="$editTrans('selectLanguages')" :tooltip="config.tooltip" :leftBorder="languageConfig.leftBorder" :rightBorder="languageConfig.rightBorder" :display-config="languageConfig.displayConfig" :color="$parent.color" :active="languageConfig.active" :disabled="languageConfig.disabled" @operate="selectLanguage"></Button>
119
- </template>
120
- <!-- 文本工具条 -->
121
- <template v-else-if="type == 'text'">
122
- <!-- 设置段落和标题 -->
123
- <Button v-if="headingConfig.show" name="heading" type="display" :title="$editTrans('heading')" :tooltip="config.tooltip" :display-config="headingConfig.displayConfig" :leftBorder="headingConfig.leftBorder" :rightBorder="headingConfig.rightBorder" :color="$parent.color" :active="headingConfig.active" :disabled="headingConfig.disabled" @operate="setHeading"></Button>
124
- <!-- 对齐方式 -->
125
- <Button v-if="alignConfig.show" name="align" type="select" :title="$editTrans('align')" :tooltip="config.tooltip" :select-config="alignConfig.selectConfig" :leftBorder="alignConfig.leftBorder" :rightBorder="alignConfig.rightBorder" :color="$parent.color" :active="alignConfig.active" :disabled="alignConfig.disabled" @operate="setAlign">
126
- <Icon value="align-left"></Icon>
127
- </Button>
128
- <!-- 有序列表 -->
129
- <Button v-if="orderListConfig.show" name="orderList" :title="$editTrans('orderList')" :tooltip="config.tooltip" :leftBorder="orderListConfig.leftBorder" :rightBorder="orderListConfig.rightBorder" :color="$parent.color" :active="orderListConfig.active" :disabled="orderListConfig.disabled" @operate="setList">
130
- <Icon value="list-ordered"></Icon>
131
- </Button>
132
- <!-- 无序列表 -->
133
- <Button v-if="unorderListConfig.show" name="unorderList" :title="$editTrans('unorderList')" :tooltip="config.tooltip" :leftBorder="unorderListConfig.leftBorder" :rightBorder="unorderListConfig.rightBorder" :color="$parent.color" :active="unorderListConfig.active" :disabled="unorderListConfig.disabled" @operate="setList">
134
- <Icon value="list-unordered"></Icon>
135
- </Button>
136
- <!-- 任务列表 -->
137
- <Button v-if="taskConfig.show" name="task" :title="$editTrans('task')" :tooltip="config.tooltip" :leftBorder="taskConfig.leftBorder" :rightBorder="taskConfig.rightBorder" :color="$parent.color" :active="taskConfig.active" :disabled="taskConfig.disabled" @operate="setTask">
138
- <Icon value="task"></Icon>
139
- </Button>
140
- <!-- 加粗 -->
141
- <Button v-if="boldConfig.show" name="bold" :title="$editTrans('bold')" :tooltip="config.tooltip" :leftBorder="boldConfig.leftBorder" :rightBorder="boldConfig.rightBorder" :color="$parent.color" :active="boldConfig.active" :disabled="boldConfig.disabled" @operate="setBold">
142
- <Icon value="bold"></Icon>
143
- </Button>
144
- <!-- 斜体 -->
145
- <Button v-if="italicConfig.show" name="italic" :title="$editTrans('italic')" :tooltip="config.tooltip" :leftBorder="italicConfig.leftBorder" :rightBorder="italicConfig.rightBorder" :color="$parent.color" :active="italicConfig.active" :disabled="italicConfig.disabled" @operate="setItalic">
146
- <Icon value="italic"></Icon>
147
- </Button>
148
- <!-- 删除线 -->
149
- <Button v-if="strikethroughConfig.show" name="strikethrough" :title="$editTrans('strikethrough')" :tooltip="config.tooltip" :leftBorder="strikethroughConfig.leftBorder" :rightBorder="strikethroughConfig.rightBorder" :color="$parent.color" :active="strikethroughConfig.active" :disabled="strikethroughConfig.disabled" @operate="setStrikethrough">
150
- <Icon value="strikethrough"></Icon>
151
- </Button>
152
- <!-- 下划线 -->
153
- <Button v-if="underlineConfig.show" name="underline" :title="$editTrans('underline')" :tooltip="config.tooltip" :leftBorder="underlineConfig.leftBorder" :rightBorder="underlineConfig.rightBorder" :color="$parent.color" :active="underlineConfig.active" :disabled="underlineConfig.disabled" @operate="setUnderline">
154
- <Icon value="underline"></Icon>
155
- </Button>
156
- <!-- 行内代码块 -->
157
- <Button v-if="codeConfig.show" name="code" :title="$editTrans('code')" :tooltip="config.tooltip" :leftBorder="codeConfig.leftBorder" :rightBorder="codeConfig.rightBorder" :color="$parent.color" :active="codeConfig.active" :disabled="codeConfig.disabled" @operate="setCodeStyle">
158
- <Icon value="code"></Icon>
159
- </Button>
160
- <!-- 上标 -->
161
- <Button v-if="superConfig.show" name="superscript" :title="$editTrans('superscript')" :tooltip="config.tooltip" :leftBorder="superConfig.leftBorder" :rightBorder="superConfig.rightBorder" :color="$parent.color" :active="superConfig.active" :disabled="superConfig.disabled" @operate="setSuperscript">
162
- <Icon value="superscript"></Icon>
163
- </Button>
164
- <!-- 下标 -->
165
- <Button v-if="subConfig.show" name="subscript" :title="$editTrans('subscript')" :tooltip="config.tooltip" :leftBorder="subConfig.leftBorder" :rightBorder="subConfig.rightBorder" :color="$parent.color" :active="subConfig.active" :disabled="subConfig.disabled" @operate="setSubscript">
166
- <Icon value="subscript"></Icon>
167
- </Button>
168
- <!-- 字号大小 -->
169
- <Button v-if="fontSizeConfig.show" name="fontSize" type="display" :title="$editTrans('fontSize')" :tooltip="config.tooltip" :display-config="fontSizeConfig.displayConfig" :leftBorder="fontSizeConfig.leftBorder" :rightBorder="fontSizeConfig.rightBorder" :color="$parent.color" :active="fontSizeConfig.active" :disabled="fontSizeConfig.disabled" @operate="setFontSize"></Button>
170
- <!-- 字体 -->
171
- <Button v-if="fontFamilyConfig.show" name="fontFamily" type="display" :title="$editTrans('fontFamily')" :tooltip="config.tooltip" :display-config="fontFamilyConfig.displayConfig" :leftBorder="fontFamilyConfig.leftBorder" :rightBorder="fontFamilyConfig.rightBorder" :color="$parent.color" :active="fontFamilyConfig.active" :disabled="fontFamilyConfig.disabled" @operate="setFontFamily"></Button>
172
- <!-- 行高 -->
173
- <Button v-if="lineHeightConfig.show" name="lineHeight" type="display" :title="$editTrans('lineHeight')" :tooltip="config.tooltip" :display-config="lineHeightConfig.displayConfig" :leftBorder="lineHeightConfig.leftBorder" :rightBorder="lineHeightConfig.rightBorder" :color="$parent.color" :active="lineHeightConfig.active" :disabled="lineHeightConfig.disabled" @operate="setLineHeight"></Button>
174
- <!-- 前景色 -->
175
- <Button v-if="foreColorConfig.show" name="foreColor" type="select" :title="$editTrans('foreColor')" :tooltip="config.tooltip" :select-config="foreColorConfig.selectConfig" :leftBorder="foreColorConfig.leftBorder" :rightBorder="foreColorConfig.rightBorder" :color="$parent.color" :active="foreColorConfig.active" :disabled="foreColorConfig.disabled" hideScroll ref="foreColor">
176
- <Icon value="font-color"></Icon>
177
- <template #layer="{ options }">
178
- <Colors :tooltip="config.tooltip" :color="$parent.color" :value="foreColorConfig.value" @change="setForeColor" :data="options"></Colors>
179
- </template>
180
- </Button>
181
- <!-- 背景色 -->
182
- <Button v-if="backColorConfig.show" name="backColor" type="select" :title="$editTrans('backColor')" :tooltip="config.tooltip" :select-config="backColorConfig.selectConfig" :leftBorder="backColorConfig.leftBorder" :rightBorder="backColorConfig.rightBorder" :color="$parent.color" :active="backColorConfig.active" :disabled="backColorConfig.disabled" hideScroll ref="backColor">
183
- <Icon value="brush"></Icon>
184
- <template #layer="{ options }">
185
- <Colors :tooltip="config.tooltip" :color="$parent.color" :value="backColorConfig.value" @change="setBackColor" :data="options"></Colors>
186
- </template>
187
- </Button>
188
- <!-- 清除样式 -->
189
- <Button v-if="formatClearConfig.show" name="formatClear" :title="$editTrans('formatClear')" :tooltip="config.tooltip" :leftBorder="formatClearConfig.leftBorder" :rightBorder="formatClearConfig.rightBorder" :color="$parent.color" :active="formatClearConfig.active" :disabled="formatClearConfig.disabled" @operate="clearFormat">
190
- <Icon value="format-clear"></Icon>
191
- </Button>
192
- </template>
193
- </div>
194
- </Layer>
195
- </template>
196
- <script>
197
- import Layer from './base/Layer'
198
- import Tooltip from './base/Tooltip'
199
- import Button from './base/Button'
200
- import Icon from './base/Icon'
201
- import Checkbox from './base/Checkbox'
202
- import Colors from './common/Colors'
203
- import { AlexElement } from 'alex-editor'
204
- import { common as DapCommon } from 'dap-util'
205
- import { getCurrentParsedomElement, removeTextStyle, removeTextMark, setTextStyle, setLineHeight, setTextMark, setList, setTask, setHeading, setAlign, isRangeInList, isRangeInTask, queryTextStyle, queryTextMark } from '../core/function'
206
- export default {
207
- name: 'Toolbar',
208
- emits: ['update:modelValue'],
209
- props: {
210
- //是否显示
211
- modelValue: {
212
- type: Boolean,
213
- default: false
214
- },
215
- //关联元素
216
- node: {
217
- type: [String, Node],
218
- default: null
219
- },
220
- //类型
221
- type: {
222
- type: String,
223
- default: 'text',
224
- validator(value) {
225
- return ['text', 'table', 'link', 'codeBlock', 'image', 'video'].includes(value)
226
- }
227
- },
228
- //工具条配置
229
- config: {
230
- type: Object,
231
- default: null
232
- }
233
- },
234
- data() {
235
- return {
236
- //链接参数配置
237
- linkConfig: {
238
- //链接地址
239
- url: '',
240
- //链接是否新窗口打开
241
- newOpen: false
242
- },
243
- //视频参数配置
244
- videoConfig: {
245
- //是否显示控制器
246
- controls: false,
247
- //是否循环
248
- loop: false,
249
- //是否自动播放
250
- autoplay: false,
251
- //是否静音
252
- muted: false
253
- },
254
- //代码块选择语言按钮配置
255
- languageConfig: {
256
- show: this.config.codeBlock.languages.show,
257
- displayConfig: {
258
- options: this.config.codeBlock.languages.options,
259
- value: '',
260
- width: this.config.codeBlock.languages.width,
261
- maxHeight: this.config.codeBlock.languages.maxHeight
262
- },
263
- leftBorder: this.config.codeBlock.languages.leftBorder,
264
- rightBorder: this.config.codeBlock.languages.rightBorder,
265
- active: false,
266
- disabled: false
267
- },
268
- //标题按钮配置
269
- headingConfig: {
270
- show: this.config.text.heading.show,
271
- displayConfig: {
272
- options: this.config.text.heading.options,
273
- value: '',
274
- width: this.config.text.heading.width,
275
- maxHeight: this.config.text.heading.maxHeight
276
- },
277
- defaultValue: this.config.text.heading.defaultValue,
278
- leftBorder: this.config.text.heading.leftBorder,
279
- rightBorder: this.config.text.heading.rightBorder,
280
- active: false,
281
- disabled: false
282
- },
283
- //对齐方式按钮配置
284
- alignConfig: {
285
- show: this.config.text.align.show,
286
- selectConfig: {
287
- options: this.config.text.align.options,
288
- width: this.config.text.align.width,
289
- maxHeight: this.config.text.align.maxHeight
290
- },
291
- leftBorder: this.config.text.align.leftBorder,
292
- rightBorder: this.config.text.align.rightBorder,
293
- active: false,
294
- disabled: false
295
- },
296
- //有序列表按钮配置
297
- orderListConfig: {
298
- show: this.config.text.orderList.show,
299
- leftBorder: this.config.text.orderList.leftBorder,
300
- rightBorder: this.config.text.orderList.rightBorder,
301
- active: false,
302
- disabled: false
303
- },
304
- //无序列表按钮配置
305
- unorderListConfig: {
306
- show: this.config.text.unorderList.show,
307
- leftBorder: this.config.text.unorderList.leftBorder,
308
- rightBorder: this.config.text.unorderList.rightBorder,
309
- active: false,
310
- disabled: false
311
- },
312
- //任务列表按钮配置
313
- taskConfig: {
314
- show: this.config.text.task.show,
315
- leftBorder: this.config.text.task.leftBorder,
316
- rightBorder: this.config.text.task.rightBorder,
317
- active: false,
318
- disabled: false
319
- },
320
- //粗体按钮配置
321
- boldConfig: {
322
- show: this.config.text.bold.show,
323
- leftBorder: this.config.text.bold.leftBorder,
324
- rightBorder: this.config.text.bold.rightBorder,
325
- active: false,
326
- disabled: false
327
- },
328
- //斜体按钮配置
329
- italicConfig: {
330
- show: this.config.text.italic.show,
331
- leftBorder: this.config.text.italic.leftBorder,
332
- rightBorder: this.config.text.italic.rightBorder,
333
- active: false,
334
- disabled: false
335
- },
336
- //删除线按钮配置
337
- strikethroughConfig: {
338
- show: this.config.text.strikethrough.show,
339
- leftBorder: this.config.text.strikethrough.leftBorder,
340
- rightBorder: this.config.text.strikethrough.rightBorder,
341
- active: false,
342
- disabled: false
343
- },
344
- //下划线按钮配置
345
- underlineConfig: {
346
- show: this.config.text.underline.show,
347
- leftBorder: this.config.text.underline.leftBorder,
348
- rightBorder: this.config.text.underline.rightBorder,
349
- active: false,
350
- disabled: false
351
- },
352
- //行内代码块按钮配置
353
- codeConfig: {
354
- show: this.config.text.code.show,
355
- leftBorder: this.config.text.code.leftBorder,
356
- rightBorder: this.config.text.code.rightBorder,
357
- active: false,
358
- disabled: false
359
- },
360
- //上标按钮配置
361
- superConfig: {
362
- show: this.config.text.super.show,
363
- leftBorder: this.config.text.super.leftBorder,
364
- rightBorder: this.config.text.super.rightBorder,
365
- active: false,
366
- disabled: false
367
- },
368
- //下标按钮配置
369
- subConfig: {
370
- show: this.config.text.sub.show,
371
- leftBorder: this.config.text.sub.leftBorder,
372
- rightBorder: this.config.text.sub.rightBorder,
373
- active: false,
374
- disabled: false
375
- },
376
- //字号按钮配置
377
- fontSizeConfig: {
378
- show: this.config.text.fontSize.show,
379
- displayConfig: {
380
- options: this.config.text.fontSize.options,
381
- value: '',
382
- width: this.config.text.fontSize.width,
383
- maxHeight: this.config.text.fontSize.maxHeight
384
- },
385
- defaultValue: this.config.text.fontSize.defaultValue,
386
- leftBorder: this.config.text.fontSize.leftBorder,
387
- rightBorder: this.config.text.fontSize.rightBorder,
388
- active: false,
389
- disabled: false
390
- },
391
- //字体按钮配置
392
- fontFamilyConfig: {
393
- show: this.config.text.fontFamily.show,
394
- displayConfig: {
395
- options: this.config.text.fontFamily.options,
396
- value: '',
397
- width: this.config.text.fontFamily.width,
398
- maxHeight: this.config.text.fontFamily.maxHeight
399
- },
400
- defaultValue: this.config.text.fontFamily.defaultValue,
401
- leftBorder: this.config.text.fontFamily.leftBorder,
402
- rightBorder: this.config.text.fontFamily.rightBorder,
403
- active: false,
404
- disabled: false
405
- },
406
- //行高按钮配置
407
- lineHeightConfig: {
408
- show: this.config.text.lineHeight.show,
409
- displayConfig: {
410
- options: this.config.text.lineHeight.options,
411
- value: '',
412
- width: this.config.text.lineHeight.width,
413
- maxHeight: this.config.text.lineHeight.maxHeight
414
- },
415
- defaultValue: this.config.text.lineHeight.defaultValue,
416
- leftBorder: this.config.text.lineHeight.leftBorder,
417
- rightBorder: this.config.text.lineHeight.rightBorder,
418
- active: false,
419
- disabled: false
420
- },
421
- //前景颜色按钮配置
422
- foreColorConfig: {
423
- show: this.config.text.foreColor.show,
424
- selectConfig: {
425
- options: this.config.text.foreColor.options
426
- },
427
- leftBorder: this.config.text.foreColor.leftBorder,
428
- rightBorder: this.config.text.foreColor.rightBorder,
429
- value: '', //选择的颜色值
430
- active: false,
431
- disabled: false
432
- },
433
- //背景颜色按钮配置
434
- backColorConfig: {
435
- show: this.config.text.backColor.show,
436
- selectConfig: {
437
- options: this.config.text.backColor.options
438
- },
439
- leftBorder: this.config.text.backColor.leftBorder,
440
- rightBorder: this.config.text.backColor.rightBorder,
441
- value: '', //选择的颜色值
442
- active: false,
443
- disabled: false
444
- },
445
- //清除格式按钮配置
446
- formatClearConfig: {
447
- show: this.config.text.formatClear.show,
448
- leftBorder: this.config.text.formatClear.leftBorder,
449
- rightBorder: this.config.text.formatClear.rightBorder,
450
- active: false,
451
- disabled: false
452
- }
453
- }
454
- },
455
- computed: {
456
- //是否显示
457
- show: {
458
- get() {
459
- return this.modelValue
460
- },
461
- set(val) {
462
- this.$emit('update:modelValue', val)
463
- }
464
- }
465
- },
466
- components: {
467
- Layer,
468
- Tooltip,
469
- Button,
470
- Icon,
471
- Checkbox,
472
- Colors
473
- },
474
- inject: ['$editTrans'],
475
- methods: {
476
- //输入框获取焦点
477
- handleInputFocus(e) {
478
- if (this.$parent.color) {
479
- e.currentTarget.style.borderColor = this.$parent.color
480
- }
481
- },
482
- //输入框失去焦点
483
- handleInputBlur(e) {
484
- e.currentTarget.style.borderColor = ''
485
- },
486
- //清除格式
487
- clearFormat() {
488
- removeTextStyle(this.$parent)
489
- removeTextMark(this.$parent)
490
- this.$parent.editor.formatElementStack()
491
- this.$parent.editor.domRender()
492
- this.$parent.editor.rangeRender()
493
- },
494
- //设置背景色
495
- setBackColor(value) {
496
- setTextStyle(this.$parent, {
497
- 'background-color': value
498
- })
499
- this.$refs.backColor.hideLayer()
500
- this.$parent.editor.formatElementStack()
501
- this.$parent.editor.domRender()
502
- this.$parent.editor.rangeRender()
503
- },
504
- //设置前景色
505
- setForeColor(value) {
506
- setTextStyle(this.$parent, {
507
- color: value
508
- })
509
- this.$refs.foreColor.hideLayer()
510
- this.$parent.editor.formatElementStack()
511
- this.$parent.editor.domRender()
512
- this.$parent.editor.rangeRender()
513
- },
514
- //设置行高
515
- setLineHeight(name, value) {
516
- setLineHeight(this.$parent, value)
517
- this.$parent.editor.formatElementStack()
518
- this.$parent.editor.domRender()
519
- this.$parent.editor.rangeRender()
520
- },
521
- //设置字体
522
- setFontFamily(name, value) {
523
- setTextStyle(this.$parent, {
524
- 'font-family': value
525
- })
526
- this.$parent.editor.formatElementStack()
527
- this.$parent.editor.domRender()
528
- this.$parent.editor.rangeRender()
529
- },
530
- //设置字号
531
- setFontSize(name, value) {
532
- setTextStyle(this.$parent, {
533
- 'font-size': value
534
- })
535
- this.$parent.editor.formatElementStack()
536
- this.$parent.editor.domRender()
537
- this.$parent.editor.rangeRender()
538
- },
539
- //设置上标
540
- setSuperscript() {
541
- if (queryTextStyle(this.$parent, 'vertical-align', 'super')) {
542
- removeTextStyle(this.$parent, ['vertical-align'])
543
- } else {
544
- setTextStyle(this.$parent, {
545
- 'vertical-align': 'super'
546
- })
547
- }
548
- this.$parent.editor.formatElementStack()
549
- this.$parent.editor.domRender()
550
- this.$parent.editor.rangeRender()
551
- },
552
- //设置下标
553
- setSubscript() {
554
- if (queryTextStyle(this.$parent, 'vertical-align', 'sub')) {
555
- removeTextStyle(this.$parent, ['vertical-align'])
556
- } else {
557
- setTextStyle(this.$parent, {
558
- 'vertical-align': 'sub'
559
- })
560
- }
561
- this.$parent.editor.formatElementStack()
562
- this.$parent.editor.domRender()
563
- this.$parent.editor.rangeRender()
564
- },
565
- //设置行内代码样式
566
- setCodeStyle() {
567
- if (queryTextMark(this.$parent, 'data-editify-code')) {
568
- removeTextMark(this.$parent, ['data-editify-code'])
569
- } else {
570
- setTextMark(this.$parent, {
571
- 'data-editify-code': true
572
- })
573
- }
574
- this.$parent.editor.formatElementStack()
575
- this.$parent.editor.domRender()
576
- this.$parent.editor.rangeRender()
577
- },
578
- //设置下划线
579
- setUnderline() {
580
- if (queryTextStyle(this.$parent, 'text-decoration', 'underline') || queryTextStyle(this.$parent, 'text-decoration-line', 'underline')) {
581
- removeTextStyle(this.$parent, ['text-decoration', 'text-decoration-line'])
582
- } else {
583
- setTextStyle(this.$parent, {
584
- 'text-decoration': 'underline'
585
- })
586
- }
587
- this.$parent.editor.formatElementStack()
588
- this.$parent.editor.domRender()
589
- this.$parent.editor.rangeRender()
590
- },
591
- //设置删除线
592
- setStrikethrough() {
593
- if (queryTextStyle(this.$parent, 'text-decoration', 'line-through') || queryTextStyle(this.$parent, 'text-decoration-line', 'line-through')) {
594
- removeTextStyle(this.$parent, ['text-decoration', 'text-decoration-line'])
595
- } else {
596
- setTextStyle(this.$parent, {
597
- 'text-decoration': 'line-through'
598
- })
599
- }
600
- this.$parent.editor.formatElementStack()
601
- this.$parent.editor.domRender()
602
- this.$parent.editor.rangeRender()
603
- },
604
- //设置列表
605
- setList(name) {
606
- setList(this.$parent, name == 'orderList')
607
- this.$parent.editor.formatElementStack()
608
- this.$parent.editor.domRender()
609
- this.$parent.editor.rangeRender()
610
- },
611
- //设置任务列表
612
- setTask() {
613
- setTask(this.$parent)
614
- this.$parent.editor.formatElementStack()
615
- this.$parent.editor.domRender()
616
- this.$parent.editor.rangeRender()
617
- },
618
- //斜体
619
- setItalic() {
620
- if (queryTextStyle(this.$parent, 'font-style', 'italic')) {
621
- removeTextStyle(this.$parent, ['font-style'])
622
- } else {
623
- setTextStyle(this.$parent, {
624
- 'font-style': 'italic'
625
- })
626
- }
627
- this.$parent.editor.formatElementStack()
628
- this.$parent.editor.domRender()
629
- this.$parent.editor.rangeRender()
630
- },
631
- //加粗
632
- setBold() {
633
- if (queryTextStyle(this.$parent, 'font-weight', 'bold') || queryTextStyle(this.$parent, 'font-weight', '700')) {
634
- removeTextStyle(this.$parent, ['font-weight'])
635
- } else {
636
- setTextStyle(this.$parent, {
637
- 'font-weight': 'bold'
638
- })
639
- }
640
- this.$parent.editor.formatElementStack()
641
- this.$parent.editor.domRender()
642
- this.$parent.editor.rangeRender()
643
- },
644
- //设置标题
645
- setHeading(name, value) {
646
- setHeading(this.$parent, value)
647
- this.$parent.editor.formatElementStack()
648
- this.$parent.editor.domRender()
649
- this.$parent.editor.rangeRender()
650
- },
651
- //设置对齐方式
652
- setAlign(name, value) {
653
- setAlign(this.$parent, value)
654
- this.$parent.editor.formatElementStack()
655
- this.$parent.editor.domRender()
656
- this.$parent.editor.rangeRender()
657
- },
658
- //设置视频属性
659
- setVideo(prop) {
660
- const element = this.$parent.editor.range.anchor.element
661
- //当前是拥有该属性
662
- if (this.videoConfig[prop]) {
663
- delete element.marks[prop]
664
- }
665
- //当前无该属性
666
- else {
667
- element.marks[prop] = true
668
- }
669
- this.videoConfig[prop] = !this.videoConfig[prop]
670
- this.$parent.editor.formatElementStack()
671
- this.$parent.editor.domRender()
672
- this.$parent.editor.rangeRender()
673
- },
674
- //设置图片或者视频宽度
675
- setWidth(value) {
676
- const element = this.$parent.editor.range.anchor.element
677
- if (element) {
678
- const styles = {
679
- width: value
680
- }
681
- if (element.hasStyles()) {
682
- element.styles = Object.assign(element.styles, styles)
683
- } else {
684
- element.styles = styles
685
- }
686
- this.$parent.editor.formatElementStack()
687
- this.$parent.editor.domRender()
688
- this.$parent.editor.rangeRender()
689
- //更新工具条位置
690
- setTimeout(() => {
691
- this.$refs.layer.setPosition()
692
- }, 0)
693
- }
694
- },
695
- //修改链接
696
- modifyLink() {
697
- if (!this.linkConfig.url) {
698
- return
699
- }
700
- const link = getCurrentParsedomElement(this.$parent, 'a')
701
- if (link) {
702
- link.marks.href = this.linkConfig.url
703
- if (this.linkConfig.newOpen) {
704
- link.marks.target = '_blank'
705
- } else {
706
- delete link.marks.target
707
- }
708
- }
709
- this.$parent.editor.formatElementStack()
710
- this.$parent.editor.domRender()
711
- },
712
- //移除链接
713
- removeLink() {
714
- const link = getCurrentParsedomElement(this.$parent, 'a')
715
- if (link) {
716
- link.parsedom = AlexElement.TEXT_NODE
717
- delete link.marks.target
718
- delete link.marks.href
719
- }
720
- this.$parent.editor.formatElementStack()
721
- this.$parent.editor.domRender()
722
- this.$parent.editor.rangeRender()
723
- },
724
- //选择代码语言
725
- selectLanguage(name, value) {
726
- const pre = getCurrentParsedomElement(this.$parent, 'pre')
727
- if (pre) {
728
- Object.assign(pre.marks, {
729
- 'data-editify-hljs': value
730
- })
731
- this.$parent.editor.formatElementStack()
732
- this.$parent.editor.domRender()
733
- this.$parent.editor.rangeRender()
734
- }
735
- },
736
- //代码块前后插入段落
737
- insertParagraphWithPre(type = 'up') {
738
- if (!this.$parent.editor.range.anchor.isEqual(this.$parent.editor.range.focus)) {
739
- this.$parent.editor.range.anchor.element = this.$parent.editor.range.focus.element
740
- this.$parent.editor.range.anchor.offset = this.$parent.editor.range.focus.offset
741
- }
742
- const pre = getCurrentParsedomElement(this.$parent, 'pre')
743
- if (pre) {
744
- const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
745
- const breakEl = new AlexElement('closed', 'br', null, null, null)
746
- this.$parent.editor.addElementTo(breakEl, paragraph)
747
- if (type == 'up') {
748
- this.$parent.editor.addElementBefore(paragraph, pre)
749
- } else {
750
- this.$parent.editor.addElementAfter(paragraph, pre)
751
- }
752
- this.$parent.editor.range.anchor.moveToEnd(paragraph)
753
- this.$parent.editor.range.focus.moveToEnd(paragraph)
754
- this.$parent.editor.formatElementStack()
755
- this.$parent.editor.domRender()
756
- this.$parent.editor.rangeRender()
757
- }
758
- },
759
- //表格前后插入列
760
- insertTableColumn(type = 'left') {
761
- if (!this.$parent.editor.range.anchor.isEqual(this.$parent.editor.range.focus)) {
762
- this.$parent.editor.range.anchor.element = this.$parent.editor.range.focus.element
763
- this.$parent.editor.range.anchor.offset = this.$parent.editor.range.focus.offset
764
- }
765
- const table = getCurrentParsedomElement(this.$parent, 'table')
766
- const column = getCurrentParsedomElement(this.$parent, 'td')
767
- const tbody = getCurrentParsedomElement(this.$parent, 'tbody')
768
- if (column && table && tbody) {
769
- const rows = tbody.children
770
- const index = column.parent.children.findIndex(item => {
771
- return item.isEqual(column)
772
- })
773
- //插入列
774
- rows.forEach(row => {
775
- const newColumn = column.clone(false)
776
- const breakEl = new AlexElement('closed', 'br', null, null, null)
777
- this.$parent.editor.addElementTo(breakEl, newColumn)
778
- if (type == 'left') {
779
- this.$parent.editor.addElementTo(newColumn, row, index)
780
- } else {
781
- this.$parent.editor.addElementTo(newColumn, row, index + 1)
782
- }
783
- })
784
- //插入col
785
- const colgroup = table.children.find(item => {
786
- return item.parsedom == 'colgroup'
787
- })
788
- const col = new AlexElement('closed', 'col', null, null, null)
789
- if (type == 'left') {
790
- this.$parent.editor.addElementTo(col, colgroup, index)
791
- } else {
792
- this.$parent.editor.addElementTo(col, colgroup, index + 1)
793
- }
794
- //渲染
795
- this.$parent.editor.formatElementStack()
796
- if (type == 'left') {
797
- const previousColumn = this.$parent.editor.getPreviousElement(column)
798
- this.$parent.editor.range.anchor.moveToStart(previousColumn)
799
- this.$parent.editor.range.focus.moveToStart(previousColumn)
800
- } else {
801
- const nextColumn = this.$parent.editor.getNextElement(column)
802
- this.$parent.editor.range.anchor.moveToStart(nextColumn)
803
- this.$parent.editor.range.focus.moveToStart(nextColumn)
804
- }
805
- this.$parent.editor.domRender()
806
- this.$parent.editor.rangeRender()
807
- }
808
- },
809
- //表格前后插入行
810
- insertTableRow(type = 'up') {
811
- if (!this.$parent.editor.range.anchor.isEqual(this.$parent.editor.range.focus)) {
812
- this.$parent.editor.range.anchor.element = this.$parent.editor.range.focus.element
813
- this.$parent.editor.range.anchor.offset = this.$parent.editor.range.focus.offset
814
- }
815
- const table = getCurrentParsedomElement(this.$parent, 'table')
816
- const row = getCurrentParsedomElement(this.$parent, 'tr')
817
- if (table && row) {
818
- const newRow = row.clone()
819
- newRow.children.forEach(column => {
820
- column.children = []
821
- const breakEl = new AlexElement('closed', 'br', null, null, null)
822
- this.$parent.editor.addElementTo(breakEl, column)
823
- })
824
- if (type == 'up') {
825
- this.$parent.editor.addElementBefore(newRow, row)
826
- } else {
827
- this.$parent.editor.addElementAfter(newRow, row)
828
- }
829
- this.$parent.editor.formatElementStack()
830
- this.$parent.editor.range.anchor.moveToStart(newRow)
831
- this.$parent.editor.range.focus.moveToStart(newRow)
832
- this.$parent.editor.domRender()
833
- this.$parent.editor.rangeRender()
834
- //更新工具条位置
835
- setTimeout(() => {
836
- this.$refs.layer.setPosition()
837
- }, 0)
838
- }
839
- },
840
- //表格前后插入段落
841
- insertParagraphWithTable(type = 'up') {
842
- const table = getCurrentParsedomElement(this.$parent, 'table')
843
- if (table) {
844
- const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
845
- const breakEl = new AlexElement('closed', 'br', null, null, null)
846
- this.$parent.editor.addElementTo(breakEl, paragraph)
847
- if (type == 'up') {
848
- this.$parent.editor.addElementBefore(paragraph, table)
849
- } else {
850
- this.$parent.editor.addElementAfter(paragraph, table)
851
- }
852
- this.$parent.editor.range.anchor.moveToEnd(paragraph)
853
- this.$parent.editor.range.focus.moveToEnd(paragraph)
854
- this.$parent.editor.formatElementStack()
855
- this.$parent.editor.domRender()
856
- this.$parent.editor.rangeRender()
857
- }
858
- },
859
- //删除表格行
860
- deleteTableRow() {
861
- if (!this.$parent.editor.range.anchor.isEqual(this.$parent.editor.range.focus)) {
862
- this.$parent.editor.range.anchor.element = this.$parent.editor.range.focus.element
863
- this.$parent.editor.range.anchor.offset = this.$parent.editor.range.focus.offset
864
- }
865
- const table = getCurrentParsedomElement(this.$parent, 'table')
866
- const row = getCurrentParsedomElement(this.$parent, 'tr')
867
- if (table && row) {
868
- const parent = row.parent
869
- if (parent.children.length == 1) {
870
- this.deleteElement('table')
871
- return
872
- }
873
- const previousRow = this.$parent.editor.getPreviousElement(row)
874
- const nextRow = this.$parent.editor.getNextElement(row)
875
- row.toEmpty()
876
- this.$parent.editor.formatElementStack()
877
- if (previousRow) {
878
- this.$parent.editor.range.anchor.moveToEnd(previousRow.children[0])
879
- this.$parent.editor.range.focus.moveToEnd(previousRow.children[0])
880
- } else {
881
- this.$parent.editor.range.anchor.moveToEnd(nextRow.children[0])
882
- this.$parent.editor.range.focus.moveToEnd(nextRow.children[0])
883
- }
884
- this.$parent.editor.domRender()
885
- this.$parent.editor.rangeRender()
886
- //更新工具条位置
887
- setTimeout(() => {
888
- this.$refs.layer.setPosition()
889
- }, 0)
890
- }
891
- },
892
- //删除表格列
893
- deleteTableColumn() {
894
- if (!this.$parent.editor.range.anchor.isEqual(this.$parent.editor.range.focus)) {
895
- this.$parent.editor.range.anchor.element = this.$parent.editor.range.focus.element
896
- this.$parent.editor.range.anchor.offset = this.$parent.editor.range.focus.offset
897
- }
898
- const column = getCurrentParsedomElement(this.$parent, 'td')
899
- const tbody = getCurrentParsedomElement(this.$parent, 'tbody')
900
- const table = getCurrentParsedomElement(this.$parent, 'table')
901
- if (column && table && tbody) {
902
- const rows = tbody.children
903
- const parent = column.parent
904
- if (parent.children.length == 1) {
905
- this.deleteElement('table')
906
- return
907
- }
908
- const previousColumn = this.$parent.editor.getPreviousElement(column)
909
- const nextColumn = this.$parent.editor.getNextElement(column)
910
- const index = column.parent.children.findIndex(item => {
911
- return item.isEqual(column)
912
- })
913
- //删除列
914
- rows.forEach(row => {
915
- row.children[index].toEmpty()
916
- })
917
- //删除col
918
- const colgroup = table.children.find(item => {
919
- return item.parsedom == 'colgroup'
920
- })
921
- colgroup.children[index].toEmpty()
922
- //渲染
923
- this.$parent.editor.formatElementStack()
924
- if (previousColumn) {
925
- this.$parent.editor.range.anchor.moveToEnd(previousColumn)
926
- this.$parent.editor.range.focus.moveToEnd(previousColumn)
927
- } else {
928
- this.$parent.editor.range.anchor.moveToEnd(nextColumn)
929
- this.$parent.editor.range.focus.moveToEnd(nextColumn)
930
- }
931
- this.$parent.editor.domRender()
932
- this.$parent.editor.rangeRender()
933
- }
934
- },
935
- //删除元素
936
- deleteElement(parsedom) {
937
- const element = getCurrentParsedomElement(this.$parent, parsedom)
938
- if (element) {
939
- element.toEmpty()
940
- this.$parent.editor.formatElementStack()
941
- this.$parent.editor.domRender()
942
- this.$parent.editor.rangeRender()
943
- }
944
- },
945
- //浮层显示时
946
- layerShow() {
947
- //代码块初始化展示设置
948
- if (this.type == 'codeBlock') {
949
- const pre = getCurrentParsedomElement(this.$parent, 'pre')
950
- if (pre) {
951
- this.languageConfig.displayConfig.value = pre.marks['data-editify-hljs'] || ''
952
- }
953
- }
954
- //链接初始化展示
955
- else if (this.type == 'link') {
956
- const link = getCurrentParsedomElement(this.$parent, 'a')
957
- if (link) {
958
- this.linkConfig.url = link.marks['href']
959
- this.linkConfig.newOpen = link.marks['target'] == '_blank'
960
- }
961
- }
962
- //视频初始化显示
963
- else if (this.type == 'video') {
964
- const video = getCurrentParsedomElement(this.$parent, 'video')
965
- if (video) {
966
- this.videoConfig.autoplay = !!video.marks['autoplay']
967
- this.videoConfig.loop = !!video.marks['loop']
968
- this.videoConfig.controls = !!video.marks['controls']
969
- this.videoConfig.muted = !!video.marks['muted']
970
- }
971
- }
972
- //文本工具条初始化显示
973
- else if (this.type == 'text') {
974
- //额外禁用判定
975
- const extraDisabled = name => {
976
- if (typeof this.config.extraDisabled == 'function') {
977
- return this.config.extraDisabled.apply(this.$parent, [name]) || false
978
- }
979
- return false
980
- }
981
- //显示已设置标题
982
- const findHeadingItem = this.headingConfig.displayConfig.options.find(item => {
983
- let val = item
984
- if (DapCommon.isObject(item)) {
985
- val = item.value
986
- }
987
- return this.$parent.dataRangeCaches.list.every(el => {
988
- if (el.element.isBlock()) {
989
- return el.element.parsedom == val
990
- }
991
- return el.element.getBlock().parsedom == val
992
- })
993
- })
994
- this.headingConfig.displayConfig.value = findHeadingItem ? (DapCommon.isObject(findHeadingItem) ? findHeadingItem.value : findHeadingItem) : this.headingConfig.defaultValue
995
- //标题禁用
996
- this.headingConfig.disabled = extraDisabled('heading')
997
-
998
- //对齐方式禁用
999
- this.alignConfig.disabled = extraDisabled('align')
1000
-
1001
- //有序列表按钮激活
1002
- this.orderListConfig.active = isRangeInList(this.$parent, true)
1003
- //有序列表按钮禁用
1004
- this.orderListConfig.disabled = extraDisabled('orderList')
1005
-
1006
- //无序列表按钮激活
1007
- this.unorderListConfig.active = isRangeInList(this.$parent, false)
1008
- //无序列表按钮禁用
1009
- this.unorderListConfig.disabled = extraDisabled('unorderList')
1010
-
1011
- //任务列表按钮激活
1012
- this.taskConfig.active = isRangeInTask(this.$parent)
1013
- //任务列表按钮禁用
1014
- this.taskConfig.disabled = extraDisabled('task')
1015
-
1016
- //粗体按钮激活
1017
- this.boldConfig.active = queryTextStyle(this.$parent, 'font-weight', 'bold') || queryTextStyle(this.$parent, 'font-weight', '700')
1018
- //粗体按钮禁用
1019
- this.boldConfig.disabled = extraDisabled('bold')
1020
-
1021
- //斜体按钮激活
1022
- this.italicConfig.active = queryTextStyle(this.$parent, 'font-style', 'italic')
1023
- //斜体按钮禁用
1024
- this.italicConfig.disabled = extraDisabled('italic')
1025
-
1026
- //删除线按钮激活
1027
- this.strikethroughConfig.active = queryTextStyle(this.$parent, 'text-decoration', 'line-through') || queryTextStyle(this.$parent, 'text-decoration-line', 'line-through')
1028
- //删除线按钮禁用
1029
- this.strikethroughConfig.disabled = extraDisabled('strikethrough')
1030
-
1031
- //下划线按钮激活
1032
- this.underlineConfig.active = queryTextStyle(this.$parent, 'text-decoration', 'underline') || queryTextStyle(this.$parent, 'text-decoration-line', 'underline')
1033
- //下划线按钮禁用
1034
- this.underlineConfig.disabled = extraDisabled('underline')
1035
-
1036
- //行内代码按钮激活
1037
- this.codeConfig.active = queryTextMark(this.$parent, 'data-editify-code')
1038
- //行内代码按钮禁用
1039
- this.codeConfig.disabled = extraDisabled('code')
1040
-
1041
- //上标按钮激活
1042
- this.superConfig.active = queryTextStyle(this.$parent, 'vertical-align', 'super')
1043
- //上标按钮禁用
1044
- this.superConfig.disabled = extraDisabled('super')
1045
-
1046
- //下标按钮激活
1047
- this.subConfig.active = queryTextStyle(this.$parent, 'vertical-align', 'sub')
1048
- //下标按钮禁用
1049
- this.subConfig.disabled = extraDisabled('sub')
1050
-
1051
- //显示已选择字号
1052
- const findFontItem = this.fontSizeConfig.displayConfig.options.find(item => {
1053
- if (DapCommon.isObject(item)) {
1054
- return queryTextStyle(this.$parent, 'font-size', item.value)
1055
- }
1056
- return queryTextStyle(this.$parent, 'font-size', item)
1057
- })
1058
- this.fontSizeConfig.displayConfig.value = findFontItem ? (DapCommon.isObject(findFontItem) ? findFontItem.value : findFontItem) : this.fontSizeConfig.defaultValue
1059
- //字号按钮禁用
1060
- this.fontSizeConfig.disabled = extraDisabled('fontSize')
1061
-
1062
- //显示已选择字体
1063
- const findFamilyItem = this.fontFamilyConfig.displayConfig.options.find(item => {
1064
- if (DapCommon.isObject(item)) {
1065
- return queryTextStyle(this.$parent, 'font-family', item.value)
1066
- }
1067
- return queryTextStyle(this.$parent, 'font-family', item)
1068
- })
1069
- this.fontFamilyConfig.displayConfig.value = findFamilyItem ? (DapCommon.isObject(findFamilyItem) ? findFamilyItem.value : findFamilyItem) : this.fontFamilyConfig.defaultValue
1070
- //字体按钮禁用
1071
- this.fontFamilyConfig.disabled = extraDisabled('fontFamily')
1072
-
1073
- //显示已设置行高
1074
- const findHeightItem = this.lineHeightConfig.displayConfig.options.find(item => {
1075
- let val = item
1076
- if (DapCommon.isObject(item)) {
1077
- val = item.value
1078
- }
1079
- return this.$parent.dataRangeCaches.list.every(el => {
1080
- if (el.element.isBlock() || el.element.isInblock()) {
1081
- return el.element.hasStyles() && el.element.styles['line-height'] == val
1082
- }
1083
- const block = el.element.getBlock()
1084
- const inblock = el.element.getInblock()
1085
- if (inblock) {
1086
- return inblock.hasStyles() && inblock.styles['line-height'] == val
1087
- }
1088
- return block.hasStyles() && block.styles['line-height'] == val
1089
- })
1090
- })
1091
- this.lineHeightConfig.displayConfig.value = findHeightItem ? (DapCommon.isObject(findHeightItem) ? findHeightItem.value : findHeightItem) : this.lineHeightConfig.defaultValue
1092
- //行高按钮禁用
1093
- this.lineHeightConfig.disabled = extraDisabled('lineHeight')
1094
-
1095
- //显示已选择的前景色
1096
- const findForeColorItem = this.foreColorConfig.selectConfig.options.find(item => {
1097
- if (DapCommon.isObject(item)) {
1098
- return queryTextStyle(this.$parent, 'color', item.value)
1099
- }
1100
- return queryTextStyle(this.$parent, 'color', item)
1101
- })
1102
- this.foreColorConfig.value = findForeColorItem ? (DapCommon.isObject(findForeColorItem) ? findForeColorItem.value : findForeColorItem) : ''
1103
- //前景色按钮禁用
1104
- this.foreColorConfig.disabled = extraDisabled('foreColor')
1105
-
1106
- //显示已选择的背景色
1107
- const findBackColorItem = this.backColorConfig.selectConfig.options.find(item => {
1108
- if (DapCommon.isObject(item)) {
1109
- return queryTextStyle(this.$parent, 'background-color', item.value)
1110
- }
1111
- return queryTextStyle(this.$parent, 'background-color', item)
1112
- })
1113
- this.backColorConfig.value = findBackColorItem ? (DapCommon.isObject(findBackColorItem) ? findBackColorItem.value : findBackColorItem) : ''
1114
- //背景色按钮禁用
1115
- this.backColorConfig.disabled = extraDisabled('backColor')
1116
-
1117
- //清除格式按钮禁用
1118
- this.formatClearConfig.disabled = extraDisabled('formatClear')
1119
- }
1120
- }
1121
- }
1122
- }
1123
- </script>
1124
- <style lang="less" scoped>
1125
- .editify-toolbar {
1126
- display: flex;
1127
- justify-content: flex-start;
1128
- align-items: center;
1129
- padding: 6px 10px;
1130
-
1131
- .editify-icon-rotate {
1132
- transform: rotate(180deg);
1133
- }
1134
- }
1135
-
1136
- .editify-toolbar-link {
1137
- display: block;
1138
- width: 280px;
1139
- padding: 4px;
1140
-
1141
- .editify-toolbar-link-label {
1142
- display: block;
1143
- text-align: left;
1144
- margin-bottom: 10px;
1145
- font-size: @font-size;
1146
- color: @font-color;
1147
- }
1148
-
1149
- input {
1150
- appearance: none;
1151
- -webkit-appearance: none;
1152
- -moz-appearance: none;
1153
- display: block;
1154
- width: 100%;
1155
- margin: 0 0 10px 0;
1156
- padding: 4px 2px;
1157
- border: none;
1158
- font-size: @font-size;
1159
- color: @font-color;
1160
- border-bottom: 1px solid @border-color;
1161
- line-height: 1.5;
1162
- transition: all 500ms;
1163
- background-color: transparent;
1164
- outline: none;
1165
-
1166
- &::-webkit-input-placeholder,
1167
- &::placeholder {
1168
- color: @font-color-disabled;
1169
- font-family: inherit;
1170
- font-size: inherit;
1171
- vertical-align: middle;
1172
- }
1173
-
1174
- &[disabled] {
1175
- background-color: transparent;
1176
- opacity: 0.6;
1177
- }
1178
- }
1179
-
1180
- .editify-toolbar-link-footer {
1181
- display: flex;
1182
- justify-content: space-between;
1183
- align-items: center;
1184
- width: 100%;
1185
- font-size: @font-size;
1186
- color: @font-color-light;
1187
-
1188
- .editify-toolbar-link-operations {
1189
- display: flex;
1190
- justify-content: flex-start;
1191
- align-items: center;
1192
-
1193
- & > span,
1194
- & > a {
1195
- cursor: pointer;
1196
- opacity: 0.8;
1197
- transition: all 200ms;
1198
-
1199
- &:hover {
1200
- opacity: 1;
1201
- }
1202
- }
1203
-
1204
- & > span {
1205
- margin-right: 15px;
1206
- }
1207
-
1208
- & > a {
1209
- text-decoration: none;
1210
- }
1211
- }
1212
- }
1213
- }
1214
- </style>
1
+ <template>
2
+ <Layer v-model="show" ref="layer" :node="node" border placement="bottom-start" @show="layerShow" :useRange="type == 'text'">
3
+ <div class="editify-toolbar" ref="toolbar" :style="config.style">
4
+ <!-- 链接工具条 -->
5
+ <template v-if="type == 'link'">
6
+ <div class="editify-toolbar-link">
7
+ <div class="editify-toolbar-link-label">{{ $editTrans('linkAddress') }}</div>
8
+ <input @change="modifyLink" @focus="handleInputFocus" @blur="handleInputBlur" :placeholder="$editTrans('linkUrlEnterPlaceholder')" v-model.trim="linkConfig.url" type="url" />
9
+ <div class="editify-toolbar-link-footer">
10
+ <Checkbox @change="modifyLink" v-model="linkConfig.newOpen" :label="$editTrans('newWindowOpen')" :color="$parent.color" :size="10"></Checkbox>
11
+ <div class="editify-toolbar-link-operations">
12
+ <span @click="removeLink">{{ $editTrans('removeLink') }}</span>
13
+ <a :href="linkConfig.url" target="_blank" :style="{ color: $parent.color }">{{ $editTrans('viewLink') }}</a>
14
+ </div>
15
+ </div>
16
+ </div>
17
+ </template>
18
+ <!-- 图片工具条 -->
19
+ <template v-else-if="type == 'image'">
20
+ <!-- 设置宽度30% -->
21
+ <Button @operate="setWidth('30%')" name="set30Width" :title="$editTrans('width30')" :tooltip="config.tooltip" :color="$parent.color"> 30% </Button>
22
+ <!-- 设置宽度50% -->
23
+ <Button @operate="setWidth('50%')" name="set50Width" :title="$editTrans('width50')" :tooltip="config.tooltip" :color="$parent.color"> 50% </Button>
24
+ <!-- 设置宽度100% -->
25
+ <Button rightBorder @operate="setWidth('100%')" name="set100Width" :title="$editTrans('width100')" :tooltip="config.tooltip" :color="$parent.color"> 100% </Button>
26
+ <!-- 设置宽度auto -->
27
+ <Button @operate="setWidth('auto')" name="setAutoWidth" :title="$editTrans('auto')" :tooltip="config.tooltip" :color="$parent.color">
28
+ <Icon value="auto-width"></Icon>
29
+ </Button>
30
+ <!-- 删除图片 -->
31
+ <Button @operate="deleteElement('img')" name="deleteImage" :title="$editTrans('deleteImage')" :tooltip="config.tooltip" :color="$parent.color">
32
+ <Icon value="delete"></Icon>
33
+ </Button>
34
+ </template>
35
+ <!-- 视频工具条 -->
36
+ <template v-else-if="type == 'video'">
37
+ <!-- 设置宽度30% -->
38
+ <Button @operate="setWidth('30%')" name="set30Width" :title="$editTrans('width30')" :tooltip="config.tooltip" :color="$parent.color"> 30% </Button>
39
+ <!-- 设置宽度50% -->
40
+ <Button @operate="setWidth('50%')" name="set50Width" :title="$editTrans('width50')" :tooltip="config.tooltip" :color="$parent.color"> 50% </Button>
41
+ <!-- 设置宽度100% -->
42
+ <Button @operate="setWidth('100%')" name="set100Width" :title="$editTrans('width100')" :tooltip="config.tooltip" :color="$parent.color"> 100% </Button>
43
+ <!-- 设置宽度auto -->
44
+ <Button rightBorder @operate="setWidth('auto')" name="setAutoWidth" :title="$editTrans('auto')" :tooltip="config.tooltip" :color="$parent.color">
45
+ <Icon value="auto-width"></Icon>
46
+ </Button>
47
+ <!-- 自动播放 -->
48
+ <Button @operate="setVideo" name="autoplay" :title="videoConfig.autoplay ? $editTrans('disabledAutoplay') : $editTrans('autoplay')" :tooltip="config.tooltip" :color="$parent.color">
49
+ <Icon :value="videoConfig.autoplay ? 'autoplay' : 'stop'"></Icon>
50
+ </Button>
51
+ <!-- 循环播放 -->
52
+ <Button @operate="setVideo" name="loop" :title="videoConfig.loop ? $editTrans('disabledLoop') : $editTrans('loop')" :tooltip="config.tooltip" :color="$parent.color">
53
+ <Icon :value="videoConfig.loop ? 'loop' : 'single'"></Icon>
54
+ </Button>
55
+ <!-- 是否静音 -->
56
+ <Button @operate="setVideo" name="muted" :title="videoConfig.muted ? $editTrans('unmuted') : $editTrans('muted')" :tooltip="config.tooltip" :color="$parent.color">
57
+ <Icon :value="videoConfig.muted ? 'muted' : 'unmuted'"></Icon>
58
+ </Button>
59
+ <!-- 是否显示控制器 -->
60
+ <Button leftBorder @operate="setVideo" name="controls" :title="$editTrans('controls')" :tooltip="config.tooltip" :color="$parent.color">
61
+ <Icon value="controls"></Icon>
62
+ </Button>
63
+ <!-- 删除视频 -->
64
+ <Button @operate="deleteElement('video')" name="deleteVideo" :title="$editTrans('deleteVideo')" :tooltip="config.tooltip" :color="$parent.color">
65
+ <Icon value="delete"></Icon>
66
+ </Button>
67
+ </template>
68
+ <!-- 表格工具条 -->
69
+ <template v-else-if="type == 'table'">
70
+ <!-- 表格前插入段落 -->
71
+ <Button @operate="insertParagraphWithTable('up')" name="textWrapUp" :title="$editTrans('textWrapUp')" :tooltip="config.tooltip" :color="$parent.color">
72
+ <Icon value="text-wrap" class="editify-icon-rotate"></Icon>
73
+ </Button>
74
+ <!-- 表格后插入段落 -->
75
+ <Button @operate="insertParagraphWithTable('down')" rightBorder name="textWrapDown" :title="$editTrans('textWrapDown')" :tooltip="config.tooltip" :color="$parent.color">
76
+ <Icon value="text-wrap"></Icon>
77
+ </Button>
78
+ <!-- 向前插入行 -->
79
+ <Button @operate="insertTableRow('up')" name="insertRowTop" :title="$editTrans('insertRowTop')" :tooltip="config.tooltip" :color="$parent.color">
80
+ <Icon value="insert-row-top"></Icon>
81
+ </Button>
82
+ <!-- 向后插入行 -->
83
+ <Button @operate="insertTableRow('down')" name="insertRowBottom" :title="$editTrans('insertRowBottom')" :tooltip="config.tooltip" :color="$parent.color">
84
+ <Icon value="insert-row-bottom"></Icon>
85
+ </Button>
86
+ <!-- 删除行 -->
87
+ <Button @operate="deleteTableRow" rightBorder name="deleteRow" :title="$editTrans('deleteRow')" :tooltip="config.tooltip" :color="$parent.color">
88
+ <Icon value="delete-row"></Icon>
89
+ </Button>
90
+ <!-- 向前插入列 -->
91
+ <Button @operate="insertTableColumn('left')" name="insertColumnLeft" :title="$editTrans('insertColumnLeft')" :tooltip="config.tooltip" :color="$parent.color">
92
+ <Icon value="insert-column-left"></Icon>
93
+ </Button>
94
+ <!-- 向后插入列 -->
95
+ <Button @operate="insertTableColumn('right')" name="insertColumnRight" :title="$editTrans('insertColumnRight')" :tooltip="config.tooltip" :color="$parent.color">
96
+ <Icon value="insert-column-right"></Icon>
97
+ </Button>
98
+ <!-- 删除列 -->
99
+ <Button @operate="deleteTableColumn" rightBorder name="deleteColumn" :title="$editTrans('deleteColumn')" :tooltip="config.tooltip" :color="$parent.color">
100
+ <Icon value="delete-column"></Icon>
101
+ </Button>
102
+ <!-- 删除表格 -->
103
+ <Button @operate="deleteElement('table')" name="deleteTable" :title="$editTrans('deleteTable')" :tooltip="config.tooltip" :color="$parent.color">
104
+ <Icon value="delete-table"></Icon>
105
+ </Button>
106
+ </template>
107
+ <!-- 代码块工具条 -->
108
+ <template v-if="type == 'codeBlock'">
109
+ <!-- 代码块前插入段落 -->
110
+ <Button @operate="insertParagraphWithPre('up')" name="textWrapUp" :title="$editTrans('textWrapUp')" :tooltip="config.tooltip" :color="$parent.color">
111
+ <Icon value="text-wrap" class="editify-icon-rotate"></Icon>
112
+ </Button>
113
+ <!-- 代码块后插入段落 -->
114
+ <Button @operate="insertParagraphWithPre('down')" name="textWrapDown" :title="$editTrans('textWrapDown')" :tooltip="config.tooltip" :color="$parent.color">
115
+ <Icon value="text-wrap"></Icon>
116
+ </Button>
117
+ <!-- 代码块语言选择 -->
118
+ <Button v-if="languageConfig.show" name="languages" type="display" :title="$editTrans('selectLanguages')" :tooltip="config.tooltip" :leftBorder="languageConfig.leftBorder" :rightBorder="languageConfig.rightBorder" :display-config="languageConfig.displayConfig" :color="$parent.color" :active="languageConfig.active" :disabled="languageConfig.disabled" @operate="selectLanguage"></Button>
119
+ </template>
120
+ <!-- 文本工具条 -->
121
+ <template v-else-if="type == 'text'">
122
+ <!-- 设置段落和标题 -->
123
+ <Button v-if="headingConfig.show" name="heading" type="display" :title="$editTrans('heading')" :tooltip="config.tooltip" :display-config="headingConfig.displayConfig" :leftBorder="headingConfig.leftBorder" :rightBorder="headingConfig.rightBorder" :color="$parent.color" :active="headingConfig.active" :disabled="headingConfig.disabled" @operate="setHeading"></Button>
124
+ <!-- 对齐方式 -->
125
+ <Button v-if="alignConfig.show" name="align" type="select" :title="$editTrans('align')" :tooltip="config.tooltip" :select-config="alignConfig.selectConfig" :leftBorder="alignConfig.leftBorder" :rightBorder="alignConfig.rightBorder" :color="$parent.color" :active="alignConfig.active" :disabled="alignConfig.disabled" @operate="setAlign">
126
+ <Icon value="align-left"></Icon>
127
+ </Button>
128
+ <!-- 有序列表 -->
129
+ <Button v-if="orderListConfig.show" name="orderList" :title="$editTrans('orderList')" :tooltip="config.tooltip" :leftBorder="orderListConfig.leftBorder" :rightBorder="orderListConfig.rightBorder" :color="$parent.color" :active="orderListConfig.active" :disabled="orderListConfig.disabled" @operate="setList">
130
+ <Icon value="list-ordered"></Icon>
131
+ </Button>
132
+ <!-- 无序列表 -->
133
+ <Button v-if="unorderListConfig.show" name="unorderList" :title="$editTrans('unorderList')" :tooltip="config.tooltip" :leftBorder="unorderListConfig.leftBorder" :rightBorder="unorderListConfig.rightBorder" :color="$parent.color" :active="unorderListConfig.active" :disabled="unorderListConfig.disabled" @operate="setList">
134
+ <Icon value="list-unordered"></Icon>
135
+ </Button>
136
+ <!-- 任务列表 -->
137
+ <Button v-if="taskConfig.show" name="task" :title="$editTrans('task')" :tooltip="config.tooltip" :leftBorder="taskConfig.leftBorder" :rightBorder="taskConfig.rightBorder" :color="$parent.color" :active="taskConfig.active" :disabled="taskConfig.disabled" @operate="setTask">
138
+ <Icon value="task"></Icon>
139
+ </Button>
140
+ <!-- 加粗 -->
141
+ <Button v-if="boldConfig.show" name="bold" :title="$editTrans('bold')" :tooltip="config.tooltip" :leftBorder="boldConfig.leftBorder" :rightBorder="boldConfig.rightBorder" :color="$parent.color" :active="boldConfig.active" :disabled="boldConfig.disabled" @operate="setBold">
142
+ <Icon value="bold"></Icon>
143
+ </Button>
144
+ <!-- 斜体 -->
145
+ <Button v-if="italicConfig.show" name="italic" :title="$editTrans('italic')" :tooltip="config.tooltip" :leftBorder="italicConfig.leftBorder" :rightBorder="italicConfig.rightBorder" :color="$parent.color" :active="italicConfig.active" :disabled="italicConfig.disabled" @operate="setItalic">
146
+ <Icon value="italic"></Icon>
147
+ </Button>
148
+ <!-- 删除线 -->
149
+ <Button v-if="strikethroughConfig.show" name="strikethrough" :title="$editTrans('strikethrough')" :tooltip="config.tooltip" :leftBorder="strikethroughConfig.leftBorder" :rightBorder="strikethroughConfig.rightBorder" :color="$parent.color" :active="strikethroughConfig.active" :disabled="strikethroughConfig.disabled" @operate="setStrikethrough">
150
+ <Icon value="strikethrough"></Icon>
151
+ </Button>
152
+ <!-- 下划线 -->
153
+ <Button v-if="underlineConfig.show" name="underline" :title="$editTrans('underline')" :tooltip="config.tooltip" :leftBorder="underlineConfig.leftBorder" :rightBorder="underlineConfig.rightBorder" :color="$parent.color" :active="underlineConfig.active" :disabled="underlineConfig.disabled" @operate="setUnderline">
154
+ <Icon value="underline"></Icon>
155
+ </Button>
156
+ <!-- 行内代码块 -->
157
+ <Button v-if="codeConfig.show" name="code" :title="$editTrans('code')" :tooltip="config.tooltip" :leftBorder="codeConfig.leftBorder" :rightBorder="codeConfig.rightBorder" :color="$parent.color" :active="codeConfig.active" :disabled="codeConfig.disabled" @operate="setCodeStyle">
158
+ <Icon value="code"></Icon>
159
+ </Button>
160
+ <!-- 上标 -->
161
+ <Button v-if="superConfig.show" name="superscript" :title="$editTrans('superscript')" :tooltip="config.tooltip" :leftBorder="superConfig.leftBorder" :rightBorder="superConfig.rightBorder" :color="$parent.color" :active="superConfig.active" :disabled="superConfig.disabled" @operate="setSuperscript">
162
+ <Icon value="superscript"></Icon>
163
+ </Button>
164
+ <!-- 下标 -->
165
+ <Button v-if="subConfig.show" name="subscript" :title="$editTrans('subscript')" :tooltip="config.tooltip" :leftBorder="subConfig.leftBorder" :rightBorder="subConfig.rightBorder" :color="$parent.color" :active="subConfig.active" :disabled="subConfig.disabled" @operate="setSubscript">
166
+ <Icon value="subscript"></Icon>
167
+ </Button>
168
+ <!-- 字号大小 -->
169
+ <Button v-if="fontSizeConfig.show" name="fontSize" type="display" :title="$editTrans('fontSize')" :tooltip="config.tooltip" :display-config="fontSizeConfig.displayConfig" :leftBorder="fontSizeConfig.leftBorder" :rightBorder="fontSizeConfig.rightBorder" :color="$parent.color" :active="fontSizeConfig.active" :disabled="fontSizeConfig.disabled" @operate="setFontSize"></Button>
170
+ <!-- 字体 -->
171
+ <Button v-if="fontFamilyConfig.show" name="fontFamily" type="display" :title="$editTrans('fontFamily')" :tooltip="config.tooltip" :display-config="fontFamilyConfig.displayConfig" :leftBorder="fontFamilyConfig.leftBorder" :rightBorder="fontFamilyConfig.rightBorder" :color="$parent.color" :active="fontFamilyConfig.active" :disabled="fontFamilyConfig.disabled" @operate="setFontFamily"></Button>
172
+ <!-- 行高 -->
173
+ <Button v-if="lineHeightConfig.show" name="lineHeight" type="display" :title="$editTrans('lineHeight')" :tooltip="config.tooltip" :display-config="lineHeightConfig.displayConfig" :leftBorder="lineHeightConfig.leftBorder" :rightBorder="lineHeightConfig.rightBorder" :color="$parent.color" :active="lineHeightConfig.active" :disabled="lineHeightConfig.disabled" @operate="setLineHeight"></Button>
174
+ <!-- 前景色 -->
175
+ <Button v-if="foreColorConfig.show" name="foreColor" type="select" :title="$editTrans('foreColor')" :tooltip="config.tooltip" :select-config="foreColorConfig.selectConfig" :leftBorder="foreColorConfig.leftBorder" :rightBorder="foreColorConfig.rightBorder" :color="$parent.color" :active="foreColorConfig.active" :disabled="foreColorConfig.disabled" hideScroll ref="foreColor">
176
+ <Icon value="font-color"></Icon>
177
+ <template #layer="{ options }">
178
+ <Colors :tooltip="config.tooltip" :color="$parent.color" :value="foreColorConfig.value" @change="setForeColor" :data="options"></Colors>
179
+ </template>
180
+ </Button>
181
+ <!-- 背景色 -->
182
+ <Button v-if="backColorConfig.show" name="backColor" type="select" :title="$editTrans('backColor')" :tooltip="config.tooltip" :select-config="backColorConfig.selectConfig" :leftBorder="backColorConfig.leftBorder" :rightBorder="backColorConfig.rightBorder" :color="$parent.color" :active="backColorConfig.active" :disabled="backColorConfig.disabled" hideScroll ref="backColor">
183
+ <Icon value="brush"></Icon>
184
+ <template #layer="{ options }">
185
+ <Colors :tooltip="config.tooltip" :color="$parent.color" :value="backColorConfig.value" @change="setBackColor" :data="options"></Colors>
186
+ </template>
187
+ </Button>
188
+ <!-- 清除样式 -->
189
+ <Button v-if="formatClearConfig.show" name="formatClear" :title="$editTrans('formatClear')" :tooltip="config.tooltip" :leftBorder="formatClearConfig.leftBorder" :rightBorder="formatClearConfig.rightBorder" :color="$parent.color" :active="formatClearConfig.active" :disabled="formatClearConfig.disabled" @operate="clearFormat">
190
+ <Icon value="format-clear"></Icon>
191
+ </Button>
192
+ </template>
193
+ </div>
194
+ </Layer>
195
+ </template>
196
+ <script>
197
+ import Layer from './base/Layer'
198
+ import Tooltip from './base/Tooltip'
199
+ import Button from './base/Button'
200
+ import Icon from './base/Icon'
201
+ import Checkbox from './base/Checkbox'
202
+ import Colors from './common/Colors'
203
+ import { AlexElement } from 'alex-editor'
204
+ import { common as DapCommon } from 'dap-util'
205
+ import { getCurrentParsedomElement, removeTextStyle, removeTextMark, setTextStyle, setLineHeight, setTextMark, setList, setTask, setHeading, setAlign, isRangeInList, isRangeInTask, queryTextStyle, queryTextMark } from '../core/function'
206
+ export default {
207
+ name: 'Toolbar',
208
+ emits: ['update:modelValue'],
209
+ props: {
210
+ //是否显示
211
+ modelValue: {
212
+ type: Boolean,
213
+ default: false
214
+ },
215
+ //关联元素
216
+ node: {
217
+ type: [String, Node],
218
+ default: null
219
+ },
220
+ //类型
221
+ type: {
222
+ type: String,
223
+ default: 'text',
224
+ validator(value) {
225
+ return ['text', 'table', 'link', 'codeBlock', 'image', 'video'].includes(value)
226
+ }
227
+ },
228
+ //工具条配置
229
+ config: {
230
+ type: Object,
231
+ default: null
232
+ }
233
+ },
234
+ data() {
235
+ return {
236
+ //链接参数配置
237
+ linkConfig: {
238
+ //链接地址
239
+ url: '',
240
+ //链接是否新窗口打开
241
+ newOpen: false
242
+ },
243
+ //视频参数配置
244
+ videoConfig: {
245
+ //是否显示控制器
246
+ controls: false,
247
+ //是否循环
248
+ loop: false,
249
+ //是否自动播放
250
+ autoplay: false,
251
+ //是否静音
252
+ muted: false
253
+ },
254
+ //代码块选择语言按钮配置
255
+ languageConfig: {
256
+ show: this.config.codeBlock.languages.show,
257
+ displayConfig: {
258
+ options: this.config.codeBlock.languages.options,
259
+ value: '',
260
+ width: this.config.codeBlock.languages.width,
261
+ maxHeight: this.config.codeBlock.languages.maxHeight
262
+ },
263
+ leftBorder: this.config.codeBlock.languages.leftBorder,
264
+ rightBorder: this.config.codeBlock.languages.rightBorder,
265
+ active: false,
266
+ disabled: false
267
+ },
268
+ //标题按钮配置
269
+ headingConfig: {
270
+ show: this.config.text.heading.show,
271
+ displayConfig: {
272
+ options: this.config.text.heading.options,
273
+ value: '',
274
+ width: this.config.text.heading.width,
275
+ maxHeight: this.config.text.heading.maxHeight
276
+ },
277
+ defaultValue: this.config.text.heading.defaultValue,
278
+ leftBorder: this.config.text.heading.leftBorder,
279
+ rightBorder: this.config.text.heading.rightBorder,
280
+ active: false,
281
+ disabled: false
282
+ },
283
+ //对齐方式按钮配置
284
+ alignConfig: {
285
+ show: this.config.text.align.show,
286
+ selectConfig: {
287
+ options: this.config.text.align.options,
288
+ width: this.config.text.align.width,
289
+ maxHeight: this.config.text.align.maxHeight
290
+ },
291
+ leftBorder: this.config.text.align.leftBorder,
292
+ rightBorder: this.config.text.align.rightBorder,
293
+ active: false,
294
+ disabled: false
295
+ },
296
+ //有序列表按钮配置
297
+ orderListConfig: {
298
+ show: this.config.text.orderList.show,
299
+ leftBorder: this.config.text.orderList.leftBorder,
300
+ rightBorder: this.config.text.orderList.rightBorder,
301
+ active: false,
302
+ disabled: false
303
+ },
304
+ //无序列表按钮配置
305
+ unorderListConfig: {
306
+ show: this.config.text.unorderList.show,
307
+ leftBorder: this.config.text.unorderList.leftBorder,
308
+ rightBorder: this.config.text.unorderList.rightBorder,
309
+ active: false,
310
+ disabled: false
311
+ },
312
+ //任务列表按钮配置
313
+ taskConfig: {
314
+ show: this.config.text.task.show,
315
+ leftBorder: this.config.text.task.leftBorder,
316
+ rightBorder: this.config.text.task.rightBorder,
317
+ active: false,
318
+ disabled: false
319
+ },
320
+ //粗体按钮配置
321
+ boldConfig: {
322
+ show: this.config.text.bold.show,
323
+ leftBorder: this.config.text.bold.leftBorder,
324
+ rightBorder: this.config.text.bold.rightBorder,
325
+ active: false,
326
+ disabled: false
327
+ },
328
+ //斜体按钮配置
329
+ italicConfig: {
330
+ show: this.config.text.italic.show,
331
+ leftBorder: this.config.text.italic.leftBorder,
332
+ rightBorder: this.config.text.italic.rightBorder,
333
+ active: false,
334
+ disabled: false
335
+ },
336
+ //删除线按钮配置
337
+ strikethroughConfig: {
338
+ show: this.config.text.strikethrough.show,
339
+ leftBorder: this.config.text.strikethrough.leftBorder,
340
+ rightBorder: this.config.text.strikethrough.rightBorder,
341
+ active: false,
342
+ disabled: false
343
+ },
344
+ //下划线按钮配置
345
+ underlineConfig: {
346
+ show: this.config.text.underline.show,
347
+ leftBorder: this.config.text.underline.leftBorder,
348
+ rightBorder: this.config.text.underline.rightBorder,
349
+ active: false,
350
+ disabled: false
351
+ },
352
+ //行内代码块按钮配置
353
+ codeConfig: {
354
+ show: this.config.text.code.show,
355
+ leftBorder: this.config.text.code.leftBorder,
356
+ rightBorder: this.config.text.code.rightBorder,
357
+ active: false,
358
+ disabled: false
359
+ },
360
+ //上标按钮配置
361
+ superConfig: {
362
+ show: this.config.text.super.show,
363
+ leftBorder: this.config.text.super.leftBorder,
364
+ rightBorder: this.config.text.super.rightBorder,
365
+ active: false,
366
+ disabled: false
367
+ },
368
+ //下标按钮配置
369
+ subConfig: {
370
+ show: this.config.text.sub.show,
371
+ leftBorder: this.config.text.sub.leftBorder,
372
+ rightBorder: this.config.text.sub.rightBorder,
373
+ active: false,
374
+ disabled: false
375
+ },
376
+ //字号按钮配置
377
+ fontSizeConfig: {
378
+ show: this.config.text.fontSize.show,
379
+ displayConfig: {
380
+ options: this.config.text.fontSize.options,
381
+ value: '',
382
+ width: this.config.text.fontSize.width,
383
+ maxHeight: this.config.text.fontSize.maxHeight
384
+ },
385
+ defaultValue: this.config.text.fontSize.defaultValue,
386
+ leftBorder: this.config.text.fontSize.leftBorder,
387
+ rightBorder: this.config.text.fontSize.rightBorder,
388
+ active: false,
389
+ disabled: false
390
+ },
391
+ //字体按钮配置
392
+ fontFamilyConfig: {
393
+ show: this.config.text.fontFamily.show,
394
+ displayConfig: {
395
+ options: this.config.text.fontFamily.options,
396
+ value: '',
397
+ width: this.config.text.fontFamily.width,
398
+ maxHeight: this.config.text.fontFamily.maxHeight
399
+ },
400
+ defaultValue: this.config.text.fontFamily.defaultValue,
401
+ leftBorder: this.config.text.fontFamily.leftBorder,
402
+ rightBorder: this.config.text.fontFamily.rightBorder,
403
+ active: false,
404
+ disabled: false
405
+ },
406
+ //行高按钮配置
407
+ lineHeightConfig: {
408
+ show: this.config.text.lineHeight.show,
409
+ displayConfig: {
410
+ options: this.config.text.lineHeight.options,
411
+ value: '',
412
+ width: this.config.text.lineHeight.width,
413
+ maxHeight: this.config.text.lineHeight.maxHeight
414
+ },
415
+ defaultValue: this.config.text.lineHeight.defaultValue,
416
+ leftBorder: this.config.text.lineHeight.leftBorder,
417
+ rightBorder: this.config.text.lineHeight.rightBorder,
418
+ active: false,
419
+ disabled: false
420
+ },
421
+ //前景颜色按钮配置
422
+ foreColorConfig: {
423
+ show: this.config.text.foreColor.show,
424
+ selectConfig: {
425
+ options: this.config.text.foreColor.options
426
+ },
427
+ leftBorder: this.config.text.foreColor.leftBorder,
428
+ rightBorder: this.config.text.foreColor.rightBorder,
429
+ value: '', //选择的颜色值
430
+ active: false,
431
+ disabled: false
432
+ },
433
+ //背景颜色按钮配置
434
+ backColorConfig: {
435
+ show: this.config.text.backColor.show,
436
+ selectConfig: {
437
+ options: this.config.text.backColor.options
438
+ },
439
+ leftBorder: this.config.text.backColor.leftBorder,
440
+ rightBorder: this.config.text.backColor.rightBorder,
441
+ value: '', //选择的颜色值
442
+ active: false,
443
+ disabled: false
444
+ },
445
+ //清除格式按钮配置
446
+ formatClearConfig: {
447
+ show: this.config.text.formatClear.show,
448
+ leftBorder: this.config.text.formatClear.leftBorder,
449
+ rightBorder: this.config.text.formatClear.rightBorder,
450
+ active: false,
451
+ disabled: false
452
+ }
453
+ }
454
+ },
455
+ computed: {
456
+ //是否显示
457
+ show: {
458
+ get() {
459
+ return this.modelValue
460
+ },
461
+ set(val) {
462
+ this.$emit('update:modelValue', val)
463
+ }
464
+ }
465
+ },
466
+ components: {
467
+ Layer,
468
+ Tooltip,
469
+ Button,
470
+ Icon,
471
+ Checkbox,
472
+ Colors
473
+ },
474
+ inject: ['$editTrans'],
475
+ methods: {
476
+ //输入框获取焦点
477
+ handleInputFocus(e) {
478
+ if (this.$parent.color) {
479
+ e.currentTarget.style.borderColor = this.$parent.color
480
+ }
481
+ },
482
+ //输入框失去焦点
483
+ handleInputBlur(e) {
484
+ e.currentTarget.style.borderColor = ''
485
+ },
486
+ //清除格式
487
+ clearFormat() {
488
+ removeTextStyle(this.$parent)
489
+ removeTextMark(this.$parent)
490
+ this.$parent.editor.formatElementStack()
491
+ this.$parent.editor.domRender()
492
+ this.$parent.editor.rangeRender()
493
+ },
494
+ //设置背景色
495
+ setBackColor(value) {
496
+ setTextStyle(this.$parent, {
497
+ 'background-color': value
498
+ })
499
+ this.$refs.backColor.hideLayer()
500
+ this.$parent.editor.formatElementStack()
501
+ this.$parent.editor.domRender()
502
+ this.$parent.editor.rangeRender()
503
+ },
504
+ //设置前景色
505
+ setForeColor(value) {
506
+ setTextStyle(this.$parent, {
507
+ color: value
508
+ })
509
+ this.$refs.foreColor.hideLayer()
510
+ this.$parent.editor.formatElementStack()
511
+ this.$parent.editor.domRender()
512
+ this.$parent.editor.rangeRender()
513
+ },
514
+ //设置行高
515
+ setLineHeight(name, value) {
516
+ setLineHeight(this.$parent, value)
517
+ this.$parent.editor.formatElementStack()
518
+ this.$parent.editor.domRender()
519
+ this.$parent.editor.rangeRender()
520
+ },
521
+ //设置字体
522
+ setFontFamily(name, value) {
523
+ setTextStyle(this.$parent, {
524
+ 'font-family': value
525
+ })
526
+ this.$parent.editor.formatElementStack()
527
+ this.$parent.editor.domRender()
528
+ this.$parent.editor.rangeRender()
529
+ },
530
+ //设置字号
531
+ setFontSize(name, value) {
532
+ setTextStyle(this.$parent, {
533
+ 'font-size': value
534
+ })
535
+ this.$parent.editor.formatElementStack()
536
+ this.$parent.editor.domRender()
537
+ this.$parent.editor.rangeRender()
538
+ },
539
+ //设置上标
540
+ setSuperscript() {
541
+ if (queryTextStyle(this.$parent, 'vertical-align', 'super')) {
542
+ removeTextStyle(this.$parent, ['vertical-align'])
543
+ } else {
544
+ setTextStyle(this.$parent, {
545
+ 'vertical-align': 'super'
546
+ })
547
+ }
548
+ this.$parent.editor.formatElementStack()
549
+ this.$parent.editor.domRender()
550
+ this.$parent.editor.rangeRender()
551
+ },
552
+ //设置下标
553
+ setSubscript() {
554
+ if (queryTextStyle(this.$parent, 'vertical-align', 'sub')) {
555
+ removeTextStyle(this.$parent, ['vertical-align'])
556
+ } else {
557
+ setTextStyle(this.$parent, {
558
+ 'vertical-align': 'sub'
559
+ })
560
+ }
561
+ this.$parent.editor.formatElementStack()
562
+ this.$parent.editor.domRender()
563
+ this.$parent.editor.rangeRender()
564
+ },
565
+ //设置行内代码样式
566
+ setCodeStyle() {
567
+ if (queryTextMark(this.$parent, 'data-editify-code')) {
568
+ removeTextMark(this.$parent, ['data-editify-code'])
569
+ } else {
570
+ setTextMark(this.$parent, {
571
+ 'data-editify-code': true
572
+ })
573
+ }
574
+ this.$parent.editor.formatElementStack()
575
+ this.$parent.editor.domRender()
576
+ this.$parent.editor.rangeRender()
577
+ },
578
+ //设置下划线
579
+ setUnderline() {
580
+ if (queryTextStyle(this.$parent, 'text-decoration', 'underline') || queryTextStyle(this.$parent, 'text-decoration-line', 'underline')) {
581
+ removeTextStyle(this.$parent, ['text-decoration', 'text-decoration-line'])
582
+ } else {
583
+ setTextStyle(this.$parent, {
584
+ 'text-decoration': 'underline'
585
+ })
586
+ }
587
+ this.$parent.editor.formatElementStack()
588
+ this.$parent.editor.domRender()
589
+ this.$parent.editor.rangeRender()
590
+ },
591
+ //设置删除线
592
+ setStrikethrough() {
593
+ if (queryTextStyle(this.$parent, 'text-decoration', 'line-through') || queryTextStyle(this.$parent, 'text-decoration-line', 'line-through')) {
594
+ removeTextStyle(this.$parent, ['text-decoration', 'text-decoration-line'])
595
+ } else {
596
+ setTextStyle(this.$parent, {
597
+ 'text-decoration': 'line-through'
598
+ })
599
+ }
600
+ this.$parent.editor.formatElementStack()
601
+ this.$parent.editor.domRender()
602
+ this.$parent.editor.rangeRender()
603
+ },
604
+ //设置列表
605
+ setList(name) {
606
+ setList(this.$parent, name == 'orderList')
607
+ this.$parent.editor.formatElementStack()
608
+ this.$parent.editor.domRender()
609
+ this.$parent.editor.rangeRender()
610
+ },
611
+ //设置任务列表
612
+ setTask() {
613
+ setTask(this.$parent)
614
+ this.$parent.editor.formatElementStack()
615
+ this.$parent.editor.domRender()
616
+ this.$parent.editor.rangeRender()
617
+ },
618
+ //斜体
619
+ setItalic() {
620
+ if (queryTextStyle(this.$parent, 'font-style', 'italic')) {
621
+ removeTextStyle(this.$parent, ['font-style'])
622
+ } else {
623
+ setTextStyle(this.$parent, {
624
+ 'font-style': 'italic'
625
+ })
626
+ }
627
+ this.$parent.editor.formatElementStack()
628
+ this.$parent.editor.domRender()
629
+ this.$parent.editor.rangeRender()
630
+ },
631
+ //加粗
632
+ setBold() {
633
+ if (queryTextStyle(this.$parent, 'font-weight', 'bold') || queryTextStyle(this.$parent, 'font-weight', '700')) {
634
+ removeTextStyle(this.$parent, ['font-weight'])
635
+ } else {
636
+ setTextStyle(this.$parent, {
637
+ 'font-weight': 'bold'
638
+ })
639
+ }
640
+ this.$parent.editor.formatElementStack()
641
+ this.$parent.editor.domRender()
642
+ this.$parent.editor.rangeRender()
643
+ },
644
+ //设置标题
645
+ setHeading(name, value) {
646
+ setHeading(this.$parent, value)
647
+ this.$parent.editor.formatElementStack()
648
+ this.$parent.editor.domRender()
649
+ this.$parent.editor.rangeRender()
650
+ },
651
+ //设置对齐方式
652
+ setAlign(name, value) {
653
+ setAlign(this.$parent, value)
654
+ this.$parent.editor.formatElementStack()
655
+ this.$parent.editor.domRender()
656
+ this.$parent.editor.rangeRender()
657
+ },
658
+ //设置视频属性
659
+ setVideo(prop) {
660
+ const element = this.$parent.editor.range.anchor.element
661
+ //当前是拥有该属性
662
+ if (this.videoConfig[prop]) {
663
+ delete element.marks[prop]
664
+ }
665
+ //当前无该属性
666
+ else {
667
+ element.marks[prop] = true
668
+ }
669
+ this.videoConfig[prop] = !this.videoConfig[prop]
670
+ this.$parent.editor.formatElementStack()
671
+ this.$parent.editor.domRender()
672
+ this.$parent.editor.rangeRender()
673
+ },
674
+ //设置图片或者视频宽度
675
+ setWidth(value) {
676
+ const element = this.$parent.editor.range.anchor.element
677
+ if (element) {
678
+ const styles = {
679
+ width: value
680
+ }
681
+ if (element.hasStyles()) {
682
+ element.styles = Object.assign(element.styles, styles)
683
+ } else {
684
+ element.styles = styles
685
+ }
686
+ this.$parent.editor.formatElementStack()
687
+ this.$parent.editor.domRender()
688
+ this.$parent.editor.rangeRender()
689
+ //更新工具条位置
690
+ setTimeout(() => {
691
+ this.$refs.layer.setPosition()
692
+ }, 0)
693
+ }
694
+ },
695
+ //修改链接
696
+ modifyLink() {
697
+ if (!this.linkConfig.url) {
698
+ return
699
+ }
700
+ const link = getCurrentParsedomElement(this.$parent, 'a')
701
+ if (link) {
702
+ link.marks.href = this.linkConfig.url
703
+ if (this.linkConfig.newOpen) {
704
+ link.marks.target = '_blank'
705
+ } else {
706
+ delete link.marks.target
707
+ }
708
+ }
709
+ this.$parent.editor.formatElementStack()
710
+ this.$parent.editor.domRender()
711
+ },
712
+ //移除链接
713
+ removeLink() {
714
+ const link = getCurrentParsedomElement(this.$parent, 'a')
715
+ if (link) {
716
+ link.parsedom = AlexElement.TEXT_NODE
717
+ delete link.marks.target
718
+ delete link.marks.href
719
+ }
720
+ this.$parent.editor.formatElementStack()
721
+ this.$parent.editor.domRender()
722
+ this.$parent.editor.rangeRender()
723
+ },
724
+ //选择代码语言
725
+ selectLanguage(name, value) {
726
+ const pre = getCurrentParsedomElement(this.$parent, 'pre')
727
+ if (pre) {
728
+ Object.assign(pre.marks, {
729
+ 'data-editify-hljs': value
730
+ })
731
+ this.$parent.editor.formatElementStack()
732
+ this.$parent.editor.domRender()
733
+ this.$parent.editor.rangeRender()
734
+ }
735
+ },
736
+ //代码块前后插入段落
737
+ insertParagraphWithPre(type = 'up') {
738
+ if (!this.$parent.editor.range.anchor.isEqual(this.$parent.editor.range.focus)) {
739
+ this.$parent.editor.range.anchor.element = this.$parent.editor.range.focus.element
740
+ this.$parent.editor.range.anchor.offset = this.$parent.editor.range.focus.offset
741
+ }
742
+ const pre = getCurrentParsedomElement(this.$parent, 'pre')
743
+ if (pre) {
744
+ const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
745
+ const breakEl = new AlexElement('closed', 'br', null, null, null)
746
+ this.$parent.editor.addElementTo(breakEl, paragraph)
747
+ if (type == 'up') {
748
+ this.$parent.editor.addElementBefore(paragraph, pre)
749
+ } else {
750
+ this.$parent.editor.addElementAfter(paragraph, pre)
751
+ }
752
+ this.$parent.editor.range.anchor.moveToEnd(paragraph)
753
+ this.$parent.editor.range.focus.moveToEnd(paragraph)
754
+ this.$parent.editor.formatElementStack()
755
+ this.$parent.editor.domRender()
756
+ this.$parent.editor.rangeRender()
757
+ }
758
+ },
759
+ //表格前后插入列
760
+ insertTableColumn(type = 'left') {
761
+ if (!this.$parent.editor.range.anchor.isEqual(this.$parent.editor.range.focus)) {
762
+ this.$parent.editor.range.anchor.element = this.$parent.editor.range.focus.element
763
+ this.$parent.editor.range.anchor.offset = this.$parent.editor.range.focus.offset
764
+ }
765
+ const table = getCurrentParsedomElement(this.$parent, 'table')
766
+ const column = getCurrentParsedomElement(this.$parent, 'td')
767
+ const tbody = getCurrentParsedomElement(this.$parent, 'tbody')
768
+ if (column && table && tbody) {
769
+ const rows = tbody.children
770
+ const index = column.parent.children.findIndex(item => {
771
+ return item.isEqual(column)
772
+ })
773
+ //插入列
774
+ rows.forEach(row => {
775
+ const newColumn = column.clone(false)
776
+ const breakEl = new AlexElement('closed', 'br', null, null, null)
777
+ this.$parent.editor.addElementTo(breakEl, newColumn)
778
+ if (type == 'left') {
779
+ this.$parent.editor.addElementTo(newColumn, row, index)
780
+ } else {
781
+ this.$parent.editor.addElementTo(newColumn, row, index + 1)
782
+ }
783
+ })
784
+ //插入col
785
+ const colgroup = table.children.find(item => {
786
+ return item.parsedom == 'colgroup'
787
+ })
788
+ const col = new AlexElement('closed', 'col', null, null, null)
789
+ if (type == 'left') {
790
+ this.$parent.editor.addElementTo(col, colgroup, index)
791
+ } else {
792
+ this.$parent.editor.addElementTo(col, colgroup, index + 1)
793
+ }
794
+ //渲染
795
+ this.$parent.editor.formatElementStack()
796
+ if (type == 'left') {
797
+ const previousColumn = this.$parent.editor.getPreviousElement(column)
798
+ this.$parent.editor.range.anchor.moveToStart(previousColumn)
799
+ this.$parent.editor.range.focus.moveToStart(previousColumn)
800
+ } else {
801
+ const nextColumn = this.$parent.editor.getNextElement(column)
802
+ this.$parent.editor.range.anchor.moveToStart(nextColumn)
803
+ this.$parent.editor.range.focus.moveToStart(nextColumn)
804
+ }
805
+ this.$parent.editor.domRender()
806
+ this.$parent.editor.rangeRender()
807
+ }
808
+ },
809
+ //表格前后插入行
810
+ insertTableRow(type = 'up') {
811
+ if (!this.$parent.editor.range.anchor.isEqual(this.$parent.editor.range.focus)) {
812
+ this.$parent.editor.range.anchor.element = this.$parent.editor.range.focus.element
813
+ this.$parent.editor.range.anchor.offset = this.$parent.editor.range.focus.offset
814
+ }
815
+ const table = getCurrentParsedomElement(this.$parent, 'table')
816
+ const row = getCurrentParsedomElement(this.$parent, 'tr')
817
+ if (table && row) {
818
+ const newRow = row.clone()
819
+ newRow.children.forEach(column => {
820
+ column.children = []
821
+ const breakEl = new AlexElement('closed', 'br', null, null, null)
822
+ this.$parent.editor.addElementTo(breakEl, column)
823
+ })
824
+ if (type == 'up') {
825
+ this.$parent.editor.addElementBefore(newRow, row)
826
+ } else {
827
+ this.$parent.editor.addElementAfter(newRow, row)
828
+ }
829
+ this.$parent.editor.formatElementStack()
830
+ this.$parent.editor.range.anchor.moveToStart(newRow)
831
+ this.$parent.editor.range.focus.moveToStart(newRow)
832
+ this.$parent.editor.domRender()
833
+ this.$parent.editor.rangeRender()
834
+ //更新工具条位置
835
+ setTimeout(() => {
836
+ this.$refs.layer.setPosition()
837
+ }, 0)
838
+ }
839
+ },
840
+ //表格前后插入段落
841
+ insertParagraphWithTable(type = 'up') {
842
+ const table = getCurrentParsedomElement(this.$parent, 'table')
843
+ if (table) {
844
+ const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
845
+ const breakEl = new AlexElement('closed', 'br', null, null, null)
846
+ this.$parent.editor.addElementTo(breakEl, paragraph)
847
+ if (type == 'up') {
848
+ this.$parent.editor.addElementBefore(paragraph, table)
849
+ } else {
850
+ this.$parent.editor.addElementAfter(paragraph, table)
851
+ }
852
+ this.$parent.editor.range.anchor.moveToEnd(paragraph)
853
+ this.$parent.editor.range.focus.moveToEnd(paragraph)
854
+ this.$parent.editor.formatElementStack()
855
+ this.$parent.editor.domRender()
856
+ this.$parent.editor.rangeRender()
857
+ }
858
+ },
859
+ //删除表格行
860
+ deleteTableRow() {
861
+ if (!this.$parent.editor.range.anchor.isEqual(this.$parent.editor.range.focus)) {
862
+ this.$parent.editor.range.anchor.element = this.$parent.editor.range.focus.element
863
+ this.$parent.editor.range.anchor.offset = this.$parent.editor.range.focus.offset
864
+ }
865
+ const table = getCurrentParsedomElement(this.$parent, 'table')
866
+ const row = getCurrentParsedomElement(this.$parent, 'tr')
867
+ if (table && row) {
868
+ const parent = row.parent
869
+ if (parent.children.length == 1) {
870
+ this.deleteElement('table')
871
+ return
872
+ }
873
+ const previousRow = this.$parent.editor.getPreviousElement(row)
874
+ const nextRow = this.$parent.editor.getNextElement(row)
875
+ row.toEmpty()
876
+ this.$parent.editor.formatElementStack()
877
+ if (previousRow) {
878
+ this.$parent.editor.range.anchor.moveToEnd(previousRow.children[0])
879
+ this.$parent.editor.range.focus.moveToEnd(previousRow.children[0])
880
+ } else {
881
+ this.$parent.editor.range.anchor.moveToEnd(nextRow.children[0])
882
+ this.$parent.editor.range.focus.moveToEnd(nextRow.children[0])
883
+ }
884
+ this.$parent.editor.domRender()
885
+ this.$parent.editor.rangeRender()
886
+ //更新工具条位置
887
+ setTimeout(() => {
888
+ this.$refs.layer.setPosition()
889
+ }, 0)
890
+ }
891
+ },
892
+ //删除表格列
893
+ deleteTableColumn() {
894
+ if (!this.$parent.editor.range.anchor.isEqual(this.$parent.editor.range.focus)) {
895
+ this.$parent.editor.range.anchor.element = this.$parent.editor.range.focus.element
896
+ this.$parent.editor.range.anchor.offset = this.$parent.editor.range.focus.offset
897
+ }
898
+ const column = getCurrentParsedomElement(this.$parent, 'td')
899
+ const tbody = getCurrentParsedomElement(this.$parent, 'tbody')
900
+ const table = getCurrentParsedomElement(this.$parent, 'table')
901
+ if (column && table && tbody) {
902
+ const rows = tbody.children
903
+ const parent = column.parent
904
+ if (parent.children.length == 1) {
905
+ this.deleteElement('table')
906
+ return
907
+ }
908
+ const previousColumn = this.$parent.editor.getPreviousElement(column)
909
+ const nextColumn = this.$parent.editor.getNextElement(column)
910
+ const index = column.parent.children.findIndex(item => {
911
+ return item.isEqual(column)
912
+ })
913
+ //删除列
914
+ rows.forEach(row => {
915
+ row.children[index].toEmpty()
916
+ })
917
+ //删除col
918
+ const colgroup = table.children.find(item => {
919
+ return item.parsedom == 'colgroup'
920
+ })
921
+ colgroup.children[index].toEmpty()
922
+ //渲染
923
+ this.$parent.editor.formatElementStack()
924
+ if (previousColumn) {
925
+ this.$parent.editor.range.anchor.moveToEnd(previousColumn)
926
+ this.$parent.editor.range.focus.moveToEnd(previousColumn)
927
+ } else {
928
+ this.$parent.editor.range.anchor.moveToEnd(nextColumn)
929
+ this.$parent.editor.range.focus.moveToEnd(nextColumn)
930
+ }
931
+ this.$parent.editor.domRender()
932
+ this.$parent.editor.rangeRender()
933
+ }
934
+ },
935
+ //删除元素
936
+ deleteElement(parsedom) {
937
+ const element = getCurrentParsedomElement(this.$parent, parsedom)
938
+ if (element) {
939
+ element.toEmpty()
940
+ this.$parent.editor.formatElementStack()
941
+ this.$parent.editor.domRender()
942
+ this.$parent.editor.rangeRender()
943
+ }
944
+ },
945
+ //浮层显示时
946
+ layerShow() {
947
+ //代码块初始化展示设置
948
+ if (this.type == 'codeBlock') {
949
+ const pre = getCurrentParsedomElement(this.$parent, 'pre')
950
+ if (pre) {
951
+ this.languageConfig.displayConfig.value = pre.marks['data-editify-hljs'] || ''
952
+ }
953
+ }
954
+ //链接初始化展示
955
+ else if (this.type == 'link') {
956
+ const link = getCurrentParsedomElement(this.$parent, 'a')
957
+ if (link) {
958
+ this.linkConfig.url = link.marks['href']
959
+ this.linkConfig.newOpen = link.marks['target'] == '_blank'
960
+ }
961
+ }
962
+ //视频初始化显示
963
+ else if (this.type == 'video') {
964
+ const video = getCurrentParsedomElement(this.$parent, 'video')
965
+ if (video) {
966
+ this.videoConfig.autoplay = !!video.marks['autoplay']
967
+ this.videoConfig.loop = !!video.marks['loop']
968
+ this.videoConfig.controls = !!video.marks['controls']
969
+ this.videoConfig.muted = !!video.marks['muted']
970
+ }
971
+ }
972
+ //文本工具条初始化显示
973
+ else if (this.type == 'text') {
974
+ //额外禁用判定
975
+ const extraDisabled = name => {
976
+ if (typeof this.config.extraDisabled == 'function') {
977
+ return this.config.extraDisabled.apply(this.$parent, [name]) || false
978
+ }
979
+ return false
980
+ }
981
+ //显示已设置标题
982
+ const findHeadingItem = this.headingConfig.displayConfig.options.find(item => {
983
+ let val = item
984
+ if (DapCommon.isObject(item)) {
985
+ val = item.value
986
+ }
987
+ return this.$parent.dataRangeCaches.list.every(el => {
988
+ if (el.element.isBlock()) {
989
+ return el.element.parsedom == val
990
+ }
991
+ return el.element.getBlock().parsedom == val
992
+ })
993
+ })
994
+ this.headingConfig.displayConfig.value = findHeadingItem ? (DapCommon.isObject(findHeadingItem) ? findHeadingItem.value : findHeadingItem) : this.headingConfig.defaultValue
995
+ //标题禁用
996
+ this.headingConfig.disabled = extraDisabled('heading')
997
+
998
+ //对齐方式禁用
999
+ this.alignConfig.disabled = extraDisabled('align')
1000
+
1001
+ //有序列表按钮激活
1002
+ this.orderListConfig.active = isRangeInList(this.$parent, true)
1003
+ //有序列表按钮禁用
1004
+ this.orderListConfig.disabled = extraDisabled('orderList')
1005
+
1006
+ //无序列表按钮激活
1007
+ this.unorderListConfig.active = isRangeInList(this.$parent, false)
1008
+ //无序列表按钮禁用
1009
+ this.unorderListConfig.disabled = extraDisabled('unorderList')
1010
+
1011
+ //任务列表按钮激活
1012
+ this.taskConfig.active = isRangeInTask(this.$parent)
1013
+ //任务列表按钮禁用
1014
+ this.taskConfig.disabled = extraDisabled('task')
1015
+
1016
+ //粗体按钮激活
1017
+ this.boldConfig.active = queryTextStyle(this.$parent, 'font-weight', 'bold') || queryTextStyle(this.$parent, 'font-weight', '700')
1018
+ //粗体按钮禁用
1019
+ this.boldConfig.disabled = extraDisabled('bold')
1020
+
1021
+ //斜体按钮激活
1022
+ this.italicConfig.active = queryTextStyle(this.$parent, 'font-style', 'italic')
1023
+ //斜体按钮禁用
1024
+ this.italicConfig.disabled = extraDisabled('italic')
1025
+
1026
+ //删除线按钮激活
1027
+ this.strikethroughConfig.active = queryTextStyle(this.$parent, 'text-decoration', 'line-through') || queryTextStyle(this.$parent, 'text-decoration-line', 'line-through')
1028
+ //删除线按钮禁用
1029
+ this.strikethroughConfig.disabled = extraDisabled('strikethrough')
1030
+
1031
+ //下划线按钮激活
1032
+ this.underlineConfig.active = queryTextStyle(this.$parent, 'text-decoration', 'underline') || queryTextStyle(this.$parent, 'text-decoration-line', 'underline')
1033
+ //下划线按钮禁用
1034
+ this.underlineConfig.disabled = extraDisabled('underline')
1035
+
1036
+ //行内代码按钮激活
1037
+ this.codeConfig.active = queryTextMark(this.$parent, 'data-editify-code')
1038
+ //行内代码按钮禁用
1039
+ this.codeConfig.disabled = extraDisabled('code')
1040
+
1041
+ //上标按钮激活
1042
+ this.superConfig.active = queryTextStyle(this.$parent, 'vertical-align', 'super')
1043
+ //上标按钮禁用
1044
+ this.superConfig.disabled = extraDisabled('super')
1045
+
1046
+ //下标按钮激活
1047
+ this.subConfig.active = queryTextStyle(this.$parent, 'vertical-align', 'sub')
1048
+ //下标按钮禁用
1049
+ this.subConfig.disabled = extraDisabled('sub')
1050
+
1051
+ //显示已选择字号
1052
+ const findFontItem = this.fontSizeConfig.displayConfig.options.find(item => {
1053
+ if (DapCommon.isObject(item)) {
1054
+ return queryTextStyle(this.$parent, 'font-size', item.value)
1055
+ }
1056
+ return queryTextStyle(this.$parent, 'font-size', item)
1057
+ })
1058
+ this.fontSizeConfig.displayConfig.value = findFontItem ? (DapCommon.isObject(findFontItem) ? findFontItem.value : findFontItem) : this.fontSizeConfig.defaultValue
1059
+ //字号按钮禁用
1060
+ this.fontSizeConfig.disabled = extraDisabled('fontSize')
1061
+
1062
+ //显示已选择字体
1063
+ const findFamilyItem = this.fontFamilyConfig.displayConfig.options.find(item => {
1064
+ if (DapCommon.isObject(item)) {
1065
+ return queryTextStyle(this.$parent, 'font-family', item.value)
1066
+ }
1067
+ return queryTextStyle(this.$parent, 'font-family', item)
1068
+ })
1069
+ this.fontFamilyConfig.displayConfig.value = findFamilyItem ? (DapCommon.isObject(findFamilyItem) ? findFamilyItem.value : findFamilyItem) : this.fontFamilyConfig.defaultValue
1070
+ //字体按钮禁用
1071
+ this.fontFamilyConfig.disabled = extraDisabled('fontFamily')
1072
+
1073
+ //显示已设置行高
1074
+ const findHeightItem = this.lineHeightConfig.displayConfig.options.find(item => {
1075
+ let val = item
1076
+ if (DapCommon.isObject(item)) {
1077
+ val = item.value
1078
+ }
1079
+ return this.$parent.dataRangeCaches.list.every(el => {
1080
+ if (el.element.isBlock() || el.element.isInblock()) {
1081
+ return el.element.hasStyles() && el.element.styles['line-height'] == val
1082
+ }
1083
+ const block = el.element.getBlock()
1084
+ const inblock = el.element.getInblock()
1085
+ if (inblock) {
1086
+ return inblock.hasStyles() && inblock.styles['line-height'] == val
1087
+ }
1088
+ return block.hasStyles() && block.styles['line-height'] == val
1089
+ })
1090
+ })
1091
+ this.lineHeightConfig.displayConfig.value = findHeightItem ? (DapCommon.isObject(findHeightItem) ? findHeightItem.value : findHeightItem) : this.lineHeightConfig.defaultValue
1092
+ //行高按钮禁用
1093
+ this.lineHeightConfig.disabled = extraDisabled('lineHeight')
1094
+
1095
+ //显示已选择的前景色
1096
+ const findForeColorItem = this.foreColorConfig.selectConfig.options.find(item => {
1097
+ if (DapCommon.isObject(item)) {
1098
+ return queryTextStyle(this.$parent, 'color', item.value)
1099
+ }
1100
+ return queryTextStyle(this.$parent, 'color', item)
1101
+ })
1102
+ this.foreColorConfig.value = findForeColorItem ? (DapCommon.isObject(findForeColorItem) ? findForeColorItem.value : findForeColorItem) : ''
1103
+ //前景色按钮禁用
1104
+ this.foreColorConfig.disabled = extraDisabled('foreColor')
1105
+
1106
+ //显示已选择的背景色
1107
+ const findBackColorItem = this.backColorConfig.selectConfig.options.find(item => {
1108
+ if (DapCommon.isObject(item)) {
1109
+ return queryTextStyle(this.$parent, 'background-color', item.value)
1110
+ }
1111
+ return queryTextStyle(this.$parent, 'background-color', item)
1112
+ })
1113
+ this.backColorConfig.value = findBackColorItem ? (DapCommon.isObject(findBackColorItem) ? findBackColorItem.value : findBackColorItem) : ''
1114
+ //背景色按钮禁用
1115
+ this.backColorConfig.disabled = extraDisabled('backColor')
1116
+
1117
+ //清除格式按钮禁用
1118
+ this.formatClearConfig.disabled = extraDisabled('formatClear')
1119
+ }
1120
+ }
1121
+ }
1122
+ }
1123
+ </script>
1124
+ <style lang="less" scoped>
1125
+ .editify-toolbar {
1126
+ display: flex;
1127
+ justify-content: flex-start;
1128
+ align-items: center;
1129
+ padding: 6px 10px;
1130
+
1131
+ .editify-icon-rotate {
1132
+ transform: rotate(180deg);
1133
+ }
1134
+ }
1135
+
1136
+ .editify-toolbar-link {
1137
+ display: block;
1138
+ width: 280px;
1139
+ padding: 4px;
1140
+
1141
+ .editify-toolbar-link-label {
1142
+ display: block;
1143
+ text-align: left;
1144
+ margin-bottom: 10px;
1145
+ font-size: @font-size;
1146
+ color: @font-color;
1147
+ }
1148
+
1149
+ input {
1150
+ appearance: none;
1151
+ -webkit-appearance: none;
1152
+ -moz-appearance: none;
1153
+ display: block;
1154
+ width: 100%;
1155
+ margin: 0 0 10px 0;
1156
+ padding: 4px 2px;
1157
+ border: none;
1158
+ font-size: @font-size;
1159
+ color: @font-color;
1160
+ border-bottom: 1px solid @border-color;
1161
+ line-height: 1.5;
1162
+ transition: all 500ms;
1163
+ background-color: transparent;
1164
+ outline: none;
1165
+
1166
+ &::-webkit-input-placeholder,
1167
+ &::placeholder {
1168
+ color: @font-color-disabled;
1169
+ font-family: inherit;
1170
+ font-size: inherit;
1171
+ vertical-align: middle;
1172
+ }
1173
+
1174
+ &[disabled] {
1175
+ background-color: transparent;
1176
+ opacity: 0.6;
1177
+ }
1178
+ }
1179
+
1180
+ .editify-toolbar-link-footer {
1181
+ display: flex;
1182
+ justify-content: space-between;
1183
+ align-items: center;
1184
+ width: 100%;
1185
+ font-size: @font-size;
1186
+ color: @font-color-light;
1187
+
1188
+ .editify-toolbar-link-operations {
1189
+ display: flex;
1190
+ justify-content: flex-start;
1191
+ align-items: center;
1192
+
1193
+ & > span,
1194
+ & > a {
1195
+ cursor: pointer;
1196
+ opacity: 0.8;
1197
+ transition: all 200ms;
1198
+
1199
+ &:hover {
1200
+ opacity: 1;
1201
+ }
1202
+ }
1203
+
1204
+ & > span {
1205
+ margin-right: 15px;
1206
+ }
1207
+
1208
+ & > a {
1209
+ text-decoration: none;
1210
+ }
1211
+ }
1212
+ }
1213
+ }
1214
+ </style>