mooho-base-admin-plus 2.10.90 → 2.10.92
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/history.md +3 -1
- package/package/ckeditor.js +74278 -0
- package/package/mooho-base-admin-plus.min.esm.js +14349 -13073
- package/package/mooho-base-admin-plus.min.js +566 -160
- package/package/style.css +10 -7
- package/package.json +3 -2
- package/src/ckeditor/mooho-classic-editor.js +187 -0
- package/src/components/richEditor/index.vue +41 -149
- package/src/components/view/view-table.vue +10 -6
- package/src/libs/ckeditor5-upload-adapter.js +38 -0
- package/src/setting.js +1 -3
- package/token.txt +2 -2
- package/vite.config.js +87 -19
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mooho-base-admin-plus",
|
|
3
3
|
"description": "MOOHO basic framework for admin by Vue3",
|
|
4
|
-
"version": "2.10.
|
|
4
|
+
"version": "2.10.92",
|
|
5
5
|
"author": "jinyifan <jinyifan@mooho.com.cn>",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"private": false,
|
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
"package": "vite build --mode lib"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
+
"@ckeditor/ckeditor5-vue": "^7.4.0",
|
|
16
17
|
"@fortawesome/fontawesome-free": "^5.13.0",
|
|
17
18
|
"@handsontable/vue3": "^16.1.1",
|
|
18
19
|
"axios": "^1.6.7",
|
|
19
|
-
"
|
|
20
|
+
"ckeditor5": "^47.6.1",
|
|
20
21
|
"date-fns": "^2.9.0",
|
|
21
22
|
"echarts": "^5.3.2",
|
|
22
23
|
"file-saver": "^2.0.2",
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 自定义 Classic 编辑器:在 GPL 下按需组合开源插件(替代 @ckeditor/ckeditor5-build-classic)
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
Alignment,
|
|
6
|
+
Autoformat,
|
|
7
|
+
BlockQuote,
|
|
8
|
+
Bold,
|
|
9
|
+
ClassicEditor,
|
|
10
|
+
Code,
|
|
11
|
+
Essentials,
|
|
12
|
+
FindAndReplace,
|
|
13
|
+
Font,
|
|
14
|
+
Heading,
|
|
15
|
+
HorizontalLine,
|
|
16
|
+
Image,
|
|
17
|
+
ImageCaption,
|
|
18
|
+
ImageStyle,
|
|
19
|
+
ImageToolbar,
|
|
20
|
+
ImageUpload,
|
|
21
|
+
Indent,
|
|
22
|
+
IndentBlock,
|
|
23
|
+
Italic,
|
|
24
|
+
Link,
|
|
25
|
+
List,
|
|
26
|
+
MediaEmbed,
|
|
27
|
+
PageBreak,
|
|
28
|
+
Paragraph,
|
|
29
|
+
PasteFromOffice,
|
|
30
|
+
PictureEditing,
|
|
31
|
+
RemoveFormat,
|
|
32
|
+
SelectAll,
|
|
33
|
+
ShowBlocks,
|
|
34
|
+
SourceEditing,
|
|
35
|
+
SpecialCharacters,
|
|
36
|
+
Strikethrough,
|
|
37
|
+
Subscript,
|
|
38
|
+
Superscript,
|
|
39
|
+
Table,
|
|
40
|
+
TableCaption,
|
|
41
|
+
TableCellProperties,
|
|
42
|
+
TableColumnResize,
|
|
43
|
+
TableProperties,
|
|
44
|
+
TableToolbar,
|
|
45
|
+
TextTransformation,
|
|
46
|
+
TodoList,
|
|
47
|
+
Underline
|
|
48
|
+
} from 'ckeditor5';
|
|
49
|
+
import 'ckeditor5/ckeditor5.css';
|
|
50
|
+
import zhCnTranslations from 'ckeditor5/translations/zh-cn.js';
|
|
51
|
+
|
|
52
|
+
export class MoohoClassicEditor extends ClassicEditor {
|
|
53
|
+
static builtinPlugins = [
|
|
54
|
+
Essentials,
|
|
55
|
+
Autoformat,
|
|
56
|
+
TextTransformation,
|
|
57
|
+
Bold,
|
|
58
|
+
Italic,
|
|
59
|
+
Underline,
|
|
60
|
+
Strikethrough,
|
|
61
|
+
Subscript,
|
|
62
|
+
Superscript,
|
|
63
|
+
Code,
|
|
64
|
+
RemoveFormat,
|
|
65
|
+
Paragraph,
|
|
66
|
+
Heading,
|
|
67
|
+
Link,
|
|
68
|
+
List,
|
|
69
|
+
TodoList,
|
|
70
|
+
BlockQuote,
|
|
71
|
+
Indent,
|
|
72
|
+
IndentBlock,
|
|
73
|
+
Alignment,
|
|
74
|
+
Font,
|
|
75
|
+
Image,
|
|
76
|
+
ImageCaption,
|
|
77
|
+
ImageStyle,
|
|
78
|
+
ImageToolbar,
|
|
79
|
+
ImageUpload,
|
|
80
|
+
PictureEditing,
|
|
81
|
+
Table,
|
|
82
|
+
TableToolbar,
|
|
83
|
+
TableProperties,
|
|
84
|
+
TableCellProperties,
|
|
85
|
+
TableCaption,
|
|
86
|
+
TableColumnResize,
|
|
87
|
+
MediaEmbed,
|
|
88
|
+
PasteFromOffice,
|
|
89
|
+
HorizontalLine,
|
|
90
|
+
PageBreak,
|
|
91
|
+
SpecialCharacters,
|
|
92
|
+
SourceEditing,
|
|
93
|
+
SelectAll,
|
|
94
|
+
FindAndReplace,
|
|
95
|
+
ShowBlocks
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
static defaultConfig = {
|
|
99
|
+
licenseKey: 'GPL',
|
|
100
|
+
/** 必须传入翻译对象;仅 side-effect import 不会注册语言包,界面会回退英文 */
|
|
101
|
+
translations: [zhCnTranslations],
|
|
102
|
+
language: 'zh-cn',
|
|
103
|
+
menuBar: {
|
|
104
|
+
isVisible: true
|
|
105
|
+
},
|
|
106
|
+
toolbar: {
|
|
107
|
+
shouldNotGroupWhenFull: true,
|
|
108
|
+
items: [
|
|
109
|
+
'undo',
|
|
110
|
+
'redo',
|
|
111
|
+
'|',
|
|
112
|
+
'findAndReplace',
|
|
113
|
+
'selectAll',
|
|
114
|
+
'|',
|
|
115
|
+
'heading',
|
|
116
|
+
'|',
|
|
117
|
+
'fontSize',
|
|
118
|
+
'fontFamily',
|
|
119
|
+
'fontColor',
|
|
120
|
+
'fontBackgroundColor',
|
|
121
|
+
'|',
|
|
122
|
+
'bold',
|
|
123
|
+
'italic',
|
|
124
|
+
'underline',
|
|
125
|
+
'strikethrough',
|
|
126
|
+
'code',
|
|
127
|
+
'subscript',
|
|
128
|
+
'superscript',
|
|
129
|
+
'removeFormat',
|
|
130
|
+
'|',
|
|
131
|
+
'alignment',
|
|
132
|
+
'|',
|
|
133
|
+
'link',
|
|
134
|
+
'|',
|
|
135
|
+
'bulletedList',
|
|
136
|
+
'numberedList',
|
|
137
|
+
'todoList',
|
|
138
|
+
'|',
|
|
139
|
+
'outdent',
|
|
140
|
+
'indent',
|
|
141
|
+
'|',
|
|
142
|
+
'blockQuote',
|
|
143
|
+
'horizontalLine',
|
|
144
|
+
'pageBreak',
|
|
145
|
+
'|',
|
|
146
|
+
'imageUpload',
|
|
147
|
+
'insertTable',
|
|
148
|
+
'mediaEmbed',
|
|
149
|
+
'specialCharacters',
|
|
150
|
+
'|',
|
|
151
|
+
'sourceEditing',
|
|
152
|
+
'showBlocks'
|
|
153
|
+
]
|
|
154
|
+
},
|
|
155
|
+
image: {
|
|
156
|
+
toolbar: [
|
|
157
|
+
'imageTextAlternative',
|
|
158
|
+
'toggleImageCaption',
|
|
159
|
+
'|',
|
|
160
|
+
'imageStyle:inline',
|
|
161
|
+
'imageStyle:block',
|
|
162
|
+
'imageStyle:side',
|
|
163
|
+
'|',
|
|
164
|
+
'linkImage'
|
|
165
|
+
]
|
|
166
|
+
},
|
|
167
|
+
table: {
|
|
168
|
+
contentToolbar: [
|
|
169
|
+
'tableColumn',
|
|
170
|
+
'tableRow',
|
|
171
|
+
'mergeTableCells',
|
|
172
|
+
'tableProperties',
|
|
173
|
+
'tableCellProperties',
|
|
174
|
+
'toggleTableCaption'
|
|
175
|
+
]
|
|
176
|
+
},
|
|
177
|
+
heading: {
|
|
178
|
+
options: [
|
|
179
|
+
{ model: 'paragraph', title: '正文', class: 'ck-heading_paragraph' },
|
|
180
|
+
{ model: 'heading1', view: 'h1', title: '标题 1', class: 'ck-heading_heading1' },
|
|
181
|
+
{ model: 'heading2', view: 'h2', title: '标题 2', class: 'ck-heading_heading2' },
|
|
182
|
+
{ model: 'heading3', view: 'h3', title: '标题 3', class: 'ck-heading_heading3' },
|
|
183
|
+
{ model: 'heading4', view: 'h4', title: '标题 4', class: 'ck-heading_heading4' }
|
|
184
|
+
]
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
}
|
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div class="mooho-rich-editor" :style="wrapStyle">
|
|
3
|
+
<ckeditor
|
|
4
|
+
:editor="editorRef"
|
|
5
|
+
:model-value="editorHtml"
|
|
6
|
+
:disabled="readonly"
|
|
7
|
+
:config="editorConfig"
|
|
8
|
+
@update:model-value="onEditorUpdate"
|
|
9
|
+
/>
|
|
10
|
+
</div>
|
|
3
11
|
</template>
|
|
4
12
|
|
|
5
13
|
<script>
|
|
6
|
-
|
|
7
|
-
|
|
14
|
+
import { markRaw } from 'vue';
|
|
15
|
+
import { Ckeditor } from '@ckeditor/ckeditor5-vue';
|
|
16
|
+
import { MoohoClassicEditor } from '../../ckeditor/mooho-classic-editor.js';
|
|
8
17
|
import mixinPage from '../../mixins/page';
|
|
9
18
|
import util from '../../libs/util';
|
|
10
|
-
import {
|
|
11
|
-
import Setting from '../../setting';
|
|
19
|
+
import { createLegacyCkEditorUploadPlugin } from '../../libs/ckeditor5-upload-adapter';
|
|
12
20
|
|
|
13
21
|
export default {
|
|
22
|
+
name: 'RichEditor',
|
|
23
|
+
components: { Ckeditor },
|
|
14
24
|
mixins: [mixinPage],
|
|
15
25
|
props: {
|
|
16
26
|
modelValue: {
|
|
17
27
|
type: String,
|
|
18
28
|
default: ''
|
|
19
29
|
},
|
|
20
|
-
// 只读
|
|
21
30
|
readonly: {
|
|
22
31
|
type: Boolean,
|
|
23
32
|
default: false
|
|
@@ -27,163 +36,46 @@
|
|
|
27
36
|
},
|
|
28
37
|
height: {
|
|
29
38
|
type: Number
|
|
30
|
-
},
|
|
31
|
-
editorUrl: {
|
|
32
|
-
type: String,
|
|
33
|
-
default: Setting.editorUrl
|
|
34
39
|
}
|
|
35
40
|
},
|
|
36
41
|
data() {
|
|
37
42
|
return {
|
|
38
|
-
|
|
39
|
-
instance: null, // 当前实例
|
|
40
|
-
$_destroyed: false // 是否销毁
|
|
43
|
+
editorRef: markRaw(MoohoClassicEditor)
|
|
41
44
|
};
|
|
42
45
|
},
|
|
43
46
|
computed: {
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
/** 表单 parseData 可能为 null/undefined,CKEditor DataController.set 必须是字符串,否则会 Object.keys 报错 */
|
|
48
|
+
editorHtml() {
|
|
49
|
+
const v = this.modelValue;
|
|
50
|
+
if (v == null) return '';
|
|
51
|
+
return typeof v === 'string' ? v : String(v);
|
|
52
|
+
},
|
|
53
|
+
wrapStyle() {
|
|
54
|
+
const h = this.height == null ? 500 : this.height;
|
|
46
55
|
return {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Authorization: 'Bearer ' + token
|
|
50
|
-
},
|
|
51
|
-
// toolbargroups: [
|
|
52
|
-
// { name: 'clipboard', groups: ['clipboard', 'undo'] },
|
|
53
|
-
// { name: 'editing', groups: ['find', 'selection', 'spellchecker'] },
|
|
54
|
-
// { name: 'links' },
|
|
55
|
-
// { name: 'insert' },
|
|
56
|
-
// { name: 'forms' },
|
|
57
|
-
// { name: 'tools' },
|
|
58
|
-
// { name: 'document', groups: ['mode', 'document', 'doctools'] },
|
|
59
|
-
// { name: 'others' },
|
|
60
|
-
// '/',
|
|
61
|
-
// { name: 'basicstyles', groups: ['basicstyles', 'cleanup'] },
|
|
62
|
-
// { name: 'paragraph', groups: ['list', 'indent', 'blocks', 'align'] },
|
|
63
|
-
// { name: 'styles' },
|
|
64
|
-
// { name: 'colors' },
|
|
65
|
-
// { name: 'about' }
|
|
66
|
-
// ],
|
|
67
|
-
filebrowserUploadUrl: this.apiBaseURL + 'api/CKEditor?r=1',
|
|
68
|
-
removePlugins: 'easyimage,cloudservices,exportpdf',
|
|
69
|
-
clipboard_handleImages: false
|
|
56
|
+
width: this.width == null ? undefined : `${this.width}px`,
|
|
57
|
+
'--mooho-re-min-height': `${h}px`
|
|
70
58
|
};
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
mounted() {
|
|
74
|
-
getEditorNamespace(this.editorUrl, namespace => {
|
|
75
|
-
this.$emit('namespaceloaded', namespace);
|
|
76
|
-
}).then(() => {
|
|
77
|
-
if (this.$_destroyed) {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const config = this.prepareConfig();
|
|
82
|
-
|
|
83
|
-
CKEDITOR.replace('editor_' + this.uid, config);
|
|
84
|
-
});
|
|
85
|
-
},
|
|
86
|
-
beforeUnmount() {
|
|
87
|
-
if (this.instance) {
|
|
88
|
-
this.instance.destroy();
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
this.$_destroyed = true;
|
|
92
|
-
},
|
|
93
|
-
watch: {
|
|
94
|
-
modelValue(val) {
|
|
95
|
-
if (this.instance && this.instance.getData() !== val) {
|
|
96
|
-
this.instance.setData(val);
|
|
97
|
-
}
|
|
98
59
|
},
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
60
|
+
editorConfig() {
|
|
61
|
+
const uploadUrl = this.apiBaseURL + 'api/CKEditor?r=1';
|
|
62
|
+
return {
|
|
63
|
+
extraPlugins: [
|
|
64
|
+
createLegacyCkEditorUploadPlugin(uploadUrl, () => util.cookies.get('token') || '')
|
|
65
|
+
]
|
|
66
|
+
};
|
|
104
67
|
}
|
|
105
68
|
},
|
|
106
69
|
methods: {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
config.on = config.on || {};
|
|
110
|
-
|
|
111
|
-
if (config.delayIfDetached === undefined) {
|
|
112
|
-
config.delayIfDetached = true;
|
|
113
|
-
}
|
|
114
|
-
if (this.readonly !== null) {
|
|
115
|
-
config.readOnly = this.readonly;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const userInstanceReadyCallback = config.on.instanceReady;
|
|
119
|
-
|
|
120
|
-
config.on.instanceReady = evt => {
|
|
121
|
-
this.instance = evt.editor;
|
|
122
|
-
|
|
123
|
-
this.$nextTick().then(() => {
|
|
124
|
-
this.prepareComponentData();
|
|
125
|
-
|
|
126
|
-
if (userInstanceReadyCallback) {
|
|
127
|
-
userInstanceReadyCallback(evt);
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
return config;
|
|
133
|
-
},
|
|
134
|
-
prepareComponentData() {
|
|
135
|
-
const data = this.modelValue;
|
|
136
|
-
|
|
137
|
-
this.instance.fire('lockSnapshot');
|
|
138
|
-
|
|
139
|
-
this.instance.setData(data, {
|
|
140
|
-
callback: () => {
|
|
141
|
-
this.$_setUpEditorEvents();
|
|
142
|
-
|
|
143
|
-
const newData = this.instance.getData();
|
|
144
|
-
|
|
145
|
-
// Locking the snapshot prevents the 'change' event.
|
|
146
|
-
// Trigger it manually to update the bound data.
|
|
147
|
-
if (data !== newData) {
|
|
148
|
-
// this.$once('input', () => {
|
|
149
|
-
// this.$emit('ready', this.instance);
|
|
150
|
-
// });
|
|
151
|
-
|
|
152
|
-
this.$emit('update:modelValue', newData);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
this.instance.fire('unlockSnapshot');
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
},
|
|
159
|
-
$_setUpEditorEvents() {
|
|
160
|
-
const editor = this.instance;
|
|
161
|
-
|
|
162
|
-
editor.on(
|
|
163
|
-
'change',
|
|
164
|
-
debounce(evt => {
|
|
165
|
-
const data = editor.getData();
|
|
166
|
-
|
|
167
|
-
// Editor#change event might be fired without an actual data change.
|
|
168
|
-
if (this.modelValue !== data) {
|
|
169
|
-
// The compatibility with the v-model and general Vue.js concept of input–like components.
|
|
170
|
-
this.$emit('update:modelValue', data, evt, editor);
|
|
171
|
-
}
|
|
172
|
-
}, 80)
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
editor.on('fileUploadResponse', evt => {
|
|
176
|
-
setTimeout(() => {
|
|
177
|
-
const data = editor.getData();
|
|
178
|
-
|
|
179
|
-
// Editor#change event might be fired without an actual data change.
|
|
180
|
-
if (this.modelValue !== data) {
|
|
181
|
-
// The compatibility with the v-model and general Vue.js concept of input–like components.
|
|
182
|
-
this.$emit('update:modelValue', data, evt, editor);
|
|
183
|
-
}
|
|
184
|
-
});
|
|
185
|
-
});
|
|
70
|
+
onEditorUpdate(val) {
|
|
71
|
+
this.$emit('update:modelValue', val == null ? '' : val);
|
|
186
72
|
}
|
|
187
73
|
}
|
|
188
74
|
};
|
|
189
75
|
</script>
|
|
76
|
+
|
|
77
|
+
<style scoped>
|
|
78
|
+
.mooho-rich-editor :deep(.ck-editor__editable) {
|
|
79
|
+
min-height: var(--mooho-re-min-height, 500px);
|
|
80
|
+
}
|
|
81
|
+
</style>
|
|
@@ -2821,9 +2821,11 @@
|
|
|
2821
2821
|
// 上移
|
|
2822
2822
|
up(row, index) {
|
|
2823
2823
|
let data = this.staticData;
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2824
|
+
// 计算全局索引(考虑分页)
|
|
2825
|
+
let globalIndex = (this.current - 1) * this.size + index;
|
|
2826
|
+
if (globalIndex > 0 && globalIndex < data.length) {
|
|
2827
|
+
data.splice(globalIndex, 1);
|
|
2828
|
+
data.splice(globalIndex - 1, 0, row);
|
|
2827
2829
|
|
|
2828
2830
|
// for (let item of data) {
|
|
2829
2831
|
// delete item.id;
|
|
@@ -2835,9 +2837,11 @@
|
|
|
2835
2837
|
// 下移
|
|
2836
2838
|
down(row, index) {
|
|
2837
2839
|
let data = this.staticData;
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2840
|
+
// 计算全局索引(考虑分页)
|
|
2841
|
+
let globalIndex = (this.current - 1) * this.size + index;
|
|
2842
|
+
if (globalIndex < data.length - 1 && globalIndex >= 0) {
|
|
2843
|
+
data.splice(globalIndex, 1);
|
|
2844
|
+
data.splice(globalIndex + 1, 0, row);
|
|
2841
2845
|
|
|
2842
2846
|
// for (let item of data) {
|
|
2843
2847
|
// delete item.id;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 对接现有 api/CKEditor 上传接口(multipart + { uploaded, url } / { uploaded:0, error })
|
|
3
|
+
*/
|
|
4
|
+
export function createLegacyCkEditorUploadPlugin(uploadUrl, getToken) {
|
|
5
|
+
return function LegacyCkEditorUploadPlugin(editor) {
|
|
6
|
+
editor.plugins.get('FileRepository').createUploadAdapter = loader => ({
|
|
7
|
+
upload() {
|
|
8
|
+
return loader.file.then(file => {
|
|
9
|
+
const data = new FormData();
|
|
10
|
+
data.append('upload', file);
|
|
11
|
+
// 勿用 credentials:'include':与 API 不同源时,服务端若返回 ACAO:* 会违反 CORS(带凭证不允许 *)。
|
|
12
|
+
// 鉴权已走 Authorization Bearer,一般不必再发跨域 Cookie。
|
|
13
|
+
return fetch(uploadUrl, {
|
|
14
|
+
method: 'POST',
|
|
15
|
+
body: data,
|
|
16
|
+
headers: {
|
|
17
|
+
Authorization: 'Bearer ' + (getToken ? getToken() : '')
|
|
18
|
+
}
|
|
19
|
+
}).then(response => {
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
return response.text().then(text => {
|
|
22
|
+
throw new Error(text || response.statusText);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return response.json();
|
|
26
|
+
}).then(body => {
|
|
27
|
+
if (body.uploaded === 1 && body.url) {
|
|
28
|
+
return { default: body.url };
|
|
29
|
+
}
|
|
30
|
+
const msg = (body.error && body.error.message) || 'Upload failed';
|
|
31
|
+
throw new Error(msg);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
abort() {}
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
}
|
package/src/setting.js
CHANGED
|
@@ -203,9 +203,7 @@ const Setting = {
|
|
|
203
203
|
* 功能配置
|
|
204
204
|
* */
|
|
205
205
|
// 相同路由,不同参数间进行切换,是否强力更新
|
|
206
|
-
sameRouteForceUpdate: false
|
|
207
|
-
// 富文本编辑器
|
|
208
|
-
editorUrl: 'https://cdn-source.ckeditor.com/4.21.0/full-all/ckeditor.js'
|
|
206
|
+
sameRouteForceUpdate: false
|
|
209
207
|
};
|
|
210
208
|
|
|
211
209
|
// const copyTo = (source, target) => {
|
package/token.txt
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
echo "//registry.npmjs.org/:_authToken=
|
|
2
|
-
npm config set //registry.npmjs.org/:_authToken=
|
|
1
|
+
echo "//registry.npmjs.org/:_authToken=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" >> .npmrc
|
|
2
|
+
npm config set //registry.npmjs.org/:_authToken=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
|
package/vite.config.js
CHANGED
|
@@ -1,9 +1,71 @@
|
|
|
1
1
|
import { defineConfig } from 'vite';
|
|
2
2
|
import vue from '@vitejs/plugin-vue';
|
|
3
|
-
import {
|
|
3
|
+
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
4
|
+
import { resolve } from 'node:path';
|
|
4
5
|
import Setting from './test/setting.env';
|
|
5
6
|
import compression from 'vite-plugin-compression';
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* npm 会把「核心包」装在 ckeditor5 的嵌套 node_modules,而 ckeditor5-emoji 等顶层插件各自再带一份
|
|
10
|
+
* core/utils/ui…,运行时就加载了两份 → ckeditor-duplicated-modules。
|
|
11
|
+
* 凡在 ckeditor5/node_modules/@ckeditor 下存在的包,全部别名到该目录,保证全应用单实例。
|
|
12
|
+
*/
|
|
13
|
+
function ckeditorSingleInstanceAliases() {
|
|
14
|
+
const nestedRoot = resolve(__dirname, 'node_modules/ckeditor5/node_modules/@ckeditor');
|
|
15
|
+
const aliases = {};
|
|
16
|
+
if (!existsSync(nestedRoot)) return aliases;
|
|
17
|
+
for (const name of readdirSync(nestedRoot)) {
|
|
18
|
+
const dir = resolve(nestedRoot, name);
|
|
19
|
+
if (statSync(dir).isDirectory()) {
|
|
20
|
+
aliases[`@ckeditor/${name}`] = dir;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return aliases;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** CKEditor 5:避免 @ckeditor/ckeditor5-utils 等被拆进多个 chunk 触发 ckeditor-duplicated-modules */
|
|
27
|
+
function isCKEditorModule(id) {
|
|
28
|
+
const n = id.replace(/\\/g, '/');
|
|
29
|
+
return n.includes('/@ckeditor/') || n.includes('/ckeditor5/');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function ckeditorManualChunk(id) {
|
|
33
|
+
if (isCKEditorModule(id)) {
|
|
34
|
+
return 'ckeditor';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const ckeditorResolve = {
|
|
39
|
+
alias: {
|
|
40
|
+
'@': resolve(__dirname, '.', 'src'),
|
|
41
|
+
...ckeditorSingleInstanceAliases()
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* `optimizeDeps.exclude` 掉 ckeditor5 / Vue 集成包后,CKEditor 链路上的 CJS/UMD 裸依赖不会自动预构建,
|
|
47
|
+
* 浏览器按 ESM 直出会报「无 default」;下列包仍需 include 做 esbuild 互操作。
|
|
48
|
+
*/
|
|
49
|
+
/** 勿包含 @ckeditor/*:预构建会打进第二份 utils/core,与上面 alias 单实例冲突 */
|
|
50
|
+
const ckeditorLinkedDepInterop = [
|
|
51
|
+
'@ungap/structured-clone',
|
|
52
|
+
'color-convert',
|
|
53
|
+
'color-name',
|
|
54
|
+
'color-parse',
|
|
55
|
+
'es-toolkit/compat/isEqual',
|
|
56
|
+
'extend',
|
|
57
|
+
'fuzzysort',
|
|
58
|
+
'rehype-dom-parse',
|
|
59
|
+
'rehype-dom-stringify',
|
|
60
|
+
'rehype-remark',
|
|
61
|
+
'remark-breaks',
|
|
62
|
+
'remark-gfm',
|
|
63
|
+
'remark-parse',
|
|
64
|
+
'remark-rehype',
|
|
65
|
+
'remark-stringify',
|
|
66
|
+
'unified'
|
|
67
|
+
];
|
|
68
|
+
|
|
7
69
|
const build = defineConfig({
|
|
8
70
|
define: {
|
|
9
71
|
__VUE_OPTIONS_API__: true,
|
|
@@ -19,18 +81,29 @@ const build = defineConfig({
|
|
|
19
81
|
})
|
|
20
82
|
],
|
|
21
83
|
base: Setting.publicPath,
|
|
84
|
+
// 勿对 ckeditor5 做预打包,否则易与源码路径下的 @ckeditor 子依赖形成双份 utils(ckeditor-duplicated-modules)
|
|
85
|
+
optimizeDeps: {
|
|
86
|
+
exclude: [
|
|
87
|
+
'ckeditor5',
|
|
88
|
+
'@ckeditor/ckeditor5-vue',
|
|
89
|
+
'@ckeditor/ckeditor5-integrations-common'
|
|
90
|
+
],
|
|
91
|
+
include: ckeditorLinkedDepInterop
|
|
92
|
+
},
|
|
22
93
|
build: {
|
|
23
94
|
sourcemap: false, // 输出.map文件
|
|
24
95
|
outDir: Setting.outputDir,
|
|
25
|
-
assetsDir: Setting.assetsDir
|
|
96
|
+
assetsDir: Setting.assetsDir,
|
|
97
|
+
rollupOptions: {
|
|
98
|
+
output: {
|
|
99
|
+
manualChunks(id) {
|
|
100
|
+
return ckeditorManualChunk(id);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
26
104
|
// minify: 'terser', // 混淆器,terser构建后文件体积更小
|
|
27
105
|
},
|
|
28
|
-
resolve:
|
|
29
|
-
alias: {
|
|
30
|
-
'@': resolve(__dirname, '.', 'src')
|
|
31
|
-
}
|
|
32
|
-
// extensions: ['.js', '.json', '.vue']
|
|
33
|
-
}
|
|
106
|
+
resolve: ckeditorResolve
|
|
34
107
|
});
|
|
35
108
|
|
|
36
109
|
const lib = defineConfig({
|
|
@@ -59,9 +132,8 @@ const lib = defineConfig({
|
|
|
59
132
|
entryFileNames: 'mooho-base-admin-plus.min.js',
|
|
60
133
|
chunkFileNames: '[name].js',
|
|
61
134
|
assetFileNames: '[name].[ext]',
|
|
62
|
-
|
|
63
|
-
inlineDynamicImports:
|
|
64
|
-
manualChunks: undefined,
|
|
135
|
+
// UMD / IIFE 不支持多 chunk,不能与 manualChunks 同时使用
|
|
136
|
+
inlineDynamicImports: true,
|
|
65
137
|
globals: { vue: 'Vue', 'view-ui-plus': 'viewUiPlus' }
|
|
66
138
|
},
|
|
67
139
|
{
|
|
@@ -72,20 +144,16 @@ const lib = defineConfig({
|
|
|
72
144
|
entryFileNames: 'mooho-base-admin-plus.min.esm.js',
|
|
73
145
|
chunkFileNames: '[name].js',
|
|
74
146
|
assetFileNames: '[name].[ext]',
|
|
75
|
-
namespaceToStringTag: true,
|
|
76
147
|
inlineDynamicImports: false,
|
|
77
|
-
manualChunks
|
|
148
|
+
manualChunks(id) {
|
|
149
|
+
return ckeditorManualChunk(id);
|
|
150
|
+
},
|
|
78
151
|
globals: { vue: 'Vue', 'view-ui-plus': 'viewUiPlus' }
|
|
79
152
|
}
|
|
80
153
|
]
|
|
81
154
|
}
|
|
82
155
|
},
|
|
83
|
-
resolve:
|
|
84
|
-
alias: {
|
|
85
|
-
'@': resolve(__dirname, '.', 'src')
|
|
86
|
-
}
|
|
87
|
-
// extensions: ['.js', '.json', '.vue']
|
|
88
|
-
}
|
|
156
|
+
resolve: ckeditorResolve
|
|
89
157
|
});
|
|
90
158
|
|
|
91
159
|
export default ({ mode }) => {
|