Skip to content

Commit f385079

Browse files
committed
新增:支持文档一键导入,支持Word文档(docx)、Markdown文档(md)文档
1 parent dadba87 commit f385079

16 files changed

Lines changed: 269 additions & 43 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
99
## 功能亮点
1010

11+
- 支持文档一键导入,支持Word文档(docx)、Markdown文档(md)文档
1112
- 全新的UI外观,使用字体图标替换原有图片图标
1213
- 移除过时、无用的插件支持,不断完善使用体验
1314
- 图片、文件、视频上传配置化定制增强

_src/adapter/editorui.js

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,28 +28,6 @@
2828
return dialog;
2929
};
3030

31-
var iframeUrlMap = {
32-
anchor: "~/dialogs/anchor/anchor.html?{timestamp}",
33-
insertimage: "~/dialogs/image/image.html?{timestamp}",
34-
link: "~/dialogs/link/link.html?{timestamp}",
35-
spechars: "~/dialogs/spechars/spechars.html?{timestamp}",
36-
searchreplace: "~/dialogs/searchreplace/searchreplace.html?{timestamp}",
37-
insertvideo: "~/dialogs/video/video.html?{timestamp}",
38-
insertaudio: "~/dialogs/audio/audio.html?{timestamp}",
39-
help: "~/dialogs/help/help.html?{timestamp}",
40-
preview: "~/dialogs/preview/preview.html?{timestamp}",
41-
emotion: "~/dialogs/emotion/emotion.html?{timestamp}",
42-
wordimage: "~/dialogs/wordimage/wordimage.html?{timestamp}",
43-
formula: "~/dialogs/formula/formula.html?{timestamp}",
44-
attachment: "~/dialogs/attachment/attachment.html?{timestamp}",
45-
insertframe: "~/dialogs/insertframe/insertframe.html?{timestamp}",
46-
edittip: "~/dialogs/table/edittip.html?{timestamp}",
47-
edittable: "~/dialogs/table/edittable.html?{timestamp}",
48-
edittd: "~/dialogs/table/edittd.html?{timestamp}",
49-
scrawl: "~/dialogs/scrawl/scrawl.html?{timestamp}",
50-
template: "~/dialogs/template/template.html?{timestamp}",
51-
background: "~/dialogs/background/background.html?{timestamp}",
52-
};
5331
//为工具栏添加按钮,以下都是统一的按钮触发命令,所以写在一起
5432
var btnCmds = [
5533
"undo",
@@ -215,7 +193,6 @@
215193
justify: ["left", "right", "center", "justify"],
216194
directionality: ["ltr", "rtl"]
217195
};
218-
219196
for (var p in typeset) {
220197
(function (cmd, val) {
221198
for (var i = 0, ci; (ci = val[i++]);) {
@@ -290,6 +267,29 @@
290267
})(ci);
291268
}
292269

270+
var dialogIframeUrlMap = {
271+
anchor: "~/dialogs/anchor/anchor.html?{timestamp}",
272+
insertimage: "~/dialogs/image/image.html?{timestamp}",
273+
link: "~/dialogs/link/link.html?{timestamp}",
274+
spechars: "~/dialogs/spechars/spechars.html?{timestamp}",
275+
searchreplace: "~/dialogs/searchreplace/searchreplace.html?{timestamp}",
276+
insertvideo: "~/dialogs/video/video.html?{timestamp}",
277+
insertaudio: "~/dialogs/audio/audio.html?{timestamp}",
278+
help: "~/dialogs/help/help.html?{timestamp}",
279+
preview: "~/dialogs/preview/preview.html?{timestamp}",
280+
emotion: "~/dialogs/emotion/emotion.html?{timestamp}",
281+
wordimage: "~/dialogs/wordimage/wordimage.html?{timestamp}",
282+
formula: "~/dialogs/formula/formula.html?{timestamp}",
283+
attachment: "~/dialogs/attachment/attachment.html?{timestamp}",
284+
insertframe: "~/dialogs/insertframe/insertframe.html?{timestamp}",
285+
edittip: "~/dialogs/table/edittip.html?{timestamp}",
286+
edittable: "~/dialogs/table/edittable.html?{timestamp}",
287+
edittd: "~/dialogs/table/edittd.html?{timestamp}",
288+
scrawl: "~/dialogs/scrawl/scrawl.html?{timestamp}",
289+
template: "~/dialogs/template/template.html?{timestamp}",
290+
background: "~/dialogs/background/background.html?{timestamp}",
291+
contentimport: "~/dialogs/contentimport/contentimport.html?{timestamp}",
292+
};
293293
var dialogBtns = {
294294
noOk: ["searchreplace", "help", "spechars", "preview"],
295295
ok: [
@@ -308,9 +308,9 @@
308308
"template",
309309
"formula",
310310
"background",
311+
"contentimport",
311312
]
312313
};
313-
314314
for (var p in dialogBtns) {
315315
(function (type, vals) {
316316
for (var i = 0, ci; (ci = vals[i++]);) {
@@ -322,8 +322,8 @@
322322
editorui[cmd] = function (editor, iframeUrl, title) {
323323
iframeUrl =
324324
iframeUrl ||
325-
(editor.options.iframeUrlMap || {})[cmd] ||
326-
iframeUrlMap[cmd];
325+
(editor.options.dialogIframeUrlMap || {})[cmd] ||
326+
dialogIframeUrlMap[cmd];
327327
title =
328328
editor.options.labelMap[cmd] ||
329329
editor.getLang("labelMap." + cmd) ||
@@ -394,7 +394,6 @@
394394
dialog.render();
395395
dialog.open();
396396
}
397-
398397
break;
399398
default:
400399
dialog.render();
@@ -509,6 +508,7 @@
509508
});
510509
return ui;
511510
};
511+
512512
editorui.fontfamily = function (editor, list, title) {
513513
list = editor.options["fontfamily"] || [];
514514
title =
@@ -766,6 +766,7 @@
766766
});
767767
return ui;
768768
};
769+
769770
editorui.inserttable = function (editor, iframeUrl, title) {
770771
title =
771772
editor.options.labelMap["inserttable"] ||
@@ -881,6 +882,7 @@
881882
};
882883
})(ri);
883884
}
885+
884886
//有序,无序列表
885887
var lists = ["insertorderedlist", "insertunorderedlist"];
886888
for (var l = 0, cl; (cl = lists[l++]);) {
@@ -952,7 +954,7 @@
952954
};
953955

