更新了搜索功能 (终于!) 1.1.0 版本 Release!
All checks were successful
Build / build-and-test (push) Successful in 33s

This commit is contained in:
2025-05-26 11:23:24 +08:00
parent eb5b28249f
commit f5d3e7ea88
10 changed files with 160 additions and 47 deletions

62
src/views/About.md Normal file
View File

@ -0,0 +1,62 @@
<script setup>
import About from '../texts/about.md'
import FunAnimation from '../components/FunAnimation.vue'
import 'mdui/components/avatar.js'
/*import { onBeforeMount, onMounted, onUnmounted, onBeforeUnmount, onActivated, onDeactivated } from 'vue'
console.log('Setup')
onBeforeMount(() => console.log('Before mount'))
onMounted(() => console.log('Mounted'))
onDeactivated(() => console.log('Deactivated'))
onActivated(() => console.log('Activated'))
onBeforeUnmount(() => console.log('Before unmount'))
onUnmounted(() => console.log('Unmounted'))*/
</script>
# 关于
这是什么, 有口舍用 ?
概述
---
一个 AO3 镜像站, 优化了 UI/UX
作者 (1)
---
- [UnknownMp](https://www.unknownmp.top)
<mdui-avatar src="https://cdn.unknownmp.top/website/logo.jpg"></mdui-avatar>
---
源代码
---
- 前端 Vue3 + Vite 6 (SSR) + MDUI 2 [Gitea](https://git.unknownmp.top/default/ao3-mirror-ssr)
- 后端 FastAPI + HttpX + LXML *(暂无仓库)*
组件库与工具链
---
### 前端
- MDUI 2 [mdui.org](https://mdui.org)
- Vue 3 [vuejs.org](https://vuejs.org)
- Vite 6 [vite.dev](https://vite.dev)
### 后端
- FastAPI [fastapi.tiangolo.com](https://fastapi.tiangolo.com/)
- HttpX [python-httpx.org](https://www.python-httpx.org/)
- LXML [lxml.de](https://lxml.de/)
废弃特性 {#deprecated}
---
### 书签 {#deprecated-feature-bookmark}
因为底层 IndexedDB 更新困难和作品段落解析困难问题, 所以在 [**v1.0.7**](https://git.unknownmp.top/default/ao3-mirror-ssr/releases/tag/v1.0.7) 以后的版本废弃了书签机制
---
其他
---
本站支持 "Server Side Rendering" by Vite SSR
CDN by Cloudflare (赛博佛祖😭)
<FunAnimation />

View File

@ -1,19 +0,0 @@
<script setup>
import About from '../texts/about.md'
import FunAnimation from '../components/FunAnimation.vue'
import 'mdui/components/avatar.js'
/*import { onBeforeMount, onMounted, onUnmounted, onBeforeUnmount, onActivated, onDeactivated } from 'vue'
console.log('Setup')
onBeforeMount(() => console.log('Before mount'))
onMounted(() => console.log('Mounted'))
onDeactivated(() => console.log('Deactivated'))
onActivated(() => console.log('Activated'))
onBeforeUnmount(() => console.log('Before unmount'))
onUnmounted(() => console.log('Unmounted'))*/
</script>
<template>
<About/>
<FunAnimation />
</template>

View File

@ -9,9 +9,6 @@ import Intro from '../texts/intro.md'
const router = useRouter()
const err = ref(false)
const srcText = ref(null)
function convert(from) {
if( Number(from) ) {
return {
@ -20,7 +17,6 @@ function convert(from) {
}
} else if (from.includes('https://archiveofourown.org/works/')) {
const sid = from.split('https://archiveofourown.org/works/')[1];
console.log(sid)
if ( sid ) {
const id = Number(sid)
if (id) {
@ -41,16 +37,15 @@ function convert(from) {
}
}
}
return { type: null }
return { type: 'f', key: from }
}
function onConvert(data) {
const { type, id, cid } = convert(data.src)
const { type, id, cid, key } = convert(data.src)
if (type == null) {
err.value = true
srcText.value?.focus()
} else if ( type == 'f') {
router.push(`/search/simple?keyword=${encodeURIComponent(key)}`)
} else {
err.value = false
if (cid) router.push(`/work/${id}/${cid}`)
else router.push(`/work/${id}`)
}
@ -60,14 +55,14 @@ function onConvert(data) {
<template>
<img style="display: block; margin: 0px auto 10px;" height="200px" alt="logo" src="/favicon.svg" />
<Intro />
<br/><Hr/>
<h1>欢迎来到 AO3 Mirror! 👋👋</h1>
<p>一个基于重构渲染的 AO3 镜像站</p>
<Hr />
<section id="converter">
<h2>链接转换</h2>
<p>输入完整链接或者 ID</p>
<p>AO3 链接 关键词搜索</p>
<Form @submit="onConvert"><ClientOnly>
<mdui-text-field variant="filled" label="链接" name="src" placeholder="https://archiveofourown.org/works/114514" ref='srcText'>
<span v-if='err' slot="helper" class='warn-text'>链接格式错误!</span>
<mdui-text-field variant="filled" label="链接 / 关键词" name="src">
</mdui-text-field><br/>
<div style="display: flex">
<div style="flex-grow: 1"></div>
@ -78,4 +73,7 @@ function onConvert(data) {
<input type="submit" />
</template></ClientOnly></Form>
</section>
<Hr/>
<Intro />
</template>

View File

@ -0,0 +1,62 @@
<script setup>
import { ref, onMounted, onServerPrefetch } from 'vue'
import { useRoute } from 'vue-router'
import 'mdui/components/text-field.js'
import 'mdui/components/card.js'
import { escapeAndFormatText } from '../utils.js'
import { useSimpleSearchState } from '../stores/search.js'
const route = useRoute()
const inputField = ref('')
const simpleSearchState = useSimpleSearchState()
onServerPrefetch(async () => {
if (route.query.keyword) {
await simpleSearchState.start(route.query.keyword)
}
console.log(simpleSearchState.result[0])
})
onMounted(() => {
inputField.value = route.query.keyword || ''
if (inputField.value && simpleSearchState != 'ssrready') simpleSearchState.start(inputField.value)
})
function onSubmit(data) {
if (simpleSearchState) simpleSearchState.start(data.src)
}
</script>
<template>
<h1>搜索</h1>
<Form @submit="onSubmit"><ClientOnly>
<mdui-text-field variant="filled" :value="inputField" label="链接 / 关键词" name="src">
</mdui-text-field><br/>
<div style="display: flex">
<div style="flex-grow: 1"></div>
<mdui-button type="submit">-></mdui-button>
</div>
<template #ssr>
<input type="text" id="src" name="src" />
<input type="submit" />
</template></ClientOnly></Form><Hr />
<p>State: {{ simpleSearchState.state }}</p><Hr/>
<template v-if="simpleSearchState.result" v-for="work in simpleSearchState.result" :key="work.workId">
<ClientOnly><mdui-card style="margin: 8px 0px;"><article>
<router-link :to="`/work/${work.workId}`"><h3>{{ work.title }}</h3></router-link>
<h4>{{ work.pseud }}</h4>
<Hr />
<p v-html="escapeAndFormatText(work.summary)"></p>
</article></mdui-card><template #ssr>
<router-link :to="`/work/${work.workId}`"><h3>{{ work.title }}</h3></router-link>
<h4>{{ work.pseud }}</h4>
<p>{{ work.summary }}</p>
<Hr />
</template></ClientOnly>
</template>
</template>

View File

@ -168,8 +168,8 @@ onBeforeUnmount(() => {
<a @click="$router.back()">返回</a>
</template>
<template v-if="workReadState.state == 'ready'">
<h1>{{ workReadState.title }}</h1>
<h2>{{ workReadState.pesud }}</h2>
<h2>{{ workReadState.title }}</h2>
<h4>{{ workReadState.pesud }}</h4>
<dl>
<template v-if="workReadState.category"><dt>作品圈</dt><ul>
<li v-for="item in workReadState.category" :key="item">