Files
legado/modules/web/src/store/bookStore.ts

211 lines
6.4 KiB
TypeScript

import { defineStore } from 'pinia'
import API from '@api'
import type {
BaseBook,
Book,
BookChapter,
BookProgress,
SeachBook,
} from '@/book'
import type { webReadConfig } from '@/web'
import { ElMessage } from 'element-plus/es'
const default_config: webReadConfig = {
theme: 0,
font: 0,
fontSize: 18,
readWidth: 800,
infiniteLoading: false,
customFontName: '',
jumpDuration: 1000,
spacing: {
paragraph: 1,
line: 0.8,
letter: 0,
},
}
let webReadConfigLoadedDate: Date | undefined
export const useBookStore = defineStore('book', {
state: () => {
return {
searchBooks: [] as SeachBook[],
shelf: [] as Book[],
catalog: [] as BookChapter[],
readingBook: { chapterPos: 0, chapterIndex: 0 } as BaseBook & {
chapterPos: number
chapterIndex: number
isSeachBook?: boolean
},
popCataVisible: false,
contentLoading: true,
showContent: false,
config: default_config,
miniInterface: false,
readSettingsVisible: false,
}
},
getters: {
bookProgress: (state): BookProgress | undefined => {
if (state.catalog.length == 0) return
const { chapterIndex, chapterPos, name, author } = state.readingBook
const title = state.catalog[chapterIndex]?.title
if (!title) return
return {
name,
author,
durChapterIndex: chapterIndex,
durChapterPos: chapterPos,
durChapterTime: new Date().getTime(),
durChapterTitle: title,
}
},
theme: state => {
return state.config.theme
},
isNight: state => state.config.theme == 6,
},
actions: {
/** 从后端加载书架书籍,优先返回内存缓存 */
async loadBookShelf(): Promise<Book[]> {
const fetchBookshellf_promise = API.getBookShelf().then(resp => {
console.log('API.getBookShelf数据返回')
const { isSuccess, data, errorMsg } = resp.data
if (isSuccess === true) {
if (
this.shelf.length !== data.length &&
this.shelf.length > 0 &&
data.length > 0
) {
ElMessage.info(`书架数据已更新`)
}
this.shelf = data.sort((a, b) => {
const x = a['durChapterTime'] || 0
const y = b['durChapterTime'] || 0
return y - x
})
} else {
if (errorMsg.includes('还没有添加小说') && this.shelf.length > 0) {
ElMessage.info('当前书架上的书籍已经被删除')
return (this.shelf = [])
}
ElMessage.error(errorMsg ?? '后端返回格式错误!')
}
console.log('书架数据已更新')
return this.shelf
})
if (this.shelf.length > 0) {
// bookshelf data fetched before:do not await
console.log('返回缓存书架数据')
return this.shelf
} else {
console.log('从阅读后端获取书架数据...')
return await fetchBookshellf_promise
}
},
/** 从后端加载书籍目录,优先返回内存缓存 */
async loadWebCatalog(
book: typeof this.readingBook,
): Promise<BookChapter[]> {
const { bookUrl, name, chapterIndex } = book
const fetchChapterList_promise = API.getChapterList(
bookUrl as string,
).then(res => {
const { isSuccess, data, errorMsg } = res.data
if (isSuccess === false) {
ElMessage.error(errorMsg)
throw new Error()
}
if (
bookUrl === this.readingBook.bookUrl &&
data.length !== this.catalog.length &&
data.length > 0 &&
this.catalog.length > 0
) {
ElMessage.info(`书籍${name}: 章节目录已更新`)
}
this.catalog = data
console.log(`书籍${name}: 章节目录已更新`)
return this.catalog
})
if (
bookUrl === this.readingBook.bookUrl &&
this.catalog.length > 0 &&
this.catalog.length - 1 >= chapterIndex
) {
console.log(`返回书籍《${name}》 缓存的章节目录`)
return this.catalog
} else {
console.log(`从阅读后端获取书籍《${name}》 章节目录数据...`)
return await fetchChapterList_promise
}
},
setPopCataVisible(visible: boolean) {
this.popCataVisible = visible
},
setContentLoading(loading: boolean) {
this.contentLoading = loading
},
setReadingBook(readingBook: typeof this.readingBook) {
this.readingBook = readingBook
},
/** 只从从后端加载一次web阅读配置 */
async loadWebConfig() {
if (webReadConfigLoadedDate === undefined) {
const _config = await API.getReadConfig()
webReadConfigLoadedDate = new Date()
console.log(
`${this.$id}.loadWebConfig: ${webReadConfigLoadedDate.toLocaleString()}成功加载阅读配置`,
)
return this.setConfig(_config)
}
console.log(
`${this.$id}.loadWebConfig: 已于${webReadConfigLoadedDate.toLocaleString()}成功加载`,
)
},
setConfig(config?: webReadConfig) {
this.config = Object.assign({}, this.config, config)
},
setReadSettingsVisible(visible: boolean) {
this.readSettingsVisible = visible
},
setShowContent(visible: boolean) {
this.showContent = visible
},
setMiniInterface(mini: boolean) {
this.miniInterface = mini
},
async setSearchBooks(books: SeachBook[]) {
books.forEach(book => {
const isSeachBook = this.shelf.every(
item => item.bookUrl !== book.bookUrl,
)
if (isSeachBook === true) {
this.searchBooks.push(book)
}
})
},
clearSearchBooks() {
this.searchBooks = []
},
/** 1.保存进度到app 2.修改内存中的数据*/
async saveBookProgress() {
if (!this.bookProgress) return Promise.resolve()
const { bookUrl } = this.readingBook
const shelfRaw = toRaw(this.shelf)
const findIndex = shelfRaw.findIndex(book => book.bookUrl === bookUrl)
if (findIndex > -1) {
this.shelf[findIndex] = Object.assign(
{},
shelfRaw[findIndex],
this.bookProgress,
)
}
// 直接关闭浏览器时 http请求可能被取消
// return API.saveBookProgress(this.bookProgress)
return API.saveBookProgressWithBeacon(this.bookProgress)
},
},
})