From 4323acb4d6ee67f618798e247a58773180f4b123 Mon Sep 17 00:00:00 2001 From: UnknownMp Date: Sun, 18 May 2025 13:33:39 +0800 Subject: [PATCH] =?UTF-8?q?[Feature]=20=E7=A7=BB=E9=99=A4=E4=B9=A6?= =?UTF-8?q?=E7=AD=BE=E6=9C=BA=E5=88=B6=20=E6=9B=B4=E6=96=B0=E4=BA=86?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=8F=8F=E8=BF=B0=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=AF=B9=E6=9C=89=E7=AB=A0=E8=8A=82=E4=BD=9C=E5=93=81=E9=98=85?= =?UTF-8?q?=E8=AF=BB=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [BugFix] BetterHr 无法在 Markdown 显示的问题 [Base] 增加 Markdown 渲染锚点支持 --- package-lock.json | 30 +++++++-- package.json | 3 +- src/main.js | 1 + src/router.js | 32 +++++++-- src/stores/api.js | 5 +- src/stores/db.js | 58 ---------------- src/stores/workRead.js | 11 +-- src/texts/about.md | 7 ++ src/texts/intro.md | 15 +++-- src/ui/BetterHr.vue | 1 - src/views/Root.vue | 16 +++-- src/views/Work.vue | 148 ++++++----------------------------------- vite.config.js | 55 ++++++++++++++- 13 files changed, 165 insertions(+), 217 deletions(-) delete mode 100644 src/stores/db.js diff --git a/package-lock.json b/package-lock.json index fe0d3f6..a92fa54 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,6 @@ "compress-json": "^3.1.1", "cookie-parser": "^1.4.7", "express": "^5.1.0", - "idb": "^8.0.3", "mdui": "^2.1.3", "pinia": "^3.0.2", "vue": "^3.5.13", @@ -23,6 +22,8 @@ "@vitejs/plugin-vue": "^5.2.4", "@vitejs/plugin-vue-jsx": "^4.1.2", "cross-env": "^7.0.3", + "markdown-it-anchor": "^9.2.0", + "markdown-it-attrs": "^4.3.1", "sass": "^1.88.0", "vite": "^6.3.5", "vite-plugin-md": "^0.21.5", @@ -3797,11 +3798,6 @@ "node": ">=0.10.0" } }, - "node_modules/idb": { - "version": "8.0.3", - "resolved": "https://registry.npmmirror.com/idb/-/idb-8.0.3.tgz", - "integrity": "sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg==" - }, "node_modules/immutable": { "version": "5.1.2", "resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.1.2.tgz", @@ -4144,6 +4140,28 @@ "markdown-it": "bin/markdown-it.js" } }, + "node_modules/markdown-it-anchor": { + "version": "9.2.0", + "resolved": "https://registry.npmmirror.com/markdown-it-anchor/-/markdown-it-anchor-9.2.0.tgz", + "integrity": "sha512-sa2ErMQ6kKOA4l31gLGYliFQrMKkqSO0ZJgGhDHKijPf0pNFM9vghjAh3gn26pS4JDRs7Iwa9S36gxm3vgZTzg==", + "dev": true, + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/markdown-it-attrs": { + "version": "4.3.1", + "resolved": "https://registry.npmmirror.com/markdown-it-attrs/-/markdown-it-attrs-4.3.1.tgz", + "integrity": "sha512-/ko6cba+H6gdZ0DOw7BbNMZtfuJTRp9g/IrGIuz8lYc/EfnmWRpaR3CFPnNbVz0LDvF8Gf1hFGPqrQqq7De0rg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "markdown-it": ">= 9.0.0" + } + }, "node_modules/markdown-it/node_modules/entities": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/entities/-/entities-3.0.1.tgz", diff --git a/package.json b/package.json index ac9b20f..1d160ff 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,6 @@ "compress-json": "^3.1.1", "cookie-parser": "^1.4.7", "express": "^5.1.0", - "idb": "^8.0.3", "mdui": "^2.1.3", "pinia": "^3.0.2", "vue": "^3.5.13", @@ -26,6 +25,8 @@ "@vitejs/plugin-vue": "^5.2.4", "@vitejs/plugin-vue-jsx": "^4.1.2", "cross-env": "^7.0.3", + "markdown-it-anchor": "^9.2.0", + "markdown-it-attrs": "^4.3.1", "sass": "^1.88.0", "vite": "^6.3.5", "vite-plugin-md": "^0.21.5", diff --git a/src/main.js b/src/main.js index 14e271b..393e59c 100644 --- a/src/main.js +++ b/src/main.js @@ -14,6 +14,7 @@ export function createApp() { app .component('ClientOnly', ClientOnly) .component('Hr', Hr) + .component('BetterHr', Hr) .component('Form', Form) return { app, pinia } } diff --git a/src/router.js b/src/router.js index 484e727..65182fe 100644 --- a/src/router.js +++ b/src/router.js @@ -3,20 +3,40 @@ import { createMemoryHistory, createWebHistory, createRouter } from 'vue-router' export function createSSRRouter() { const router = createRouter({ history: import.meta.env.SSR ? createMemoryHistory() : createWebHistory(), + scrollBehavior(to, from, savedPosition) { + if (savedPosition) { + return savedPosition + } else if (to.hash) { + return { + el: to.hash, + behavior: 'smooth', + } + } else { + return { top: 0 } + } + }, routes: [{ path: '/', name: '前言', component: () => import('./views/Root.vue'), meta: { - title: "首页", + title: '首页', order: 1 }, },{ path: '/work/:id', - name: '阅读', + name: 'work', component: () => import('./views/Work.vue'), meta: { - title: "", + title: '阅读', + hidden: true + } + },{ + path: '/work/:id/:cid', + name: 'workChapter', + component: () => import('./views/Work.vue'), + meta: { + title: '阅读', hidden: true } },{ @@ -24,7 +44,7 @@ export function createSSRRouter() { name: '关于', component: () => import('./views/About.vue'), meta: { - title: "", + title: '', order: 2 }, },{ @@ -32,7 +52,7 @@ export function createSSRRouter() { name: '开发人员选项', component: () => import('./views/Developer.vue'), meta: { - title: "", + title: '', hidden: true }, },{ @@ -40,7 +60,7 @@ export function createSSRRouter() { name: 'NotFound', component: () => import('./views/fallback/NotFound.vue'), meta: { - title: "页面未找到", + title: '页面未找到', hidden: true, code: 404 } diff --git a/src/stores/api.js b/src/stores/api.js index 801c0db..674bc6d 100644 --- a/src/stores/api.js +++ b/src/stores/api.js @@ -102,8 +102,9 @@ export const useApiStore = defineStore('api', () => { inited = false await init() } - async function getWork(workId) { - return await apiGet('work',{ workId }) + async function getWork(workId, chapterId) { + if (chapterId) return await apiGet(`work/${workId}/${chapterId}`) + return await apiGet(`work/${workId}`) } return { init, diff --git a/src/stores/db.js b/src/stores/db.js deleted file mode 100644 index c5ed5cc..0000000 --- a/src/stores/db.js +++ /dev/null @@ -1,58 +0,0 @@ -import { ref } from 'vue' -import { defineStore } from 'pinia' - -import { openDB } from 'idb'; - -export const useDB = defineStore('_db', () => { - const dbPromise = openDB('data', 1, { - upgrade(db) { - const bookmarkStore = db.createObjectStore('bookmarks', { - keyPath: 'id', - autoIncrement: true, - }) - bookmarkStore.createIndex('by-workId', 'workId'); - }, - }) - return { - db: dbPromise - } -}) - -export const useBookmarkStore = defineStore('bookmark', () => { - const db = useDB().db - async function getAll(workId) { - return (await db).getAllFromIndex('bookmarks', 'by-workId', workId); - } - async function get(id) { - return (await db).get('bookmarks', id); - } - async function add(workId, index, para, name ) { - return (await db).add('bookmarks', { - workId, name, para, index - }); - } - async function del(id) { - (await db).delete('bookmarks', id); - } - async function delByWork(workId) { - (await getAll(workId)).forEach(async (item) => { - del(item.id) - }) - } - async function updateName(id, name) { - const raw = await get(id) - if (raw) { - raw.name = name - console.log(name) - await (await db).put('bookmarks', raw); - } - } - return { - get, - add, - del, - getAll, - delByWork, - updateName - } -}) diff --git a/src/stores/workRead.js b/src/stores/workRead.js index dd31188..8897bb3 100644 --- a/src/stores/workRead.js +++ b/src/stores/workRead.js @@ -8,6 +8,7 @@ import { useApiStore } from '@/stores/api.js' export const useWorkReadState = defineStore('workRead', () => { const api = useApiStore() const id = ref(null) + const cid = ref(null) const summary = ref(null) const pesud = ref(null) const title = ref(null) @@ -25,7 +26,7 @@ export const useWorkReadState = defineStore('workRead', () => { title.value = data.title summary.value = [escapeAndFormatText(data.summary)] pesud.value = data.pesud - text.value = data.text.split('\n\n') + text.value = data.text publishedTime.value = data.stats.publishedTime wordCount.value = data.stats.wordCount kudoCount.value = data.stats.kudoCount @@ -34,10 +35,10 @@ export const useWorkReadState = defineStore('workRead', () => { fandom.value = data.fandom lang.value = data.lang } - async function loadWork(target) { - if (target == id.value || state.value == 'loading') return + async function loadWork(target, targetc) { + if (target == id.value && targetc == cid.value || state.value == 'loading') return state.value = 'loading' - const result = await api.getWork(target) + const result = await api.getWork(target, targetc) if (result.status == 200) { setData(result.data) state.value = 'ready' @@ -47,7 +48,7 @@ export const useWorkReadState = defineStore('workRead', () => { } } return { - id, + id, cid, title, summary, pesud, diff --git a/src/texts/about.md b/src/texts/about.md index 21b2cc0..2064b00 100644 --- a/src/texts/about.md +++ b/src/texts/about.md @@ -18,6 +18,13 @@ - Vue 3 [vuejs.org](https://vuejs.org) - Vite 6 [vitejs.dev](https://vite.dev) +废弃特性 +--- + +### 书签 {#deprecated-feature-bookmark} + +因为底层 IndexedDB 更新困难和作品段落解析困难问题, 所以在 **v1.0.7** 以后的版本废弃了书签机制 + 其他 --- 本站支持 "Server Side Rendering" by Vite SSR diff --git a/src/texts/intro.md b/src/texts/intro.md index a0bc902..57d36cc 100644 --- a/src/texts/intro.md +++ b/src/texts/intro.md @@ -14,17 +14,24 @@ 现在这个站点还处于测试阶段, 只有一种使用方法 *(后面会扩展)* -首先你需要一个 AO3 链接 +首先你需要一个 AO3 链接 (或者数字 ID) 比如: https://archiveofourown.org/works/114514 +带章节的话就是 + + https://archiveofourown.org/works/114514/chapters/1919810 + + 接着将前面的部分替换为本站点的链接 (保留数字ID部分): 即: https://ao3.unknownmp.top/work/114514 -这里的数字ID即为`114514` +章节: + + https://ao3.unknownmp.top/work/114514/1919810 浏览器打开它, OK 你会用了🤓👆! @@ -33,7 +40,7 @@ ## 功能与特性 🤗 - ✅ 预览 -- ✅ 书签 (本地) -- 📝 历史记录 (本地) +- ✅ 作品详细数据 - 📝 搜索 +- ❌ 不再支持! [详情](/about#deprecated-feature-bookmark) 书签 (本地) diff --git a/src/ui/BetterHr.vue b/src/ui/BetterHr.vue index c0caf6d..d1c785b 100644 --- a/src/ui/BetterHr.vue +++ b/src/ui/BetterHr.vue @@ -5,7 +5,6 @@ defineProps(['class']) // 接收外部 class 属性