954956
// 表情
955-
editorui["emotion"] = function (editor, iframeUrl) {
957+
editorui['emotion'] = function (editor, iframeUrl) {
956958
var cmd = "emotion";
957959
var ui = new editorui.MultiMenuPop({
958960
title:
@@ -963,8 +965,8 @@
963965
className: "edui-for-" + cmd,
964966
iframeUrl: editor.ui.mapUrl(
965967
iframeUrl ||
966-
(editor.options.iframeUrlMap || {})[cmd] ||
967-
iframeUrlMap[cmd]
968+
(editor.options.dialogIframeUrlMap || {})[cmd] ||
969+
dialogIframeUrlMap[cmd]
968970
)
969971
});
970972
editorui.buttons[cmd] = ui;
@@ -975,7 +977,7 @@
975977
return ui;
976978
};
977979

978-
editorui.autotypeset = function (editor) {
980+
editorui['autotypeset'] = function (editor) {
979981
var ui = new editorui.AutoTypeSetButton({
980982
editor: editor,
981983
title:
@@ -995,7 +997,7 @@
995997
};
996998

997999
/* 简单上传插件 */
998-
editorui["simpleupload"] = function (editor) {
1000+
editorui['simpleupload'] = function (editor) {
9991001
var name = "simpleupload",
10001002
ui = new editorui.Button({
10011003
className: "edui-for-" + name,
@@ -1028,4 +1030,5 @@
10281030
});
10291031
return ui;
10301032
};
1033+
10311034
})();

_src/plugins/shortcutmenu.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ UE.plugins["shortcutmenu"] = function () {
2929
clientX: e.clientX,
3030
clientY: e.clientY
3131
};
32-
console.log('shortcutmenu.mouseup', e, e.target, me.selection.getRange());
32+
// console.log('shortcutmenu.mouseup', e, e.target, me.selection.getRange());
3333

3434
setTimeout(function () {
3535
// console.log(e, me.selection.getRange());
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<!DOCTYPE html>
2+
<head>
3+
<title></title>
4+
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
5+
<script type="text/javascript" src="../internal.js?{timestamp}"></script>
6+
<style type="text/css">
7+
.wrapper {
8+
width: 600px;
9+
padding: 10px;
10+
height: 352px;
11+
overflow: hidden;
12+
position: relative;
13+
border-bottom: 1px solid #d7d7d7;
14+
}
15+
16+
.wrapper .file-upload {
17+
display: flex;
18+
align-items: center;
19+
}
20+
21+
.wrapper .file-upload .file-tip {
22+
color: #999;
23+
font-size: 12px;
24+
padding-left: 10px;
25+
flex-grow: 1;
26+
}
27+
28+
.wrapper .file-manual {
29+
background: #EEE;
30+
padding: 10px;
31+
border-radius: 5px;
32+
margin-top: 10px;
33+
line-height: 2;
34+
}
35+
36+
.wrapper .file-manual .title {
37+
font-weight: bold;
38+
font-size: 120%;
39+
}
40+
41+
.wrapper .file-manual .body {
42+
}
43+
44+
.wrapper .file-manual .body li {
45+
list-style: disc;
46+
margin-left: 20px;
47+
}
48+
49+
.wrapper .upload-button {
50+
width: 100px;
51+
height: 30px;
52+
background-color: #F8F8F8;
53+
border: 1px solid #EEE;
54+
border-radius: 4px;
55+
text-align: center;
56+
line-height: 28px;
57+
cursor: pointer;
58+
position: relative;
59+
flex-shrink: 0;
60+
}
61+
62+
.wrapper .upload-button .text {
63+
display: inline-block;
64+
vertical-align: middle;
65+
}
66+
67+
.wrapper .upload-button input {
68+
position: absolute;
69+
left: 0;
70+
top: 0;
71+
opacity: 0;
72+
cursor: pointer;
73+
height: 100%;
74+
width: 100%;
75+
}
76+
77+
.wrapper .file-result {
78+
border: 1px solid #333;
79+
padding: 10px;
80+
border-radius: 5px;
81+
position: absolute;
82+
left: 10px;
83+
right: 10px;
84+
top: 50px;
85+
background: #FFF;
86+
bottom: 10px;
87+
overflow: auto;
88+
display: none;
89+
}
90+
</style>
91+
</head>
92+
<body>
93+
<div class="wrapper">
94+
<div class="file-upload">
95+
<div class="upload-button">
96+
<div class="text">选择本地文件</div>
97+
<input type="file" id="contentImport"/>
98+
</div>
99+
<div class="file-tip"></div>
100+
</div>
101+
<div class="file-manual">
102+
<div class="title">
103+
支持文档格式
104+
</div>
105+
<div class="body">
106+
<ul>
107+
<li><b>Word</b>:docx</li>
108+
<li><b>Markdown</b>:md</li>
109+
</ul>
110+
</div>
111+
</div>
112+
<div class="file-result"></div>
113+
</div>
114+
<script src="../../third-party/jquery-1.10.2.js?{timestamp}"></script>
115+
<script src="https://cdn.bootcdn.net/ajax/libs/mammoth/1.6.0/mammoth.browser.min.js"></script>
116+
<script src="https://cdn.bootcdn.net/ajax/libs/showdown/2.1.0/showdown.min.js"></script>
117+
<script type="text/javascript" src="contentimport.js?{timestamp}"></script>
118+
<script type="text/javascript">
119+
utils.domReady(function () {
120+
var options = {};
121+
var callbacks = {};
122+
contentImport.init(options, callbacks);
123+
});
124+
</script>
125+
</body>
126+
</html>
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
var contentImport = {};
2+
var g = $G;
3+
4+
contentImport.data = {
5+
result: null,
6+
};
7+
contentImport.init = function (opt, callbacks) {
8+
addUploadButtonListener();
9+
addOkListener();
10+
};
11+
12+
function processWord(file) {
13+
$('.file-tip').html('正在转换Word文件,请稍后...');
14+
$('.file-result').html('').hide();
15+
var reader = new FileReader();
16+
reader.onload = function (loadEvent) {
17+
mammoth.convertToHtml({
18+
arrayBuffer: loadEvent.target.result
19+
})
20+
.then(function displayResult(result) {
21+
$('.file-tip').html('转换成功');
22+
contentImport.data.result = result.value;
23+
$('.file-result').html(result.value).show();
24+
}, function (error) {
25+
$('.file-tip').html('Word文件转换失败:' + error);
26+
});
27+
};
28+
reader.onerror = function (loadEvent) {
29+
$('.file-tip').html('Word文件转换失败:' + loadEvent);
30+
};
31+
reader.readAsArrayBuffer(file);
32+
}
33+
34+
function processMarkdown(file) {
35+
$('.file-tip').html('正在转换Markdown文件,请稍后...');
36+
$('.file-result').html('').hide();
37+
var reader = new FileReader();
38+
reader.onload = function (loadEvent) {
39+
var converter = new showdown.Converter();
40+
var html = converter.makeHtml(loadEvent.target.result);
41+
$('.file-tip').html('转换成功');
42+
contentImport.data.result = html;
43+
$('.file-result').html(html).show();
44+
};
45+
reader.onerror = function (loadEvent) {
46+
$('.file-tip').html('Markdown文件转换失败:' + loadEvent);
47+
};
48+
reader.readAsText(file, "UTF-8");
49+
}
50+
51+
function addUploadButtonListener() {
52+
g('contentImport').addEventListener('change', function () {
53+
const file = this.files[0];
54+
const fileName = file.name;
55+
const fileExt = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
56+
switch (fileExt) {
57+
case 'docx':
58+
case 'doc':
59+
processWord(file);
60+
break;
61+
case 'md':
62+
processMarkdown(file);
63+
break;
64+
default:
65+
$('.file-tip').html('不支持的文件格式:' + fileExt);
66+
break;
67+
}
68+
});
69+
}
70+
71+
function addOkListener() {
72+
dialog.onok = function () {
73+
if (!contentImport.data.result) {
74+
alert('请先上传文件识别内容');
75+
return false;
76+
}
77+
editor.fireEvent('saveScene');
78+
editor.execCommand("inserthtml", contentImport.data.result);
79+
editor.fireEvent('saveScene');
80+
};
81+
dialog.oncancel = function () {
82+
83+
};
84+
}

0 commit comments

Comments
 (0)