@ -29,6 +29,7 @@ import {
Autosave ,
BalloonToolbar ,
Base64UploadAdapter ,
BlockQuote ,
Bold ,
Code ,
CodeBlock ,
@ -76,7 +77,7 @@ import {
SpecialCharactersMathematical ,
SpecialCharactersText ,
Strikethrough ,
/ / S t y l e ,
Style ,
Subscript ,
Superscript ,
Table ,
@ -98,9 +99,10 @@ import {
/ / S p l i t B u t t o n V i e w ,
Collection ,
addListToDropdown ,
/ / P o s i t i o n ,
/ / M o d e l ,
/ / a d d T o o l b a r T o D r o p d o w n
} from 'ckeditor5' ;
/ / i m p o r t t r a n s l a t i o n s f r o m ' c k e d i t o r 5 / t r a n s l a t i o n s / z h - c n . j s ' ;
@ -116,18 +118,24 @@ import { saveAs } from 'file-saver';
/ / i m p o r t S p l i t B u t t o n V i e w f r o m " @ c k e d i t o r / c k e d i t o r 5 - u i / s r c / d r o p d o w n / b u t t o n / s p l i t b u t t o n v i e w " ;
/ / 将 当 前 页 面 的 样 式 转 为 内 联
function getStyle ( ) {
function getStyle ( ) {
let str = '<head><meta charset="utf-8"></meta>' ;
const styles = document . querySelectorAll ( 'style' ) ;
for ( let i = 0 ; i < styles . length ; i ++ ) {
str += styles [ i ] . outerHTML ;
for ( let i = 0 ; i < styles . length ; i ++ ) {
str += styles [ i ] . outerHTML ;
}
str += "<style>.results{width:100%!important;} .result .title{width:100%;}</style>" ;
str += "<style>table{border-collapse: collapse;table-layout: fixed}</style>"
/ / s t r + = " < s t y l e > t a b l e t h e a d t r { b a c k g r o u n d - c o l o r : # f 3 f 4 f 9 ; } < / s t y l e > "
str += "<style>table td,th{ font-size: 14px;padding: 1px 1px;border-width: 1px;border-style: solid;border-color: #d0d0d0;word-break: keep-all;white-space: nowrap;}</style>"
str += "<style>table{border-collapse: collapse;table-layout: fixed}</style>"
/ / s t r + = " < s t y l e > t a b l e t h e a d t r { b a c k g r o u n d - c o l o r : # f 3 f 4 f 9 ; } < / s t y l e > "
str += "<style>table td,th{ font-size: 14px;padding: 1px 1px;border-width: 1px;border-style: solid;border-color: #d0d0d0;word-break: keep-all;white-space: nowrap;}</style>"
return str ;
}
/ / 获 取 用 户 编 辑 的 内 容 < h t m l >
function getPageContent ( ) {
const pageContent = document . querySelector ( "#app > div > div > div > div.editor-container__editor-wrapper > div > div > div.ck.ck-reset.ck-editor.ck-rounded-corners > div.ck.ck-editor__main" )
return pageContent . innerHTML ;
}
/ / 导 出 为 d o c x 插 件
class Export2Word extends Plugin {
init ( ) {
const editor = this . editor ;
@ -148,10 +156,10 @@ class Export2Word extends Plugin {
/ / E x e c u t e a c a l l b a c k f u n c t i o n w h e n t h e b u t t o n i s c l i c k e d
button . on ( 'execute' , ( ) => {
const pageContent = document . querySelector ( "#app > div > div > div > div.editor-container__editor-wrapper > div > div > div.ck.ck-reset.ck-editor.ck-rounded-corners > div.ck.ck-editor__main" )
const style = getStyle ( ) ;
const page = '<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style>@media print{@page{size:A4 portrait;margin:0cm 3cm}@page:left{margin-left:2.5cm;margin-right:2.7cm;}@page:right{margin-left:2.7cm;margin-right:2.5cm;}}</style>' + style + '</head><body>' + pageContent . outerHTML + '</body></html>'
const pageContent = getPageContent ( ) ;
const style = getStyle ( ) ;
const page = '<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style>@media print{@page{size:A4 portrait;margin:0cm 3cm}@page:left{margin-left:2.5cm;margin-right:2.7cm;}@page:right{margin-left:2.7cm;margin-right:2.5cm;}}</style>' + style + '</head><body>' + pageContent + '</body></html>'
/ / c o n s o l e . l o g ( p a g e ) ;
asBlob ( page ) . then ( data => {
saveAs ( data , 'file.docx' ) / / s a v e a s d o c x f i l e
@ -160,28 +168,29 @@ class Export2Word extends Plugin {
return button ;
} ) ;
/ / 增 加 菜 单 栏 ? 不 显 示 按 钮
editor . ui . extendMenuBar ( {
menu : {
menuId : 'export' ,
label : '导出' ,
groups : [
{
groupId : 'export' ,
items : [
'ExportToWord '
]
}
]
} ,
position : 'after:help '
}
) ;
/ / e d i t o r . u i . e x t e n d M e n u B a r ( {
/ / m e n u : {
/ / m e n u I d : ' e x p o r t ' ,
/ / l a b e l : ' 导 出 ' ,
/ / g r o u p s : [
/ / {
/ / g r o u p I d : ' e x p o r t ' ,
/ / i t e m s : [
/ / ' E x p o r t T o W o r d '
/ / ]
/ / }
/ / ]
/ / } ,
/ / p o s i t i o n : ' a f t e r : h e l p '
/ / }
/ / ) ;
}
}
class Export2PDF extends Plugin {
/ / 导 出 为 P D F 插 件
class Export2PDF extends Plugin {
init ( ) {
const editor = this . editor ;
@ -201,14 +210,15 @@ class Export2PDF extends Plugin{
/ / E x e c u t e a c a l l b a c k f u n c t i o n w h e n t h e b u t t o n i s c l i c k e d
button . on ( 'execute' , ( ) => {
const pageContent = document . querySelector ( "#app > div > div > div > div.editor-container__editor-wrapper > div > div > div.ck.ck-reset.ck-editor.ck-rounded-corners > div.ck.ck-editor__main" ) ;
const style = getStyle ( ) ;
const page = '<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style>@media print{@page{size:A4 portrait;margin:0cm 3cm}@page:left{margin-left:2.5cm;margin-right:2.7cm;}@page:right{margin-left:2.7cm;margin-right:2.5cm;}}</style>' + style + '</head><body>' + pageContent . outerHTML + '</body></html>'
const newWindow = window . open ( '' , 'PrintDocument' , 'height=600,width=700,top=50,left=50' ) ;
const pageContent = getPageContent ( ) ;
const style = getStyle ( ) ;
/ / 去 掉 e l e m e n t 中 的 c k - f o c u s e d c k - w e i g h t _ s e l e c t e d 消 除 页 面 和 图 片 的 蓝 边
const page = '<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style>@media print{@page{size:A4 portrait;margin:0cm 3cm}@page:left{margin-left:2.5cm;margin-right:2.7cm;}@page:right{margin-left:2.7cm;margin-right:2.5cm;}}</style>' + style + '</head><body>' + pageContent . replaceAll ( 'ck-focused' , 'ck-blurred' ) . replaceAll ( 'ck-weight_selected' , '' ) + '</body></html>'
const newWindow = window . open ( '' , 'PrintDocument' , 'height=600,width=700,top=50,left=50' ) ;
newWindow . document . write ( page ) ;
newWindow . document . close ( ) ;
newWindow . print ( ) ;
newWindow . onafterprint = function ( ) {
newWindow . onafterprint = function ( ) {
newWindow . close ( ) ;
}
} ) ;
@ -217,76 +227,75 @@ class Export2PDF extends Plugin{
} ) ;
}
}
/ / 智 能 润 色 插 件
class Translation extends Plugin {
init ( ) {
/ / c o n s o l e . l o g ( ' T r a n s l a t i o n i n i t i a l i z e d ! ' ) ;
init ( ) {
/ / c o n s o l e . l o g ( ' T r a n s l a t i o n i n i t i a l i z e d ! ' ) ;
this . editor . ui . componentFactory . add ( 'translate' , ( locale ) => {
const dropdownView = createDropdown ( locale ) ;
dropdownView . buttonView . set ( {
label : '智能助手' ,
withText : true ,
} ) ;
this . editor . ui . componentFactory . add ( 'translate' , ( locale ) => {
const dropdownView = createDropdown ( locale ) ;
dropdownView . buttonView . set ( {
label : '智能助手' ,
withText : true ,
} ) ;
const items = new Collection ( ) ;
items . add ( {
type : 'button' ,
model : {
id : 'summary' ,
withText : true ,
label : '摘要' ,
}
} ) ;
items . add ( {
type : 'button' ,
model : {
id : 'decoration' ,
withText : true ,
label : '润色'
}
} ) ;
items . add ( {
type : 'button' ,
model : {
id : 'extension' ,
withText : true ,
label : '续写'
}
} ) ;
items . add ( {
type : 'button' ,
model : {
id : 'correction' ,
withText : true ,
label : '修改'
}
} ) ;
items . add ( {
type : 'button' ,
model : {
id : 'translation' ,
withText : true ,
label : '翻译'
}
} ) ;
addListToDropdown ( dropdownView , items ) ;
const items = new Collection ( ) ;
items . add ( {
type : 'button' ,
model : {
id : 'summary' ,
withText : true ,
label : '摘要' ,
}
} ) ;
items . add ( {
type : 'button' ,
model : {
id : 'decoration' ,
withText : true ,
label : '润色'
}
} ) ;
items . add ( {
type : 'button' ,
model : {
id : 'extension' ,
withText : true ,
label : '续写'
}
} ) ;
items . add ( {
type : 'button' ,
model : {
id : 'correction' ,
withText : true ,
label : '修改'
}
} ) ;
items . add ( {
type : 'button' ,
model : {
id : 'translation' ,
withText : true ,
label : '翻译'
}
} ) ;
addListToDropdown ( dropdownView , items ) ;
dropdownView . on ( 'execute' , ( eventInfo ) => {
const { id , label } = eventInfo . source ;
dropdownView . on ( 'execute' , ( eventInfo ) => {
const { id , label } = eventInfo . source ;
/ / 获 取 选 中 的 文 本 , 用 来 进 行 后 续 操 作
const selectionText = window . getSelection ( ) . toString ( ) ;
if ( id === 'summary' ) {
if ( id === 'summary' ) {
/ / t h i s . e d i t o r . e x e c u t e ( ' E x p o r t T o W o r d ' ) ;
console . log ( 'Object (en):' , label , selectionText ) ;
}
} ) ;
console . log ( 'Object (en):' , label , selectionText ) ;
}
} ) ;
return dropdownView ;
} ) ;
}
return dropdownView ;
} ) ;
}
}
export default {
name : 'app' ,
data ( ) {
@ -294,10 +303,11 @@ export default {
isLayoutReady : false ,
config : null , / / C K E d i t o r n e e d s t h e D O M t r e e b e f o r e c a l c u l a t i n g t h e c o n f i g u r a t i o n .
/ / e d i t o r : D e c o u p l e d E d i t o r
editor : ClassicEditor
editor : ClassicEditor
} ;
} ,
mounted ( ) {
const userConfig = getUserConfigFromBackend ( ) ;
this . config = {
toolbar : {
items : [
@ -305,7 +315,7 @@ export default {
'redo' ,
'|' ,
'heading' ,
/ / ' s t y l e ' ,
'style' ,
'|' ,
'fontSize' ,
'fontFamily' ,
@ -321,14 +331,14 @@ export default {
'insertTable' ,
'highlight' ,
'codeBlock' ,
'blockquote' ,
'|' ,
'alignment' ,
'|' ,
'bulletedList' ,
'numberedList' ,
'outdent' ,
'indent' ,
'|' , 'ExportToWord' , 'ExportToPDF' , 'translate'
'|' , 'ExportToWord' , 'ExportToPDF' , 'translate'
] ,
shouldNotGroupWhenFull : true
} ,
@ -341,6 +351,7 @@ export default {
Autosave ,
BalloonToolbar ,
Base64UploadAdapter ,
BlockQuote ,
Bold ,
Code ,
CodeBlock ,
@ -388,7 +399,7 @@ export default {
SpecialCharactersMathematical ,
SpecialCharactersText ,
Strikethrough ,
/ / S t y l e ,
Style ,
Subscript ,
Superscript ,
Table ,
@ -401,37 +412,19 @@ export default {
TodoList ,
Underline ,
Undo ,
Export2Word , Translation , Export2PDF
Export2Word , Translation , Export2PDF
] ,
balloonToolbar : [ 'bold' , 'italic' , '|' , 'link' , 'insertImage' , '|' , 'bulletedList' , 'numberedList' ] ,
/ / 自 定 义 设 置 字 体
fontFamily : {
/ / 显 示 所 有 字 体
/ / 自 定 义 字 体
options : userConfig . fontFamily . options ,
/ / 启 用 对 所 有 字 体 名 称 的 支 持
supportAllValues : true ,
/ / 增 加 字 体
options : [
'default' ,
'宋体' ,
'新宋体' ,
'仿宋' ,
'楷体' ,
'微软雅黑' ,
'黑体' ,
'华文仿宋' ,
'华文楷体' ,
'华文隶书' ,
'华文宋体' ,
'华文细黑' ,
'华文新魏' ,
'华文行楷' ,
'华文中宋' ,
'隶书' ,
'苹方 常规' ,
'幼圆' ,
] ,
} ,
fontSize : {
options : [ 10 , 12 , 14 , 'default' , 18 , 20 , 22 ] ,
/ / 五 号 , 小 四 , 四 号 , 小 三 , 三 号 , 小 二 , 二 号
options : userConfig . fontSize . options ,
supportAllValues : true
} ,
heading : {
@ -501,6 +494,9 @@ export default {
'resizeImage'
]
} ,
/ / 初 始 化 数 据 , 新 建 页 面 时 显 示 空 白 / 选 择 的 模 板
/ / 打 开 已 有 页 面 时 将 页 面 数 据 传 入
/ / T O D O
initialData :
'<h2>Congratulations on setting up CKEditor 5! 🎉</h2>\n<p>\n You\'ve successfully created a CKEditor 5 project. This powerful text editor will enhance your application, enabling rich text editing\n capabilities that are customizable and easy to use.\n</p>\n<h3>What\'s next?</h3>\n<ol>\n <li>\n <strong>Integrate into your app</strong>: time to bring the editing into your application. Take the code you created and add to your\n application.\n </li>\n <li>\n <strong>Explore features:</strong> Experiment with different plugins and toolbar options to discover what works best for your needs.\n </li>\n <li>\n <strong>Customize your editor:</strong> Tailor the editor\'s configuration to match your application\'s style and requirements. Or even\n write your plugin!\n </li>\n</ol>\n<p>\n Keep experimenting, and don\'t hesitate to push the boundaries of what you can achieve with CKEditor 5. Your feedback is invaluable to us\n as we strive to improve and evolve. Happy editing!\n</p>\n<h3>Helpful resources</h3>\n<ul>\n <li>📝 <a href="https://orders.ckeditor.com/trial/premium-features">Trial sign up</a>,</li>\n <li>📕 <a href="https://ckeditor.com/docs/ckeditor5/latest/installation/index.html">Documentation</a>,</li>\n <li>⭐️ <a href="https://github.com/ckeditor/ckeditor5">GitHub</a> (star us if you can!),</li>\n <li>🏠 <a href="https://ckeditor.com">CKEditor Homepage</a>,</li>\n <li>🧑💻 <a href="https://ckeditor.com/ckeditor-5/demo/">CKEditor 5 Demos</a>,</li>\n</ul>\n<h3>Need help?</h3>\n<p>\n See this text, but the editor is not starting up? Check the browser\'s console for clues and guidance. It may be related to an incorrect\n license key if you use premium features or another feature-related requirement. If you cannot make it work, file a GitHub issue, and we\n will help as soon as possible!\n</p>\n' ,
language : 'zh-cn' ,
@ -536,60 +532,24 @@ export default {
} ,
menuBar : {
isVisible : true ,
removeItems : [ 'help' ] ,
} ,
placeholder : 'Type or paste your content here!' ,
/ / s t y l e : {
/ / d e f i n i t i o n s : [
/ / {
/ / n a m e : ' A r t i c l e c a t e g o r y ' ,
/ / e l e m e n t : ' h 3 ' ,
/ / c l a s s e s : [ ' c a t e g o r y ' ]
/ / } ,
/ / {
/ / n a m e : ' T i t l e ' ,
/ / e l e m e n t : ' h 2 ' ,
/ / c l a s s e s : [ ' d o c u m e n t - t i t l e ' ]
/ / } ,
/ / {
/ / n a m e : ' S u b t i t l e ' ,
/ / e l e m e n t : ' h 3 ' ,
/ / c l a s s e s : [ ' d o c u m e n t - s u b t i t l e ' ]
/ / } ,
/ / {
/ / n a m e : ' I n f o b o x ' ,
/ / e l e m e n t : ' p ' ,
/ / c l a s s e s : [ ' i n f o - b o x ' ]
/ / } ,
/ / {
/ / n a m e : ' S i d e q u o t e ' ,
/ / e l e m e n t : ' b l o c k q u o t e ' ,
/ / c l a s s e s : [ ' s i d e - q u o t e ' ]
/ / } ,
/ / {
/ / n a m e : ' M a r k e r ' ,
/ / e l e m e n t : ' s p a n ' ,
/ / c l a s s e s : [ ' m a r k e r ' ]
/ / } ,
/ / {
/ / n a m e : ' S p o i l e r ' ,
/ / e l e m e n t : ' s p a n ' ,
/ / c l a s s e s : [ ' s p o i l e r ' ]
/ / } ,
/ / {
/ / n a m e : ' C o d e ( d a r k ) ' ,
/ / e l e m e n t : ' p r e ' ,
/ / c l a s s e s : [ ' f a n c y - c o d e ' , ' f a n c y - c o d e - d a r k ' ]
/ / } ,
/ / {
/ / n a m e : ' C o d e ( b r i g h t ) ' ,
/ / e l e m e n t : ' p r e ' ,
/ / c l a s s e s : [ ' f a n c y - c o d e ' , ' f a n c y - c o d e - b r i g h t ' ]
/ / }
/ / ]
/ / } ,
/ / 用 户 可 以 自 定 义 和 管 理 样 式
style : {
definitions : userConfig . style . definitions
} ,
table : {
contentToolbar : [ 'tableColumn' , 'tableRow' , 'mergeTableCells' , 'tableProperties' , 'tableCellProperties' ]
} ,
autosave : {
waitingTime : 180000 , / / ( i n m s ) 3 m i n u t e s
save ( ) {
/ / T O D O s a v e
return saveData ( getPageContent ( ) ) ;
}
} ,
/ / t r a n s l a t i o n s : [ t r a n s l a t i o n s ]
} ;
@ -605,4 +565,118 @@ export default {
}
}
} ;
/ / 更 灵 活 配 置
function getUserConfigFromBackend ( ) {
/ / T O D O 请 求 用 户 配 置
const options = { }
/ / 字 体 、 字 号 、 样 式
/ / T O D O
const {
fontFamilyOptions = [
'default' ,
'宋体' ,
'新宋体' ,
'仿宋' ,
'楷体' ,
'微软雅黑' ,
'黑体' ,
'华文仿宋' ,
'华文楷体' ,
'华文隶书' ,
'华文宋体' ,
'华文细黑' ,
'华文新魏' ,
'华文行楷' ,
'华文中宋' ,
'隶书' ,
'苹方 常规' ,
'幼圆' ,
'Times New Roman'
] ,
/ / 五 号 , 小 四 , 四 号 , 小 三 , 三 号 , 小 二 , 二 号
fontSizeOptions = [ 10.5 , 12 , 14 , 15 , 'default' , 18 , 22 ] ,
styleDefinitions = [
{
name : 'Article category' ,
element : 'h3' ,
classes : [ 'category' ]
} ,
{
name : 'Title' ,
element : 'h2' ,
classes : [ 'document-title' ]
} ,
{
name : 'Subtitle' ,
element : 'h3' ,
classes : [ 'document-subtitle' ]
} ,
{
name : 'Info box' ,
element : 'p' ,
classes : [ 'info-box' ]
} ,
{
name : 'Side quote' ,
element : 'blockquote' ,
classes : [ 'side-quote' ]
} ,
{
name : 'Marker' ,
element : 'span' ,
classes : [ 'marker' ]
} ,
{
name : 'Spoiler' ,
element : 'span' ,
classes : [ 'spoiler' ]
} ,
{
name : 'Code (dark)' ,
element : 'pre' ,
classes : [ 'fancy-code' , 'fancy-code-dark' ]
} ,
{
name : 'Code (bright)' ,
element : 'pre' ,
classes : [ 'fancy-code' , 'fancy-code-bright' ]
} ,
{
name : 'GradientBorder' ,
element : 'p' ,
classes : [ 'gradientborder' ]
}
]
} = options ;
/ / 如 果 传 入 的 o p t i o n s 没 有 对 应 项 , 使 用 默 认 值
return {
fontFamily : {
options : fontFamilyOptions
} ,
fontSize : {
options : fontSizeOptions
} ,
style : {
definitions : styleDefinitions
}
} ;
}
/ / T O D O 实 现 自 动 保 存 s a v e D a t a 方 法 , 将 编 辑 内 容 发 送 至 后 端
function saveData ( data ) {
/ / r e t u r n n e w P r o m i s e ( r e s o l v e = > {
/ / s e t T i m e o u t ( ( ) = > {
/ / c o n s o l e . l o g ( ' S a v e d ' , d a t a ) ;
/ / r e s o l v e ( ) ;
/ / } , H T T P _ S E R V E R _ L A G ) ;
/ / } ) ;
console . log ( data ) ;
}
/ / T O D O 手 动 保 存
/ / f u n c t i o n s a v e B y H a n d ( ) {
/ / t h i s . e d i t o r . p l u g i n s . g e t ( ' A u t o s a v e ' ) . s a v e ( ) . t h e n ( ( ) = > {
/ / c o n s o l e . l o g ( ' D a t a s a v e d s u c c e s s f u l l y ' ) ;
/ / } ) ;
/ / }
< / script >