Skip to content

Commit

Permalink
Dev/0.4.0 (#16)
Browse files Browse the repository at this point in the history
* feat: split epub

* feat: style edit
  • Loading branch information
baicie authored Jan 10, 2024
1 parent ba0d06f commit 4536f46
Show file tree
Hide file tree
Showing 13 changed files with 305 additions and 147 deletions.
121 changes: 46 additions & 75 deletions packages/client/modules/common-reader/main.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<script lang='ts' setup>
import type { SearchOnlineResult } from '@b-reader/utils'
import { ConfigProvider, Layout, LayoutContent, LayoutSider, Tree } from 'ant-design-vue'
import type { DataNode, EventDataNode, TreeProps } from 'ant-design-vue/es/tree'
import { ConfigProvider, Tree } from 'ant-design-vue'
import type { TreeProps } from 'ant-design-vue/es/tree'
import { computed, onBeforeMount } from 'vue'
import ReaderContainer from '../../src/components/reader/reader-container.vue'
import { locale, theme } from '../../src/theme'
import { useCommonReader } from './use-reader'
Expand Down Expand Up @@ -30,12 +31,14 @@ const item = computed(() => {
}
})
const navs = computed<any>(() => state.navs)
const height = computed(() => window.innerHeight)
function handleClickChapter(selectedKeys: string[], e: { node: EventDataNode }) {
function handleClickChapter(selectedKeys: string[]) {
if (selectedKeys.length) {
// eslint-disable-next-line no-console
console.log(selectedKeys, e)
console.log(selectedKeys)
const name = selectedKeys[0].split('#').length > 1 ? selectedKeys[0].split('#')[1] : selectedKeys[0]
state.currentPath = name
const targetElement = document.getElementById(name)
Expand All @@ -53,30 +56,6 @@ function handleClickChapter(selectedKeys: string[], e: { node: EventDataNode })
}
}
// function onScrollend() {
// const lastItem = _content.value[_content.value.length - 1]
// const nextIndex = state.navs.findIndex(item => item.path === lastItem.id)
// const next = state.navs[nextIndex + 1]
// if (next) {
// sendMessage({
// path: 'reader:common:content:req',
// data: {
// md5: state.init.md5!,
// path: next.path,
// scroll: false,
// title: next.name,
// },
// })
// }
// }
// const onListUpdate = useThrottleFn((startIndex: number, endIndex: number, visibleStartIndex: number, visibleEndIndex: number) => {
// if (visibleEndIndex > visibleStartIndex) {
// const item = state.navs[visibleStartIndex + 1]
// getContent(item)
// }
// }, 1000)
function getContent(item?: SearchOnlineResult, scroll = false) {
// eslint-disable-next-line no-console
console.log('getContent', item)
Expand All @@ -93,60 +72,52 @@ function getContent(item?: SearchOnlineResult, scroll = false) {
}
}
function handleNext() {
const index = navs.value.findIndex(item => item.path === state.currentPath)
if (index === navs.value.length - 1)
return
handleClickChapter([navs.value[index + 1].path])
}
function handlePre() {
const index = navs.value.findIndex(item => item.path === state.currentPath)
if (index === 0)
return
handleClickChapter([navs.value[index - 1].path])
}
onBeforeMount(() => {
initApp()
})
</script>

<template>
<ConfigProvider :locale="locale" :theme="theme" class="flex">
<Layout>
<LayoutSider :width="250" :style="{ overflow: 'auto', height: '100vh', position: 'fixed', left: 0, top: 0, bottom: 0 }">
<template v-if="state.navs.length">
<Tree
:tree-data="state.navs as unknown as DataNode[]"
block-node
default-expand-all
selectable
:field-names="filedName"
:height="height"
@select="handleClickChapter"
/>
</template>
</LayoutSider>
<LayoutContent :style="{ marginLeft: '250px', padding: '24px' }">
<h1 :id="item.id">
{{ item.title }}
</h1>
<div v-html="item.content" />
<!-- <DynamicScroller
ref="scroller"
class="scroller"
:items="_content"
:min-item-size="50"
page-mode
emit-update
@scroll-end="onScrollend"
@update="onListUpdate"
>
<template #default="{ item, index, active }">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[
item.id,
]"
:data-index="index"
>
<h1 :id="item.id">
{{ item.title }}
</h1>
<div v-html="item.content" />
</DynamicScrollerItem>
</template>
</DynamicScroller> -->
</LayoutContent>
</Layout>
<ReaderContainer
@next="handleNext"
@pre="handlePre"
>
<template #menus>
<Tree
:tree-data="navs"
block-node
default-expand-all
selectable
:field-names="filedName"
:height="height"
@select="handleClickChapter"
/>
</template>

<template #default>
<div>
<h1 :id="item.id">
{{ item.title }}
</h1>
<div v-html="item.content" />
</div>
</template>
</ReaderContainer>
</ConfigProvider>
</template>

Expand Down
2 changes: 1 addition & 1 deletion packages/client/modules/common-reader/use-reader.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { reactive, ref, shallowReactive, toRaw } from 'vue'
import type { Book, MessageType, SearchOnlineResult } from '@b-reader/utils'
import { ref, shallowReactive, toRaw } from 'vue'
import { useAppStore } from '../../src/store/app'
import { getDataFromHtml } from '../../src/utils'

