Tips:一些记录,一些笔记

2024/04/28
SUNDAY
The only limit to our realization of tomorrow will be our doubts of today.
实现明天理想的唯一障碍是今天的疑虑。

01
CKEditor5
官方网站:
https://ckeditor.com/

CKEditor 5:所有特性:
https://ckeditor.com/docs/ckeditor5/latest/features/index.html
如果希望在Django中集成CKEditor,有两种方式:
通过官方网站下载CKEditor的安装介质,然后进行一步一步的配置
通过Django的Python软件包安装后,启用插件后,进行简单的配置
如果选择第一种方式,你首先需要在下面的官方下载页面获取你需要的软件包:
https://ckeditor.com/ckeditor-5/download/
https://ckeditor.com/ckeditor-5/online-builder/
另一种方式,你需要通过「PIP」安装相关的Python软件:
django-ckeditor
django-ckeditor5
如果你在百度或者谷歌上搜索「Django集成CKEditor」你找到的大部分的文档都是通过PIP安装,然后进行简单配置实现的。
在这里,以上两种方式我都会进行说明。
02
「方式一」CKEditor:定制自己想要的插件(Plugin)
可以在官方网站定制自己想要的插件(Plugin)

选好后,可以在官方网站在线打包:

然后,将最终生成的压缩包下载下来:


03
在Django中引入「CKEditor」
然后,解压:

解压后,可以先在「sample」中看看最终生成的效果是不是你期望的「编辑器的样子」
打开「index.html」

将解压的程序放入Django的「static」中:
我们需要放到Django中的部分是「build」文件夹中的这部分文件:



然后,就可以进行使用了。
04
在Django中使用CKEditor「前台页面展示」
在Django中使用CKEditor分为两个场景:
Django后台的Admin管理页面
Django前台的页面展示
一、「Django前台」的页面展示
先看效果:

这里,以「wiki_add.html」为例,所有的CKEditor的使用、JS的定义、CSS的配置都会围绕这个页面展开,这样也便于理解在前端页面中,到底是如何使用CKEditor的。
CSS样式表:

