Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev/0.4.0 #16

Merged
merged 2 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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