Expand Down
3 changes: 3 additions & 0 deletions packages/client/modules/reader/main.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { createApp } from 'vue'
import VueVirtualScroller from 'vue-virtual-scroller'
import directives from '../../src/directives'
import i18n from '../../src/locales'
import main from './main.vue'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'

const app = createApp(main)
app.use(directives)
app.use(i18n)
app.use(VueVirtualScroller)
app.mount('#app')
90 changes: 57 additions & 33 deletions packages/client/modules/reader/main.vue
Original file line number Diff line number Diff line change
@@ -1,37 +1,56 @@
<script lang="ts" setup>
import type { TreeProps } from 'ant-design-vue'
import { ConfigProvider, Layout, LayoutContent, LayoutSider, Tree, message } from 'ant-design-vue'
import type { DataNode, EventDataNode } from 'ant-design-vue/es/tree'
import { ConfigProvider, Layout, LayoutContent, LayoutSider, Tree } from 'ant-design-vue'
import { get } from 'lodash'
import { onBeforeMount, watchEffect } from 'vue'
import { computed, onBeforeMount } from 'vue'
import { locale, theme } from '../../src/theme'
import ReaderContainer from '../../src/components/reader/reader-container.vue'
import { RenderItem2 } from './render-item'
import { useEpubRender } from './use-render'
const { initReader, epub } = useEpubRender()
const { initReader, state, getContent } = useEpubRender()
const filedName: TreeProps['fieldNames'] = {
children: 'children',
title: 'label',
key: 'content',
}
function handleClickChapter(selectedKeys: string[], e: { node: EventDataNode }) {
if (selectedKeys.length) {
// eslint-disable-next-line no-console
console.log(selectedKeys, e)
const id = selectedKeys[0].split('#').length > 1 ? selectedKeys[0].split('#')[1] : selectedKeys[0]
scrollToElement(id)
const _content = computed(() => {
return Object.entries(state.contents).map(([, value]) => ({
id: value.id,
content: value.content,
}))
})
const item = computed(() => {
return _content.value.find(item => item.id === state.currentPath) || {
id: '',
content: '',
}
})
const height = computed(() => window.innerHeight)
const navs = computed<any>(() => state.navs)
function handleClickChapter(selectedKeys: string[]) {
if (selectedKeys.length)
getContent(selectedKeys[0])
}
function scrollToElement(name: string) {
// 获取目标元素的引用
const targetElement = document.getElementById(name)
// 使用 scrollIntoView 方法滚动到目标元素
targetElement && targetElement.scrollIntoView({
behavior: 'smooth', // 可选,滚动行为,可以是 'auto', 'smooth', 'instant'
})
function handleNext() {
const index = navs.value.findIndex(item => item.content === state.currentPath)
if (index === navs.value.length - 1)
return
handleClickChapter([navs.value[index + 1].content])
}
function handlePre() {
const index = navs.value.findIndex(item => item.content === state.currentPath)
if (index === 0)
return
handleClickChapter([navs.value[index - 1].content])
}
onBeforeMount(() => {
Expand All @@ -41,26 +60,31 @@ onBeforeMount(() => {
function getBodyItem(item: any) {
return get(item, 'content.html.$$[1].$$', [])
}
watchEffect(() => {
if (epub.contents.length)
message.destroy()
})
</script>

<template>
<ConfigProvider :locale="locale" :theme="theme">
<Layout>
<LayoutSider :width="250" :style="{ overflow: 'auto', height: '100vh', position: 'fixed', left: 0, top: 0, bottom: 0 }">
<template v-if="epub.nva.length">
<Tree :tree-data="epub.nva as unknown as DataNode[]" block-node default-expand-all selectable :field-names="filedName" @select="handleClickChapter" />
</template>
</LayoutSider>
<LayoutContent :style="{ marginLeft: '250px', padding: '24px' }">
<template v-for="item in epub.contents" :key="item.id">
<RenderItem2 :items="getBodyItem(item)" :root-id="item.id" />
<ReaderContainer
@next="handleNext"
@pre="handlePre"
>
<template #menus>
<template v-if="navs.length">
<Tree
:tree-data="navs"
block-node
default-expand-all
selectable
:field-names="filedName"
:height="height"
@select="handleClickChapter"
/>
</template>
</LayoutContent>
</Layout>
</template>

<template #default>
<RenderItem2 :items="getBodyItem(item)" :root-id="item.id" />
</template>
</ReaderContainer>
</ConfigProvider>
</template>
4 changes: 2 additions & 2 deletions packages/client/modules/reader/render-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export const RenderItem2 = defineComponent({
<Fragment>
{
items.value?.map((element) => {
const { '#name': tagName, $$: children, ...attributes } = element
const { '#name': tagName, $$: children, id: childId, ...attributes } = element

if (Object.keys(attributes).includes('_')) {
const { _, ...arts } = attributes
Expand All @@ -96,7 +96,7 @@ export const RenderItem2 = defineComponent({
const childElements = children
? <RenderItem2 items={children}></RenderItem2>
: null
return h(tagName, { ...attributes, id: id.value }, childElements as any)
return h(tagName, { ...attributes, id: childId || id.value }, childElements as any)
}
})
}
Expand Down
Loading

0 comments on commit 4536f46

Please sign in to comment.