feat: add catalog demo
This commit is contained in:
+12
@@ -303,9 +303,21 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="catalog" editor-component="catalog">
|
||||
<div class="catalog__header">
|
||||
<span>目录</span>
|
||||
<div class="catalog__header__close">
|
||||
<i></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="catalog__main"></div>
|
||||
</div>
|
||||
<div class="editor"></div>
|
||||
<div class="footer" editor-component="footer">
|
||||
<div>
|
||||
<div class="catalog-mode" title="目录">
|
||||
<i></i>
|
||||
</div>
|
||||
<div class="page-mode">
|
||||
<i title="页面模式(分页、连页)"></i>
|
||||
<div class="options">
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757"><path d="M13 0c.552 0 1 .48 1 1.071V13.93c0 .59-.448 1.07-1 1.07H3c-.552 0-1-.48-1-1.071V1.07C2 .48 2.448 0 3 0h10zm0 1H3v13h10V1z"/><path d="M5 10v1H4v-1h1zm6 0v1H6v-1h5zM5 7v1H4V7h1zm6 0v1H6V7h5zM5 4v1H4V4h1zm6 0v1H6V4h5z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 337 B |
@@ -4,7 +4,8 @@ export enum EditorComponent {
|
||||
MAIN = 'main',
|
||||
FOOTER = 'footer',
|
||||
CONTEXTMENU = 'contextmenu',
|
||||
POPUP = 'popup'
|
||||
POPUP = 'popup',
|
||||
CATALOG = 'catalog'
|
||||
}
|
||||
|
||||
export enum EditorContext {
|
||||
|
||||
+4
-1
@@ -42,6 +42,7 @@ import { ITitleOption } from './interface/Title'
|
||||
import { defaultTitleOption } from './dataset/constant/Title'
|
||||
import { TitleLevel } from './dataset/enum/Title'
|
||||
import { ListStyle, ListType } from './dataset/enum/List'
|
||||
import { ICatalog, ICatalogItem } from './interface/Catalog'
|
||||
|
||||
export default class Editor {
|
||||
|
||||
@@ -216,5 +217,7 @@ export type {
|
||||
IWatermark,
|
||||
INavigateInfo,
|
||||
IBlock,
|
||||
ILang
|
||||
ILang,
|
||||
ICatalog,
|
||||
ICatalogItem
|
||||
}
|
||||
+57
-4
@@ -1,10 +1,11 @@
|
||||
import { data, options } from './mock'
|
||||
import './style.css'
|
||||
import prism from 'prismjs'
|
||||
import Editor, { BlockType, Command, ControlType, EditorMode, ElementType, IBlock, IElement, KeyMap, ListStyle, ListType, PageMode, PaperDirection, RowFlex, TitleLevel } from './editor'
|
||||
import Editor, { BlockType, Command, ControlType, EditorMode, ElementType, IBlock, ICatalogItem, IElement, KeyMap, ListStyle, ListType, PageMode, PaperDirection, RowFlex, TitleLevel } from './editor'
|
||||
import { Dialog } from './components/dialog/Dialog'
|
||||
import { formatPrismToken } from './utils/prism'
|
||||
import { Signature } from './components/signature/Signature'
|
||||
import { debounce } from './utils'
|
||||
|
||||
window.onload = function () {
|
||||
const isApple = typeof navigator !== 'undefined' && /Mac OS X/.test(navigator.userAgent)
|
||||
@@ -844,7 +845,54 @@ window.onload = function () {
|
||||
instance.command.executePrint()
|
||||
}
|
||||
|
||||
// 6. 页面模式 | 纸张缩放 | 纸张大小 | 纸张方向 | 页边距 | 全屏
|
||||
// 6. 目录显隐 | 页面模式 | 纸张缩放 | 纸张大小 | 纸张方向 | 页边距 | 全屏
|
||||
async function updateCatalog() {
|
||||
const catalog = await instance.command.getCatalog()
|
||||
const catalogMainDom = document.querySelector<HTMLDivElement>('.catalog__main')!
|
||||
catalogMainDom.innerHTML = ''
|
||||
if (catalog) {
|
||||
const appendCatalog = (parent: HTMLDivElement, catalogItems: ICatalogItem[]) => {
|
||||
for (let c = 0; c < catalogItems.length; c++) {
|
||||
const catalogItem = catalogItems[c]
|
||||
const catalogItemDom = document.createElement('div')
|
||||
catalogItemDom.classList.add('catalog-item')
|
||||
// 渲染
|
||||
const catalogItemContentDom = document.createElement('div')
|
||||
catalogItemContentDom.classList.add('catalog-item__content')
|
||||
const catalogItemContentSpanDom = document.createElement('span')
|
||||
catalogItemContentSpanDom.innerText = catalogItem.name
|
||||
catalogItemContentDom.append(catalogItemContentSpanDom)
|
||||
// 定位
|
||||
catalogItemContentDom.onclick = () => {
|
||||
instance.command.executeLocationCatalog(catalogItem.id)
|
||||
}
|
||||
catalogItemDom.append(catalogItemContentDom)
|
||||
if (catalogItem.subCatalog && catalogItem.subCatalog.length) {
|
||||
appendCatalog(catalogItemDom, catalogItem.subCatalog)
|
||||
}
|
||||
// 追加
|
||||
parent.append(catalogItemDom)
|
||||
}
|
||||
}
|
||||
appendCatalog(catalogMainDom, catalog)
|
||||
}
|
||||
}
|
||||
let isCatalogShow = true
|
||||
const catalogDom = document.querySelector<HTMLElement>('.catalog')!
|
||||
const catalogModeDom = document.querySelector<HTMLDivElement>('.catalog-mode')!
|
||||
const catalogHeaderCloseDom = document.querySelector<HTMLDivElement>('.catalog__header__close')!
|
||||
const switchCatalog = () => {
|
||||
isCatalogShow = !isCatalogShow
|
||||
if (isCatalogShow) {
|
||||
catalogDom.style.display = 'block'
|
||||
updateCatalog()
|
||||
} else {
|
||||
catalogDom.style.display = 'none'
|
||||
}
|
||||
}
|
||||
catalogModeDom.onclick = switchCatalog
|
||||
catalogHeaderCloseDom.onclick = switchCatalog
|
||||
|
||||
const pageModeDom = document.querySelector<HTMLDivElement>('.page-mode')!
|
||||
const pageModeOptionsDom = pageModeDom.querySelector<HTMLDivElement>('.options')!
|
||||
pageModeDom.onclick = function () {
|
||||
@@ -1158,10 +1206,15 @@ window.onload = function () {
|
||||
activeMode.classList.add('active')
|
||||
}
|
||||
|
||||
instance.listener.contentChange = async function () {
|
||||
instance.listener.contentChange = debounce(async function () {
|
||||
// 字数
|
||||
const wordCount = await instance.command.getWordCount()
|
||||
document.querySelector<HTMLSpanElement>('.word-count')!.innerText = `${wordCount || 0}`
|
||||
}
|
||||
// 目录
|
||||
if (isCatalogShow) {
|
||||
updateCatalog()
|
||||
}
|
||||
}, 200)
|
||||
|
||||
instance.listener.saved = function (payload) {
|
||||
console.log('elementList: ', payload)
|
||||
|
||||
+87
-1
@@ -651,11 +651,83 @@ ul {
|
||||
background-image: url('./assets/images/print.svg');
|
||||
}
|
||||
|
||||
.catalog {
|
||||
width: 250px;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
top: 100px;
|
||||
padding: 0 20px 40px 20px;
|
||||
}
|
||||
|
||||
.catalog .catalog__header {
|
||||
height: 48px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #e2e6ed;
|
||||
}
|
||||
|
||||
.catalog .catalog__header span {
|
||||
color: #3d4757;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.catalog .catalog__header i {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
background: url(./assets/images/close.svg) no-repeat;
|
||||
transition: all .2s;
|
||||
}
|
||||
|
||||
.catalog .catalog__header>div:hover {
|
||||
background: rgba(235, 238, 241);
|
||||
}
|
||||
|
||||
.catalog__main {
|
||||
height: calc(100% - 60px);
|
||||
padding: 10px 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.catalog__main .catalog-item {
|
||||
width: 100%;
|
||||
padding-left: 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.catalog__main>.catalog-item {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.catalog__main .catalog-item .catalog-item__content {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.catalog__main .catalog-item .catalog-item__content:hover>span {
|
||||
color: #4991f2;
|
||||
}
|
||||
|
||||
.catalog__main .catalog-item .catalog-item__content span {
|
||||
color: #3d4757;
|
||||
line-height: 30px;
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.editor>div {
|
||||
margin: 80px auto;
|
||||
}
|
||||
|
||||
|
||||
.ce-page-container canvas {
|
||||
box-shadow: rgb(158 161 165 / 40%) 0px 2px 12px 0px;
|
||||
}
|
||||
@@ -681,6 +753,20 @@ ul {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer .catalog-mode {
|
||||
padding: 1px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.footer .catalog-mode i {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
background-image: url('./assets/images/catalog.svg');
|
||||
}
|
||||
|
||||
.footer .page-mode {
|
||||
padding: 1px;
|
||||
position: relative;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
export function debounce(func: Function, delay: number) {
|
||||
let timer: number
|
||||
return function (...args: any) {
|
||||
if (timer) {
|
||||
window.clearTimeout(timer)
|
||||
}
|
||||
timer = window.setTimeout(() => {
|
||||
// @ts-ignore
|
||||
func.apply(this, args)
|
||||
}, delay)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user