文件「ckeditor.css」
/*** @license Copyright (c) 2014-2024, CKSource Holding sp. z o.o. All rights reserved.* This file is licensed under the terms of the MIT License (see LICENSE.md).*/:root {--ck-sample-base-spacing: 2em;--ck-sample-color-white: #fff;--ck-sample-color-green: #279863;--ck-sample-color-blue: #1a9aef;--ck-sample-container-width: 1285px;--ck-sample-sidebar-width: 350px;--ck-sample-editor-min-height: 400px;--ck-sample-editor-z-index: 10;}/* --------- EDITOR STYLES ---------------------------------------------------------------------------------------- */.editor__editable,/* Classic build. */main .ck-editor[role='application'] .ck.ck-content,/* Decoupled document build. */.ck.editor__editable[role='textbox'],.ck.ck-editor__editable[role='textbox'],/* Inline & Balloon build. */.ck.editor[role='textbox'] {width: 100%;background: #fff;font-size: 1em;line-height: 1.6em;min-height: var(--ck-sample-editor-min-height);padding: 1.5em 2em;}.ck.ck-editor__editable {background: #fff;border: 1px solid hsl(0, 0%, 70%);width: 100%;}/* Because of sidebar `position: relative`, Edge is overriding the outline of a focused editor. */.ck.ck-editor__editable {position: relative;z-index: var(--ck-sample-editor-z-index);}.editor-container {display: flex;flex-direction: row;flex-wrap: nowrap;position: relative;width: 100%;height: 100%;justify-content: center;margin: 20px auto 20px auto;}.editor-container--with-sidebar > .ck.ck-editor {width: calc( 100% - var(--ck-sample-sidebar-width) );}/* --------- DECOUPLED (DOCUMENT) BUILD. ---------------------------------------------*/body[data-editor='DecoupledEditor'] .document-editor__toolbar {width: 100%;}body[data-editor='DecoupledEditor'] .collaboration-demo__editable,body[data-editor='DecoupledEditor'] .row-editor .editor {/* A pixel is added for each of the border. */width: calc(21cm + 2px);min-height: calc(29.7cm + 2px);/* To avoid having extra scrolls inside the editor container. */height: fit-content;padding: 2cm 1.2cm;margin: 2.5rem;border: 1px hsl( 0, 0%, 82.7% ) solid;background-color: var(--ck-sample-color-white);box-shadow: 0 0 5px hsla( 0, 0%, 0%, .1 );box-sizing: border-box;}body[data-editor='DecoupledEditor'] .row-editor {display: flex;position: relative;justify-content: center;overflow-y: auto;background-color: #f2f2f2;border: 1px solid hsl(0, 0%, 77%);/* Limit the max-height of the editor to avoid scrolling from bottom to top to see the toolbar. */max-height: 700px;}body[data-editor='DecoupledEditor'] .sidebar {background: transparent;border: 0;box-shadow: none;}/* --------- COMMENTS & TRACK CHANGES FEATURE ---------------------------------------------------------------------- */.sidebar {padding: 0 15px;position: relative;min-width: var(--ck-sample-sidebar-width);max-width: var(--ck-sample-sidebar-width);font-size: 20px;border: 1px solid hsl(0, 0%, 77%);background: hsl(0, 0%, 98%);border-left: 0;overflow: hidden;min-height: 100%;flex-grow: 1;}/* Do not inherit styles related to the editable editor content. See line 25.*/.sidebar .ck-content[role='textbox'],.ck.ck-annotation-wrapper .ck-content[role='textbox'] {min-height: unset;width: unset;padding: 0;background: transparent;}.sidebar.narrow {min-width: 60px;flex-grow: 0;}.sidebar.hidden {display: none !important;}#sidebar-display-toggle {position: absolute;z-index: 1;width: 30px;height: 30px;text-align: center;left: 15px;top: 30px;border: 0;padding: 0;color: hsl( 0, 0%, 50% );transition: 250ms ease color;background-color: transparent;}#sidebar-display-toggle:hover {color: hsl( 0, 0%, 30% );cursor: pointer;}#sidebar-display-toggle:focus,#sidebar-display-toggle:active {outline: none;border: 1px solid #a9d29d;}#sidebar-display-toggle svg {fill: currentColor;}/* --------- COLLABORATION FEATURES (USERS) ------------------------------------------------------------------------ */.row-presence {width: 100%;border: 1px solid hsl(0, 0%, 77%);border-bottom: 0;background: hsl(0, 0%, 98%);padding: var(--ck-spacing-small);/* Make `border-bottom` as `box-shadow` to not overlap with the editor border. */box-shadow: 0 1px 0 0 hsl(0, 0%, 77%);/* Make `z-index` bigger than `.editor` to properly display tooltips. */z-index: 20;}.ck.ck-presence-list {flex: 1;padding: 1.25rem .75rem;}.presence .ck.ck-presence-list__counter {order: 2;margin-left: var(--ck-spacing-large)}/* --------- REAL TIME COLLABORATION FEATURES (SHARE TOPBAR CONTAINER) --------------------------------------------- */.collaboration-demo__row {display: flex;position: relative;justify-content: center;overflow-y: auto;background-color: #f2f2f2;border: 1px solid hsl(0, 0%, 77%);}body[data-editor='InlineEditor'] .collaboration-demo__row {border: 0;}.collaboration-demo__container {max-width: var(--ck-sample-container-width);margin: 0 auto;padding: 1.25rem;}.presence, .collaboration-demo__row {transition: .2s opacity;}.collaboration-demo__topbar {background: #fff;border: 1px solid var(--ck-color-toolbar-border);display: flex;justify-content: space-between;align-items: center;border-bottom: 0;border-radius: 4px 4px 0 0;}.collaboration-demo__topbar .btn {margin-right: 1em;outline-offset: 2px;outline-width: 2px;background-color: var( --ck-sample-color-blue );}.collaboration-demo__topbar .btn:focus,.collaboration-demo__topbar .btn:hover {border-color: var( --ck-sample-color-blue );}.collaboration-demo__share {display: flex;align-items: center;padding: 1.25rem .75rem}.collaboration-demo__share-description p {margin: 0;font-weight: bold;font-size: 0.9em;}.collaboration-demo__share input {height: auto;font-size: 0.9em;min-width: 220px;margin: 0 10px;border-radius: 4px;border: 1px solid var(--ck-color-toolbar-border)}.collaboration-demo__share button,.collaboration-demo__share input {height: 40px;padding: 5px 10px;}.collaboration-demo__share button {position: relative;}.collaboration-demo__share button:focus {outline: none;}.collaboration-demo__share button[data-tooltip]::before,.collaboration-demo__share button[data-tooltip]::after {position: absolute;visibility: hidden;opacity: 0;pointer-events: none;transition: all .15s cubic-bezier(.5,1,.25,1);z-index: 1;}.collaboration-demo__share button[data-tooltip]::before {content: attr(data-tooltip);padding: 5px 15px;border-radius: 3px;background: #111;color: #fff;text-align: center;font-size: 11px;top: 100%;left: 50%;margin-top: 5px;transform: translateX(-50%);}.collaboration-demo__share button[data-tooltip]::after {content: '';border: 5px solid transparent;width: 0;font-size: 0;line-height: 0;top: 100%;left: 50%;transform: translateX(-50%);border-bottom: 5px solid #111;border-top: none;}.collaboration-demo__share button[data-tooltip]:hover:before,.collaboration-demo__share button[data-tooltip]:hover:after {visibility: visible;opacity: 1;}.collaboration-demo--ready {overflow: visible;height: auto;}.collaboration-demo--ready .presence,.collaboration-demo--ready .collaboration-demo__row {opacity: 1;}/* --------- PAGINATION FEATURE ------------------------------------------------------------------------------------ *//* Pagination view line must be stacked at least at the same level as the editor,otherwise it will be hidden underneath. */.ck.ck-pagination-view-line {z-index: var(--ck-sample-editor-z-index);}/* --------- REVISION HISTORY FEATURE ------------------------------------------------------------------------------ */.revision-viewer-container {display: none;max-width: 100%;word-wrap: break-word;}.revision-viewer-sidebar {position: relative;min-width: 310px;overflow: hidden;background: var(--ck-color-toolbar-background);border: 1px solid var(--ck-color-toolbar-border);margin-left: -1px;}/* A case when Pagination and Revision History features are enabled in the editor. *//* Move the square with page number from the Pagination plugin to the left side, so that it does not cover the RH sidebar. */body[data-revision-history='true'] .ck.ck-pagination-view-line::after {transform: translateX(-100%) !important;left: -1px !important;right: unset !important;}/* --------- DOCUMENT OUTLINE FEATURE ------------------------------------------------------------------------------ */.document-outline-container {max-height: 80vh;overflow-y: auto;margin-bottom: 1em;}.document-outline-container .ck.ck-document-outline {min-height: 100%;border: 1px solid var(--ck-color-base-border);background-color: hsl(0, 0%, 96%);}/* --------- SAMPLE GENERIC STYLES (not related to CKEditor) ------------------------------------------------------- */body, html {padding: 0;margin: 0;font-family: sans-serif, Arial, Verdana, "Trebuchet MS", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 16px;line-height: 1.5;}body {height: 100%;color: #2D3A4A;}body * {box-sizing: border-box;}a {color: #38A5EE;}header .centered {display: flex;flex-flow: row nowrap;justify-content: space-between;align-items: center;min-height: 8em;}header h1 a {font-size: 20px;display: flex;align-items: center;color: #2D3A4A;text-decoration: none;}header h1 img {display: block;height: 64px;}header nav ul {margin: 0;padding: 0;list-style-type: none;}header nav ul li {display: inline-block;}header nav ul li + li {margin-left: 1em;}header nav ul li a {font-weight: bold;text-decoration: none;color: #2D3A4A;}header nav ul li a:hover {text-decoration: underline;}main .message {padding: 0 0 var(--ck-sample-base-spacing);background: var(--ck-sample-color-green);color: var(--ck-sample-color-white);}main .message::after {content: "";z-index: -1;display: block;height: 10em;width: 100%;background: var(--ck-sample-color-green);position: absolute;left: 0;}main .message h2 {position: relative;padding-top: 1em;font-size: 2em;}.centered {max-width: var(--ck-sample-container-width);margin: 0 auto;padding: 0 var(--ck-sample-base-spacing);}.row {display: flex;position: relative;}.btn {cursor: pointer;padding: 8px 16px;font-size: 1rem;user-select: none;border-radius: 4px;transition: color .2s ease-in-out,background-color .2s ease-in-out,border-color .2s ease-in-out,opacity .2s ease-in-out;background-color: var(--ck-sample-color-button-blue);border-color: var(--ck-sample-color-button-blue);color: var(--ck-sample-color-white);display: inline-block;}.btn--tiny {padding: 6px 12px;font-size: .8rem;}footer {margin: calc(2*var(--ck-sample-base-spacing)) var(--ck-sample-base-spacing);font-size: .8em;text-align: center;color: rgba(0,0,0,.4);}/* --------- RWD --------------------------------------------------------------------------------------------------- */@media screen and ( max-width: 800px ) {:root {--ck-sample-base-spacing: 1em;}header h1 {width: 100%;}header h1 img {height: 40px;}header nav ul {text-align: right;}main .message h2 {font-size: 1.5em;}}
JS的定义:

文件「config.project.wiki.add.js」
DecoupledEditor.create( document.querySelector( '.editor' ), {// Editor configuration.} ).then( editor => {window.editor = editor;// Set a custom container for the toolbar.document.querySelector( '.document-editor__toolbar' ).appendChild( editor.ui.view.toolbar.element );document.querySelector( '.ck-toolbar' ).classList.add( 'ck-reset_all' );} ).catch( handleSampleError );function handleSampleError( error ) {const issueUrl = 'https://github.com/ckeditor/ckeditor5/issues';const message = ['Oops, something went wrong!',`Please, report the following error on ${ issueUrl } with the build id "sv0v4xk1a70f-rfval9obuxru" and the error stack trace:`].join( '\n' );console.error( message );console.error( error );}
页面设置:
母页(基础页)「project_manage.html」
在它的「body」上需要设置针对CKEditor5的属性:

<body data-editor="DecoupledEditor" data-collaboration="false" data-revision-history="false">
具体的插入富文本编辑器的页面「wiki_add.html」
继承母页的配置:

引入前面的CSS文件:

然后,在内容(content block)区域定义需要渲染CKEditor的位置:

最后,在「script」区域引用相关的JS:

该页面,完整的文件内容如下:
{% extends 'layout/project_manage.html' %}{% load static %}{% block css %}<style>.bd-placeholder-img {font-size: 1.125rem;text-anchor: middle;-webkit-user-select: none;-moz-user-select: none;user-select: none;}@media (min-width: 768px) {.bd-placeholder-img-lg {font-size: 3.5rem;}}.b-example-divider {height: 3rem;background-color: rgba(0, 0, 0, .1);border: solid rgba(0, 0, 0, .15);border-width: 1px 0;box-shadow: inset 0 .5em 1.5em rgba(0, 0, 0, .1), inset 0 .125em .5em rgba(0, 0, 0, .15);}.b-example-vr {flex-shrink: 0;width: 0.5rem;height: 100vh;}.bi {vertical-align: -.125em;fill: currentColor;}.nav-scroller {position: relative;z-index: 2;height: 2.75rem;overflow-y: hidden;}.nav-scroller .nav {display: flex;flex-wrap: nowrap;padding-bottom: 1rem;margin-top: -1px;overflow-x: auto;text-align: center;white-space: nowrap;-webkit-overflow-scrolling: touch;}.FormFolderCreateDetail {display: flex;flex-direction: column;background: rgba(31, 34, 37, 0.03);box-shadow: rgba(31, 34, 37, 0.06) 0px 0px 0px 1px inset;padding: 4px;gap: 4px;margin: 12px 0px;border-radius: 6px;}.FormFolderCreateDetailButton {font-family: Inter, -apple-system, BlinkMacSystemFont, sans-serif;-webkit-font-smoothing: antialiased;font-variant-numeric: lining-nums;font-feature-settings: "lnum", "calt";font-size: 13px;font-weight: 500;font-style: normal;font-stretch: normal;letter-spacing: -0.04px;line-height: 16px;display: grid;grid-template-columns: 1fr;-webkit-box-pack: justify;justify-content: space-between;-webkit-box-align: center;align-items: center;width: 100%;height: 32px;user-select: none;appearance: none;box-sizing: border-box;text-decoration: none;padding: 6px 8px;gap: 8px;border-radius: 6px;transition: background 0.15s cubic-bezier(0.4, 0, 0.2, 1) 0s, color, opacity;}.FormFolderCreateDetailButton:not(:disabled):not(.isStatic) {cursor: pointer;-webkit-tap-highlight-color: transparent;}.FormFolderCreateDetailButton.AppearanceDefault {background: rgba(31, 34, 37, 0);color: rgba(31, 34, 37, 0.9);}.FormFolderCreateDetailButton.hasRightContent {grid-template-columns: 1fr auto;}.FormFolderCreateDetailSpan {display: flex;flex-direction: column;padding: 2px 0px;text-align: left;min-width: 0px;}</style><link rel="stylesheet" href="{% static 'css/project/manage/sidebars.css' %}"><link rel="stylesheet" href="{% static 'css/ckeditor/ckeditor.css' %}"><!--<link rel="stylesheet" href="{% static 'plugin/wangeditor/css/style.css' %}">-->{% endblock %}{% block content %}<!-- SVG --><svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><symbol id="bootstrap" viewBox="0 0 118 94"><title>Bootstrap</title><path fill-rule="evenodd" clip-rule="evenodd" d="M24.509 0c-6.733 0-11.715 5.893-11.492 12.284.214 6.14-.064 14.092-2.066 20.577C8.943 39.365 5.547 43.485 0 44.014v5.972c5.547.529 8.943 4.649 10.951 11.153 2.002 6.485 2.28 14.437 2.066 20.577C12.794 88.106 17.776 94 24.51 94H93.5c6.733 0 11.714-5.893 11.491-12.284-.214-6.14.064-14.092 2.066-20.577 2.009-6.504 5.396-10.624 10.943-11.153v-5.972c-5.547-.529-8.934-4.649-10.943-11.153-2.002-6.484-2.28-14.437-2.066-20.577C105.214 5.894 100.233 0 93.5 0H24.508zM80 57.863C80 66.663 73.436 72 62.543 72H44a2 2 0 01-2-2V24a2 2 0 012-2h18.437c9.083 0 15.044 4.92 15.044 12.474 0 5.302-4.01 10.049-9.119 10.88v.277C75.317 46.394 80 51.21 80 57.863zM60.521 28.34H49.948v14.934h8.905c6.884 0 10.68-2.772 10.68-7.727 0-4.643-3.264-7.207-9.012-7.207zM49.948 49.2v16.458H60.91c7.167 0 10.964-2.876 10.964-8.281 0-5.406-3.903-8.178-11.425-8.178H49.948z"></path></symbol><symbol id="home" viewBox="0 0 16 16"><path d="M8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4.5a.5.5 0 0 0 .5-.5v-4h2v4a.5.5 0 0 0 .5.5H14a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146zM2.5 14V7.707l5.5-5.5 5.5 5.5V14H10v-4a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5v4H2.5z"/></symbol><symbol id="speedometer2" viewBox="0 0 16 16"><path d="M8 4a.5.5 0 0 1 .5.5V6a.5.5 0 0 1-1 0V4.5A.5.5 0 0 1 8 4zM3.732 5.732a.5.5 0 0 1 .707 0l.915.914a.5.5 0 1 1-.708.708l-.914-.915a.5.5 0 0 1 0-.707zM2 10a.5.5 0 0 1 .5-.5h1.586a.5.5 0 0 1 0 1H2.5A.5.5 0 0 1 2 10zm9.5 0a.5.5 0 0 1 .5-.5h1.5a.5.5 0 0 1 0 1H12a.5.5 0 0 1-.5-.5zm.754-4.246a.389.389 0 0 0-.527-.02L7.547 9.31a.91.91 0 1 0 1.302 1.258l3.434-4.297a.389.389 0 0 0-.029-.518z"/><path fill-rule="evenodd" d="M0 10a8 8 0 1 1 15.547 2.661c-.442 1.253-1.845 1.602-2.932 1.25C11.309 13.488 9.475 13 8 13c-1.474 0-3.31.488-4.615.911-1.087.352-2.49.003-2.932-1.25A7.988 7.988 0 0 1 0 10zm8-7a7 7 0 0 0-6.603 9.329c.203.575.923.876 1.68.63C4.397 12.533 6.358 12 8 12s3.604.532 4.923.96c.757.245 1.477-.056 1.68-.631A7 7 0 0 0 8 3z"/></symbol><symbol id="table" viewBox="0 0 16 16"><path d="M0 2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2zm15 2h-4v3h4V4zm0 4h-4v3h4V8zm0 4h-4v3h3a1 1 0 0 0 1-1v-2zm-5 3v-3H6v3h4zm-5 0v-3H1v2a1 1 0 0 0 1 1h3zm-4-4h4V8H1v3zm0-4h4V4H1v3zm5-3v3h4V4H6zm4 4H6v3h4V8z"/></symbol><symbol id="people-circle" viewBox="0 0 16 16"><path d="M11 6a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/><path fill-rule="evenodd" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm8-7a7 7 0 0 0-5.468 11.37C3.242 11.226 4.805 10 8 10s4.757 1.225 5.468 2.37A7 7 0 0 0 8 1z"/></symbol><symbol id="grid" viewBox="0 0 16 16"><path d="M1 2.5A1.5 1.5 0 0 1 2.5 1h3A1.5 1.5 0 0 1 7 2.5v3A1.5 1.5 0 0 1 5.5 7h-3A1.5 1.5 0 0 1 1 5.5v-3zM2.5 2a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zm6.5.5A1.5 1.5 0 0 1 10.5 1h3A1.5 1.5 0 0 1 15 2.5v3A1.5 1.5 0 0 1 13.5 7h-3A1.5 1.5 0 0 1 9 5.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zM1 10.5A1.5 1.5 0 0 1 2.5 9h3A1.5 1.5 0 0 1 7 10.5v3A1.5 1.5 0 0 1 5.5 15h-3A1.5 1.5 0 0 1 1 13.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3zm6.5.5A1.5 1.5 0 0 1 10.5 9h3a1.5 1.5 0 0 1 1.5 1.5v3a1.5 1.5 0 0 1-1.5 1.5h-3A1.5 1.5 0 0 1 9 13.5v-3zm1.5-.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z"/></symbol><symbol id="collection" viewBox="0 0 16 16"><path d="M2.5 3.5a.5.5 0 0 1 0-1h11a.5.5 0 0 1 0 1h-11zm2-2a.5.5 0 0 1 0-1h7a.5.5 0 0 1 0 1h-7zM0 13a1.5 1.5 0 0 0 1.5 1.5h13A1.5 1.5 0 0 0 16 13V6a1.5 1.5 0 0 0-1.5-1.5h-13A1.5 1.5 0 0 0 0 6v7zm1.5.5A.5.5 0 0 1 1 13V6a.5.5 0 0 1 .5-.5h13a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-.5.5h-13z"/></symbol><symbol id="calendar3" viewBox="0 0 16 16"><path d="M14 0H2a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zM1 3.857C1 3.384 1.448 3 2 3h12c.552 0 1 .384 1 .857v10.286c0 .473-.448.857-1 .857H2c-.552 0-1-.384-1-.857V3.857z"/><path d="M6.5 7a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm-9 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm-9 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol><symbol id="chat-quote-fill" viewBox="0 0 16 16"><path d="M16 8c0 3.866-3.582 7-8 7a9.06 9.06 0 0 1-2.347-.306c-.584.296-1.925.864-4.181 1.234-.2.032-.352-.176-.273-.362.354-.836.674-1.95.77-2.966C.744 11.37 0 9.76 0 8c0-3.866 3.582-7 8-7s8 3.134 8 7zM7.194 6.766a1.688 1.688 0 0 0-.227-.272 1.467 1.467 0 0 0-.469-.324l-.008-.004A1.785 1.785 0 0 0 5.734 6C4.776 6 4 6.746 4 7.667c0 .92.776 1.666 1.734 1.666.343 0 .662-.095.931-.26-.137.389-.39.804-.81 1.22a.405.405 0 0 0 .011.59c.173.16.447.155.614-.01 1.334-1.329 1.37-2.758.941-3.706a2.461 2.461 0 0 0-.227-.4zM11 9.073c-.136.389-.39.804-.81 1.22a.405.405 0 0 0 .012.59c.172.16.446.155.613-.01 1.334-1.329 1.37-2.758.942-3.706a2.466 2.466 0 0 0-.228-.4 1.686 1.686 0 0 0-.227-.273 1.466 1.466 0 0 0-.469-.324l-.008-.004A1.785 1.785 0 0 0 10.07 6c-.957 0-1.734.746-1.734 1.667 0 .92.777 1.666 1.734 1.666.343 0 .662-.095.931-.26z"/></symbol><symbol id="cpu-fill" viewBox="0 0 16 16"><path d="M6.5 6a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z"/><path d="M5.5.5a.5.5 0 0 0-1 0V2A2.5 2.5 0 0 0 2 4.5H.5a.5.5 0 0 0 0 1H2v1H.5a.5.5 0 0 0 0 1H2v1H.5a.5.5 0 0 0 0 1H2v1H.5a.5.5 0 0 0 0 1H2A2.5 2.5 0 0 0 4.5 14v1.5a.5.5 0 0 0 1 0V14h1v1.5a.5.5 0 0 0 1 0V14h1v1.5a.5.5 0 0 0 1 0V14h1v1.5a.5.5 0 0 0 1 0V14a2.5 2.5 0 0 0 2.5-2.5h1.5a.5.5 0 0 0 0-1H14v-1h1.5a.5.5 0 0 0 0-1H14v-1h1.5a.5.5 0 0 0 0-1H14v-1h1.5a.5.5 0 0 0 0-1H14A2.5 2.5 0 0 0 11.5 2V.5a.5.5 0 0 0-1 0V2h-1V.5a.5.5 0 0 0-1 0V2h-1V.5a.5.5 0 0 0-1 0V2h-1V.5zm1 4.5h3A1.5 1.5 0 0 1 11 6.5v3A1.5 1.5 0 0 1 9.5 11h-3A1.5 1.5 0 0 1 5 9.5v-3A1.5 1.5 0 0 1 6.5 5z"/></symbol><symbol id="gear-fill" viewBox="0 0 16 16"><path d="M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.283-.698-2.686.705-1.987 1.987l.169.311c.446.82.023 1.841-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1a1.464 1.464 0 0 1 .872 2.105l-.17.31c-.698 1.283.705 2.686 1.987 1.987l.311-.169a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.283.698 2.686-.705 1.987-1.987l-.169-.311a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.698-1.283-.705-2.686-1.987-1.987l-.311.169a1.464 1.464 0 0 1-2.105-.872l-.1-.34zM8 10.93a2.929 2.929 0 1 1 0-5.86 2.929 2.929 0 0 1 0 5.858z"/></symbol><symbol id="speedometer" viewBox="0 0 16 16"><path d="M8 2a.5.5 0 0 1 .5.5V4a.5.5 0 0 1-1 0V2.5A.5.5 0 0 1 8 2zM3.732 3.732a.5.5 0 0 1 .707 0l.915.914a.5.5 0 1 1-.708.708l-.914-.915a.5.5 0 0 1 0-.707zM2 8a.5.5 0 0 1 .5-.5h1.586a.5.5 0 0 1 0 1H2.5A.5.5 0 0 1 2 8zm9.5 0a.5.5 0 0 1 .5-.5h1.5a.5.5 0 0 1 0 1H12a.5.5 0 0 1-.5-.5zm.754-4.246a.389.389 0 0 0-.527-.02L7.547 7.31A.91.91 0 1 0 8.85 8.569l3.434-4.297a.389.389 0 0 0-.029-.518z"/><path fill-rule="evenodd" d="M6.664 15.889A8 8 0 1 1 9.336.11a8 8 0 0 1-2.672 15.78zm-4.665-4.283A11.945 11.945 0 0 1 8 10c2.186 0 4.236.585 6.001 1.606a7 7 0 1 0-12.002 0z"/></symbol><symbol id="toggles2" viewBox="0 0 16 16"><path d="M9.465 10H12a2 2 0 1 1 0 4H9.465c.34-.588.535-1.271.535-2 0-.729-.195-1.412-.535-2z"/><path d="M6 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 1a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm.535-10a3.975 3.975 0 0 1-.409-1H4a1 1 0 0 1 0-2h2.126c.091-.355.23-.69.41-1H4a2 2 0 1 0 0 4h2.535z"/><path d="M14 4a4 4 0 1 1-8 0 4 4 0 0 1 8 0z"/></symbol><symbol id="tools" viewBox="0 0 16 16"><path d="M1 0L0 1l2.2 3.081a1 1 0 0 0 .815.419h.07a1 1 0 0 1 .708.293l2.675 2.675-2.617 2.654A3.003 3.003 0 0 0 0 13a3 3 0 1 0 5.878-.851l2.654-2.617.968.968-.305.914a1 1 0 0 0 .242 1.023l3.356 3.356a1 1 0 0 0 1.414 0l1.586-1.586a1 1 0 0 0 0-1.414l-3.356-3.356a1 1 0 0 0-1.023-.242L10.5 9.5l-.96-.96 2.68-2.643A3.005 3.005 0 0 0 16 3c0-.269-.035-.53-.102-.777l-2.14 2.141L12 4l-.364-1.757L13.777.102a3 3 0 0 0-3.675 3.68L7.462 6.46 4.793 3.793a1 1 0 0 1-.293-.707v-.071a1 1 0 0 0-.419-.814L1 0zm9.646 10.646a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708zM3 11l.471.242.529.026.287.445.445.287.026.529L5 13l-.242.471-.026.529-.445.287-.287.445-.529.026L3 15l-.471-.242L2 14.732l-.287-.445L1.268 14l-.026-.529L1 13l.242-.471.026-.529.445-.287.287-.445.529-.026L3 11z"/></symbol><symbol id="chevron-right" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/></symbol><symbol id="geo-fill" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M4 4a4 4 0 1 1 4.5 3.969V13.5a.5.5 0 0 1-1 0V7.97A4 4 0 0 1 4 3.999zm2.493 8.574a.5.5 0 0 1-.411.575c-.712.118-1.28.295-1.655.493a1.319 1.319 0 0 0-.37.265.301.301 0 0 0-.057.09V14l.002.008a.147.147 0 0 0 .016.033.617.617 0 0 0 .145.15c.165.13.435.27.813.395.751.25 1.82.414 3.024.414s2.273-.163 3.024-.414c.378-.126.648-.265.813-.395a.619.619 0 0 0 .146-.15.148.148 0 0 0 .015-.033L12 14v-.004a.301.301 0 0 0-.057-.09 1.318 1.318 0 0 0-.37-.264c-.376-.198-.943-.375-1.655-.493a.5.5 0 1 1 .164-.986c.77.127 1.452.328 1.957.594C12.5 13 13 13.4 13 14c0 .426-.26.752-.544.977-.29.228-.68.413-1.116.558-.878.293-2.059.465-3.34.465-1.281 0-2.462-.172-3.34-.465-.436-.145-.826-.33-1.116-.558C3.26 14.752 3 14.426 3 14c0-.599.5-1 .961-1.243.505-.266 1.187-.467 1.957-.594a.5.5 0 0 1 .575.411z"/></symbol></svg><main class="d-flex flex-nowrap"><!-- 左侧 SideBars --><div class="d-flex flex-column flex-shrink-0 p-3 bg-white" style="width: 280px;"><!-- 头部图标 --><a href="#" class="d-flex align-items-center link-dark text-decoration-none pb-1 mb-1"><svg t="1714013295044" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1324" width="24" height="24"><path d="M512 512m-485.4784 0a485.4784 485.4784 0 1 0 970.9568 0 485.4784 485.4784 0 1 0-970.9568 0Z" fill="#A4E5FF" p-id="1325"></path><path d="M240.64 357.4272v124.6208h244.9408V258.3552H339.712A99.072 99.072 0 0 0 240.64 357.4272zM684.288 258.3552h-145.8688v223.6928H783.36V357.4272a99.072 99.072 0 0 0-99.072-99.072zM240.64 666.5728a99.072 99.072 0 0 0 99.072 99.072h145.8688v-229.0176H240.64zM538.4192 765.6448h145.8688A99.072 99.072 0 0 0 783.36 666.5728v-129.9456h-244.9408z" fill="#FFFFFF" p-id="1326"></path></svg><span style="margin-left: 10px;">All Documents</span></a><a href="#" class="d-flex align-items-center link-dark text-decoration-none pb-1 mb-1"><svg t="1714013254347" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1172" width="24" height="24"><path d="M512 512m-485.4784 0a485.4784 485.4784 0 1 0 970.9568 0 485.4784 485.4784 0 1 0-970.9568 0Z" fill="#FFDC78" p-id="1173"></path><path d="M512 232.8576A279.1424 279.1424 0 1 0 791.1424 512 279.1424 279.1424 0 0 0 512 232.8576z m128.3584 367.872a25.6 25.6 0 0 1-35.5328 6.8608L496.64 534.6816a25.6 25.6 0 0 1-11.264-21.1968V388.6592a25.6 25.6 0 0 1 51.2 0v111.2064l96.768 65.28a25.6 25.6 0 0 1 7.0144 35.584z" fill="#FFFFFF" p-id="1174"></path></svg><span style="margin-left: 10px;">Recents</span></a><a href="#" class="d-flex align-items-center link-dark text-decoration-none pb-2 mb-2 border-bottom"><svg t="1714013232606" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1020" width="24" height="24"><path d="M512 512m-485.4784 0a485.4784 485.4784 0 1 0 970.9568 0 485.4784 485.4784 0 1 0-970.9568 0Z" fill="#BEA3FB" p-id="1021"></path><path d="M539.0848 270.08l68.1984 138.24 152.4736 22.1184a30.208 30.208 0 0 1 16.7424 51.5072l-110.336 107.52 26.0608 151.9104a30.208 30.208 0 0 1-43.8272 31.8464L512 701.44l-136.3968 71.68a30.208 30.208 0 0 1-43.8272-31.8464l26.0608-151.9104-110.336-107.52a30.208 30.208 0 0 1 16.7424-51.5072l152.4736-22.1184 68.1984-138.24a30.208 30.208 0 0 1 54.1696 0.1024z" fill="#FFFFFF" p-id="1022"></path></svg><span style="margin-left: 10px;">Starred</span></a><!-- 头部以下的「树形菜单」 --><ul class="list-unstyled ps-0"><!-- 文件夹的分割行 --><div class="row"><span class="col" style="flex-basis: 1px; -webkit-box-flex: 1; flex-grow: 1; overflow: hidden;white-space: nowrap; text-overflow: ellipsis;">Folders</span><div class="col text-end"><!-- Modal Button --><button type="button"style="border: 0px; background: none; padding: 0; cursor: pointer;"class=""data-bs-toggle="modal"data-bs-target="#ModalFolderCreate"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M11.995 19.5a7.232 7.232 0 0 0 2.898-.585 7.582 7.582 0 0 0 2.392-1.627 7.748 7.748 0 0 0 1.625-2.398c.393-.904.59-1.868.59-2.89a7.172 7.172 0 0 0-.59-2.89 7.708 7.708 0 0 0-4.026-4.024 7.231 7.231 0 0 0-2.898-.586 7.209 7.209 0 0 0-2.888.586c-.905.39-1.7.932-2.387 1.626A7.788 7.788 0 0 0 5.09 9.11 7.172 7.172 0 0 0 4.5 12c0 1.022.197 1.986.59 2.89a7.748 7.748 0 0 0 1.625 2.398 7.582 7.582 0 0 0 2.392 1.627c.904.39 1.867.585 2.888.585Zm0-1.413c-.842 0-1.63-.156-2.363-.469A6.032 6.032 0 0 1 7.7 16.312a6.115 6.115 0 0 1-1.3-1.942A6.006 6.006 0 0 1 5.93 12a6.058 6.058 0 0 1 3.692-5.618 5.963 5.963 0 0 1 2.364-.47c.848 0 1.64.157 2.373.47.734.313 1.38.748 1.937 1.306a6.142 6.142 0 0 1 1.31 1.942c.315.737.473 1.527.473 2.37 0 .843-.156 1.633-.47 2.37a6.115 6.115 0 0 1-1.3 1.942 6.02 6.02 0 0 1-4.314 1.775ZM8.577 12c0 .204.065.37.195.497s.304.19.52.19H11.3v2.018c0 .204.062.373.186.506.123.133.29.2.501.2a.686.686 0 0 0 .506-.2.686.686 0 0 0 .2-.507v-2.016h2.006a.7.7 0 0 0 .511-.19.664.664 0 0 0 .195-.498.692.692 0 0 0-.195-.511.69.69 0 0 0-.51-.195h-2.007V9.286a.698.698 0 0 0-.2-.516.685.685 0 0 0-.506-.2.652.652 0 0 0-.502.2.728.728 0 0 0-.185.516v2.008H9.293a.703.703 0 0 0-.52.195c-.13.13-.196.3-.196.511Z" fill="#000"></path></svg></button><!--<button type="button"style="border: 0px; background: none; padding: 0; cursor: pointer;"class=""data-bs-toggle="dropdown"aria-expanded="false"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M11.995 19.5a7.232 7.232 0 0 0 2.898-.585 7.582 7.582 0 0 0 2.392-1.627 7.748 7.748 0 0 0 1.625-2.398c.393-.904.59-1.868.59-2.89a7.172 7.172 0 0 0-.59-2.89 7.708 7.708 0 0 0-4.026-4.024 7.231 7.231 0 0 0-2.898-.586 7.209 7.209 0 0 0-2.888.586c-.905.39-1.7.932-2.387 1.626A7.788 7.788 0 0 0 5.09 9.11 7.172 7.172 0 0 0 4.5 12c0 1.022.197 1.986.59 2.89a7.748 7.748 0 0 0 1.625 2.398 7.582 7.582 0 0 0 2.392 1.627c.904.39 1.867.585 2.888.585Zm0-1.413c-.842 0-1.63-.156-2.363-.469A6.032 6.032 0 0 1 7.7 16.312a6.115 6.115 0 0 1-1.3-1.942A6.006 6.006 0 0 1 5.93 12a6.058 6.058 0 0 1 3.692-5.618 5.963 5.963 0 0 1 2.364-.47c.848 0 1.64.157 2.373.47.734.313 1.38.748 1.937 1.306a6.142 6.142 0 0 1 1.31 1.942c.315.737.473 1.527.473 2.37 0 .843-.156 1.633-.47 2.37a6.115 6.115 0 0 1-1.3 1.942 6.02 6.02 0 0 1-4.314 1.775ZM8.577 12c0 .204.065.37.195.497s.304.19.52.19H11.3v2.018c0 .204.062.373.186.506.123.133.29.2.501.2a.686.686 0 0 0 .506-.2.686.686 0 0 0 .2-.507v-2.016h2.006a.7.7 0 0 0 .511-.19.664.664 0 0 0 .195-.498.692.692 0 0 0-.195-.511.69.69 0 0 0-.51-.195h-2.007V9.286a.698.698 0 0 0-.2-.516.685.685 0 0 0-.506-.2.652.652 0 0 0-.502.2.728.728 0 0 0-.185.516v2.008H9.293a.703.703 0 0 0-.52.195c-.13.13-.196.3-.196.511Z" fill="#000"></path></svg></button><ul class="dropdown-menu"><li><a class="dropdown-item" href="#">Create new subfolder</a></li><li><a class="dropdown-item" href="#">Edit</a></li><li><a class="dropdown-item" href="#">Move to</a></li><li><hr class="dropdown-divider"></li><li><a class="dropdown-item" href="#" style="color: red;">Delete</a></li></ul>--></div></div><!-- 第一组「树形菜单」 --><li class="mb-1"><button class="btn btn-toggle d-inline-flex align-items-center rounded border-0 collapsed"data-bs-toggle="collapse" data-bs-target="#home-collapse"aria-expanded="true">Home</button><div class="collapse show" id="home-collapse"><ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small"><li><a href="#" class="link-dark d-inline-flex text-decoration-none rounded">Overview</a></li><li><a href="#" class="link-dark d-inline-flex text-decoration-none rounded">Updates</a></li><li><a href="#" class="link-dark d-inline-flex text-decoration-none rounded">Reports</a></li></ul></div></li></ul></div><!-- Modal --><div class="modal fade ModalFolderCreate"id="ModalFolderCreate"role="dialog"tabindex="-1"aria-labelledby="ModalFolderCreateLabel"aria-hidden="true"data-bs-backdrop="static" data-bs-keyboard="false"><!-- Modal Dialog --><div class="modal-dialog modal-dialog-centered modal-dialog-scrollable"><div class="modal-content"><!-- 头部区域 --><div class="modal-header"><h4 class="modal-title fs-5"id="ModalFolderCreateLabel">Create New Folder</h4><button type="button" class="btn-close"data-bs-dismiss="modal"aria-label="Close"></button></div><!-- 内容区域 --><div class="modal-body"><form id="FormFolderCreateLabel"><!-- 文件夹名称 --><div class="form-group"><input class="form-control" type="text" placeholder="Folder Name"><span class="error-msg"></span><br></div><!-- 文件夹属性 --></form></div><!-- 底部区域 --><div class="modal-footer"><!--<button type="button"class="btn btn-secondary"data-bs-dismiss="modal">取消</button>--><button type="button"class="btn btn-primary"id="btnSubmitModalFolderCreate">Create</button></div></div></div></div><!-- 分割 --><!--<div class="b-example-divider b-example-vr"></div>--><!-- 右侧 --><div class="container-fluid"><!-- 右侧头部:工具栏(按钮) --><!--<div class="right-top-toolbar" style="margin-bottom: 5px"></div>--><!-- 右侧富文本 --><!-- 右侧头部:工具栏(按钮) --><div><!-- Button: Save --><a type="button"id="btnWikiAddSubmit"class="btn" style="margin-top: 2px; margin-left: 2px; background-color: deepskyblue;"><span><svg t="1714058006123" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="23526" width="24" height="24"><path d="M794.3 422.5c-11 0-20-9-20-20v-41.8L666.6 252.6v59.1c0 32.2-26.2 58.4-58.4 58.4h-218c-32.2 0-58.4-26.2-58.4-58.4V204.2c0-11 9-20 20-20s20 9 20 20v107.5c0 10.1 8.2 18.4 18.4 18.4h218c10.1 0 18.4-8.2 18.4-18.4V204.2c0-8.1 4.9-15.4 12.4-18.5 7.5-3.1 16.1-1.4 21.8 4.4l147.7 148.2c3.7 3.7 5.8 8.8 5.8 14.1v50.1c0 11.1-9 20-20 20z" fill="#1C1C1C" p-id="23527"></path><path d="M451.1 815.5h-208c-32.2 0-58.4-26.2-58.4-58.4V242.6c0-32.2 26.2-58.4 58.4-58.4h403.5c11 0 20 9 20 20s-9 20-20 20H243.1c-10.1 0-18.4 8.2-18.4 18.4v514.5c0 10.1 8.2 18.4 18.4 18.4h208c11 0 20 9 20 20s-9 20-20 20z" fill="#1C1C1C" p-id="23528"></path><path d="M304.4 814.6c-11 0-20-9-20-20V638c0-32.2 26.2-58.4 58.4-58.4h255c11 0 20 9 20 20s-9 20-20 20h-255c-10.1 0-18.4 8.2-18.4 18.4v156.7c0 10.9-9 19.9-20 19.9zM653.1 838.8c-5.1 0-10.2-2-14.1-5.9-7.8-7.8-7.8-20.5 0-28.3l230.4-230.4c4.8-4.8 4.8-12.7 0-17.5l-42.1-42.1c-4.7-4.7-12.8-4.7-17.5 0L579.3 745c-7.8 7.8-20.5 7.8-28.3 0-7.8-7.8-7.8-20.5 0-28.3l230.4-230.4c9.9-9.9 23-15.3 37-15.3s27.1 5.4 37 15.3l42.1 42.1c20.4 20.4 20.4 53.7 0 74.1L667.2 832.9c-3.9 3.9-9 5.9-14.1 5.9z" fill="#1C1C1C" p-id="23529"></path><path d="M539.6 864.2c-1.5 0-2.9-0.2-4.4-0.5-10.8-2.4-17.5-13.1-15.1-23.9l25.7-113.3c2.4-10.8 13.1-17.5 23.9-15.1 10.8 2.4 17.5 13.1 15.1 23.9L559 848.6c-2.1 9.3-10.3 15.6-19.4 15.6z" fill="#1C1C1C" p-id="23530"></path><path d="M539.5 864.2c-9.1 0-17.4-6.3-19.5-15.6-2.4-10.8 4.3-21.5 15.1-23.9L648.4 799c10.8-2.5 21.5 4.3 23.9 15.1 2.4 10.8-4.3 21.5-15.1 23.9L544 863.7c-1.5 0.3-3 0.5-4.5 0.5zM858.1 633.3c-5.1 0-10.2-2-14.1-5.9l-87.7-87.7c-7.8-7.8-7.8-20.5 0-28.3 7.8-7.8 20.5-7.8 28.3 0l87.7 87.7c7.8 7.8 7.8 20.5 0 28.3-4 4-9.1 5.9-14.2 5.9z" fill="#1C1C1C" p-id="23531"></path></svg></span>Save</a><!-- Button: Delete --><a type="button"class="btn" style="margin-top: 2px; margin-left: 2px; background-color: red;"href="#"><span><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8.692 20h6.625c.543 0 .98-.158 1.31-.474.33-.316.51-.748.54-1.295l.468-10.22h.76c.165 0 .307-.06.426-.182A.592.592 0 0 0 19 7.401a.593.593 0 0 0-.179-.429.576.576 0 0 0-.426-.182H5.605a.58.58 0 0 0-.422.182.585.585 0 0 0-.183.429c0 .164.061.306.183.428a.58.58 0 0 0 .422.182h.76l.477 10.23c.024.547.2.977.526 1.29.327.313.769.469 1.324.469Zm.12-1.222a.649.649 0 0 1-.477-.191.73.73 0 0 1-.21-.492L7.647 8.01h8.677l-.45 10.084a.697.697 0 0 1-.2.492.672.672 0 0 1-.496.191H8.812Zm1.072-1.13a.523.523 0 0 0 .37-.132.42.42 0 0 0 .133-.342l-.21-7.476a.442.442 0 0 0-.142-.346.521.521 0 0 0-.362-.128.506.506 0 0 0-.367.132.453.453 0 0 0-.137.342l.21 7.476a.479.479 0 0 0 .147.346c.092.085.21.128.358.128Zm2.116 0a.536.536 0 0 0 .38-.132.446.446 0 0 0 .142-.342V9.698a.446.446 0 0 0-.142-.342.536.536 0 0 0-.38-.132.54.54 0 0 0-.376.132.44.44 0 0 0-.146.342v7.476c0 .14.049.253.146.342a.54.54 0 0 0 .376.132Zm2.126 0c.14 0 .258-.043.352-.128a.47.47 0 0 0 .152-.346l.201-7.476a.419.419 0 0 0-.133-.342.523.523 0 0 0-.37-.132.504.504 0 0 0-.358.128.479.479 0 0 0-.147.346l-.201 7.476a.426.426 0 0 0 .128.342.52.52 0 0 0 .376.132ZM8.802 7.364h1.301V5.832a.59.59 0 0 1 .18-.45.66.66 0 0 1 .47-.17h2.484c.19 0 .344.057.463.17.119.112.178.262.178.45v1.532h1.31V5.741c0-.54-.166-.966-.499-1.276-.333-.31-.786-.465-1.36-.465h-2.676c-.574 0-1.026.155-1.356.465-.33.31-.495.735-.495 1.276v1.623Z" fill="#000"></path></svg></span>Delete</a><!-- Button: Others --></div><!-- 右侧编辑器 --><div class="row"><div class="document-editor__toolbar"></div></div><div class="row-editor" style="width: 100%;"><div class="editor-container"><div class="editor"></div></div></div></div></main>{% endblock %}{% block js %}<script type="text/javascript" src="{% static 'js/project/manage/sidebars.js' %}"></script><script type="text/javascript" src="{% static 'plugin/ckeditor/ckeditor.js' %}"></script><script type="text/javascript" src="{% static 'plugin/ckeditor/config.project.wiki.add.js' %}"></script><script>// 页面框架加载完成后自动执行的函数$(function() {btnWikiAddSubmitClick();});function btnWikiAddSubmitClick() {$('#btnWikiAddSubmit').click(function(){console.log("「保存」被点击了")})}</script>{% endblock %}
05
在Django中使用CKEditor「后台Admin管理页面」
再来看,如何在Django后台的Admin管理页面中使用CKEditor。
先看没有使用CKEditor的时候的效果:

可以看到,正文部分是一个输入框,并没有启用「富文本编辑器」
然后用「开发者模式」定位上面的输入框,找到它对应的「ID」:

可以看到,目标的ID为「id_wiki_content」
文件「config.project.wiki.admin.js」
ClassicEditor.create( document.querySelector( '.field-wiki_content' ) ).catch( error => {console.error( error );} );
修改「admin.py」
@admin.register(Wiki)class WikiAdmin(admin.ModelAdmin):fields = ['wiki_creator','project','wiki_name','wiki_type','wiki_parent','wiki_content',]list_display = ['wiki_creator', 'project','wiki_name','wiki_type','wiki_parent','wiki_content','wiki_datetime_create',]# 如果通过PIP的方式实现的CKEditor引入# 则需要注释「class Media」这一段代码class Media:# 引入CSS文件css = {'all': ('css/ckeditor/ckeditor.css',)}# 引入JS文件js = ('plugin/jQuery/jquery-3.7.1.min.js','plugin/ckeditor/ckeditor.js','plugin/ckeditor/translations/zh.js','plugin/ckeditor/config.project.wiki.admin.js',)
06
通过PIP装包的方式继承CKEditor
安装软件包:
(daily_info_management) (base) adamhuan@Leviathan daily_info_management % pwd/Users/adamhuan/PycharmProjects/visible-abyss/daily_info_management(daily_info_management) (base) adamhuan@Leviathan daily_info_management %(daily_info_management) (base) adamhuan@Leviathan daily_info_management % pip listPackage Version------------------- -----------asgiref 3.8.1async-timeout 4.0.3Django 5.0.4django-redis 5.4.0djangorestframework 3.15.1Faker 24.9.0pillow 10.3.0pip 24.0python-dateutil 2.9.0.post0redis 5.0.3setuptools 69.1.1six 1.16.0sqlparse 0.4.4typing_extensions 4.11.0wheel 0.42.0(daily_info_management) (base) adamhuan@Leviathan daily_info_management %(daily_info_management) (base) adamhuan@Leviathan daily_info_management % pip install django-ckeditor-5Looking in indexes: https://mirrors.aliyun.com/pypi/simple/Collecting django-ckeditor-5Downloading https://mirrors.aliyun.com/pypi/packages/b0/c4/22e7991cd1f97c3da00e687c1ab0868fac4520b7a9848cdb1e3261d94e86/django_ckeditor_5-0.2.12-py3-none-any.whl (2.1 MB)━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.1/2.1 MB 392.1 kB/s eta 0:00:00Requirement already satisfied: Django>=2.2 in Users/adamhuan/PycharmProjects/visible-abyss/python_virtual_env/daily_info_management/lib/python3.10/site-packages (from django-ckeditor-5) (5.0.4)Requirement already satisfied: Pillow in Users/adamhuan/PycharmProjects/visible-abyss/python_virtual_env/daily_info_management/lib/python3.10/site-packages (from django-ckeditor-5) (10.3.0)Requirement already satisfied: asgiref<4,>=3.7.0 in Users/adamhuan/PycharmProjects/visible-abyss/python_virtual_env/daily_info_management/lib/python3.10/site-packages (from Django>=2.2->django-ckeditor-5) (3.8.1)Requirement already satisfied: sqlparse>=0.3.1 in Users/adamhuan/PycharmProjects/visible-abyss/python_virtual_env/daily_info_management/lib/python3.10/site-packages (from Django>=2.2->django-ckeditor-5) (0.4.4)Requirement already satisfied: typing-extensions>=4 in Users/adamhuan/PycharmProjects/visible-abyss/python_virtual_env/daily_info_management/lib/python3.10/site-packages (from asgiref<4,>=3.7.0->Django>=2.2->django-ckeditor-5) (4.11.0)Installing collected packages: django-ckeditor-5Successfully installed django-ckeditor-5-0.2.12(daily_info_management) (base) adamhuan@Leviathan daily_info_management %
注册应用:

配置应用:文件「settings.py」
customColorPalette = [{'color': 'hsl(4, 90%, 58%)','label': 'Red'},{'color': 'hsl(340, 82%, 52%)','label': 'Pink'},{'color': 'hsl(291, 64%, 42%)','label': 'Purple'},{'color': 'hsl(262, 52%, 47%)','label': 'Deep Purple'},{'color': 'hsl(231, 48%, 48%)','label': 'Indigo'},{'color': 'hsl(207, 90%, 54%)','label': 'Blue'},]CKEDITOR_5_CONFIGS = {'default': {'toolbar': ['heading', '|', 'bold', 'italic', 'link','bulletedList', 'numberedList', 'blockQuote', 'imageUpload', ],},'extends': {'blockToolbar': ['paragraph', 'heading1', 'heading2', 'heading3','|','bulletedList', 'numberedList','|','blockQuote',],'toolbar': ['heading', '|', 'outdent', 'indent', '|', 'bold', 'italic', 'link', 'underline', 'strikethrough','code', 'subscript', 'superscript', 'highlight', '|', 'codeBlock', 'sourceEditing', 'insertImage','bulletedList', 'numberedList', 'todoList', '|', 'blockQuote', 'imageUpload', '|','fontSize', 'fontFamily', 'fontColor', 'fontBackgroundColor', 'mediaEmbed', 'removeFormat','insertTable', ],'image': {'toolbar': ['imageTextAlternative', '|', 'imageStyle:alignLeft','imageStyle:alignRight', 'imageStyle:alignCenter', 'imageStyle:side', '|'],'styles': ['full','side','alignLeft','alignRight','alignCenter',]},'table': {'contentToolbar': ['tableColumn', 'tableRow', 'mergeTableCells','tableProperties', 'tableCellProperties'],'tableProperties': {'borderColors': customColorPalette,'backgroundColors': customColorPalette},'tableCellProperties': {'borderColors': customColorPalette,'backgroundColors': customColorPalette}},'heading': {'options': [{'model': 'paragraph', 'title': 'Paragraph', 'class': 'ck-heading_paragraph'},{'model': 'heading1', 'view': 'h1', 'title': 'Heading 1', 'class': 'ck-heading_heading1'},{'model': 'heading2', 'view': 'h2', 'title': 'Heading 2', 'class': 'ck-heading_heading2'},{'model': 'heading3', 'view': 'h3', 'title': 'Heading 3', 'class': 'ck-heading_heading3'}]}},'list': {'properties': {'styles': 'true','startIndex': 'true','reversed': 'true',}}}
「settings.py」中,与「CKEditor」有关的其他配置项:
MEDIA_URL = '/media/'MEDIA_ROOT = os.path.join(BASE_DIR,'media/')CKEDITOR_JQUERY_URL = 'https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js'CKEDITOR_UPLOAD_PATH = 'uploads/'CKEDITOR_IMAGE_BACKEND = 'pillow'CKEDITOR_CONFIGS = {'default': {'toolbar': 'full','height':600,'width':800,},}
配置路由(主路由文件)
"""URL configuration for daily_info_management project.The `urlpatterns` list routes URLs to views. For more information please see:https://docs.djangoproject.com/en/5.0/topics/http/urls/Examples:Function views1. Add an import: from my_app import views2. Add a URL to urlpatterns: path('', views.templates, name='templates')Class-based views1. Add an import: from other_app.views import Home2. Add a URL to urlpatterns: path('', Home.as_view(), name='templates')Including another URLconf1. Import the include() function: from django.urls import include, path2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))"""from django.contrib import adminfrom django.urls import path, includefrom django.conf import settingsfrom django.conf.urls.static import staticurlpatterns = [# 首页path("", include("home.urls", namespace="home")),path("home/", include("home.urls", namespace="home")),# 管理页path("admin/", admin.site.urls),# 账户path("account/", include("account.urls",namespace="account")),# 项目path("project/", include("project.urls", namespace="project")),]# CKEditor 5urlpatterns += [path("ckeditor5/", include('django_ckeditor_5.urls'), name="ck_editor_5_upload_file"),] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
最后,修改目标属性的模型类:
from django.db import modelsfrom django_ckeditor_5.fields import CKEditor5Fieldclass Wiki(models.Model):"""维基百科"""class Meta:verbose_name = "维基百科"verbose_name_plural = verbose_nameproject = models.ForeignKey(verbose_name="所属项目",to="Project",on_delete=models.CASCADE)wiki_creator = models.ForeignKey(verbose_name="创建者",to=Account,on_delete=models.DO_NOTHING)wiki_name = models.CharField(verbose_name="名称",max_length=32)WIKI_TYPE_CHOICES = ((1, "文档 Document"),(2, "文件夹 Folder"),)wiki_type = models.SmallIntegerField(verbose_name="类型",choices=WIKI_TYPE_CHOICES,default=1)# 之前的# wiki_content = models.TextField(# verbose_name="正文"# )wiki_content = CKEditor5Field(verbose_name="正文",config_name='extends')wiki_datetime_create = models.DateTimeField(verbose_name="创建时间",auto_now_add=True,)wiki_parent = models.ForeignKey(verbose_name="父级",to="Wiki",on_delete=models.CASCADE,null=True,blank=True,related_name="wiki_children",)
由于修改了数据模型类的定义,因此要做「数据库的迁移」
(daily_info_management) (base) adamhuan@Leviathan daily_info_management % python manage.py makemigrationsSystem check identified some issues:WARNINGS:?: (2_0.W001) Your URL pattern 'star/(?P<project_type>\w+)/(?P<project_id>\d+)' [name='star'] has a route that contains '(?P<', begins with a '^', or ends with a '$'. This was likely an oversight when migrating to django.urls.path().?: (2_0.W001) Your URL pattern 'unstar/(?P<project_type>\w+)/(?P<project_id>\d+)' [name='unstar'] has a route that contains '(?P<', begins with a '^', or ends with a '$'. This was likely an oversight when migrating to django.urls.path().?: (rest_framework.W001) You have specified a default PAGE_SIZE pagination rest_framework setting, without specifying also a DEFAULT_PAGINATION_CLASS.HINT: The default for DEFAULT_PAGINATION_CLASS is None. In previous versions this was PageNumberPagination. If you wish to define PAGE_SIZE globally whilst defining pagination_class on a per-view basis you may silence this check.?: (urls.W005) URL namespace 'home' isn't unique. You may not be able to reverse all URLs in this namespaceMigrations for 'project':project/migrations/0007_alter_wiki_wiki_content.py- Alter field wiki_content on wiki(daily_info_management) (base) adamhuan@Leviathan daily_info_management %(daily_info_management) (base) adamhuan@Leviathan daily_info_management % python manage.py migrateSystem check identified some issues:WARNINGS:?: (2_0.W001) Your URL pattern 'star/(?P<project_type>\w+)/(?P<project_id>\d+)' [name='star'] has a route that contains '(?P<', begins with a '^', or ends with a '$'. This was likely an oversight when migrating to django.urls.path().?: (2_0.W001) Your URL pattern 'unstar/(?P<project_type>\w+)/(?P<project_id>\d+)' [name='unstar'] has a route that contains '(?P<', begins with a '^', or ends with a '$'. This was likely an oversight when migrating to django.urls.path().?: (rest_framework.W001) You have specified a default PAGE_SIZE pagination rest_framework setting, without specifying also a DEFAULT_PAGINATION_CLASS.HINT: The default for DEFAULT_PAGINATION_CLASS is None. In previous versions this was PageNumberPagination. If you wish to define PAGE_SIZE globally whilst defining pagination_class on a per-view basis you may silence this check.?: (urls.W005) URL namespace 'home' isn't unique. You may not be able to reverse all URLs in this namespaceOperations to perform:Apply all migrations: account, admin, auth, contenttypes, project, sessionsRunning migrations:Applying project.0007_alter_wiki_wiki_content... OK(daily_info_management) (base) adamhuan@Leviathan daily_info_management %
最后,看看后台管理页面的效果:

可以看到,CKEditor的富文本编辑器已经生效。
————————————————————
以上,便是如何在Django中集成CKEditor5的简单步骤。
而关于CKEditor与Django的结合,其实还有很多的话题与相关技术点可以探讨,我将会在后续的笔记中逐步更新。
END
温馨提示
如果你喜欢本文,请分享到朋友圈,想要获得更多信息,请关注我。




