feat: add catalog demo

pr675
Hufe921 3 years ago
parent 402e448559
commit 9343afe831

@ -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 {

@ -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
}

@ -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)

@ -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)
}
}
Loading…
Cancel
Save