Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
9ef6da3efb | |||
2aea1eae7f | |||
063a1330d7 | |||
0607e6241b | |||
89538823fc |
@ -33,9 +33,9 @@ if (!isProduction) {
|
||||
})
|
||||
app.use(vite.middlewares)
|
||||
} else {
|
||||
const compression = (await import('compression')).default
|
||||
//const compression = (await import('compression')).default
|
||||
const sirv = (await import('sirv')).default
|
||||
app.use(compression())
|
||||
//app.use(compression())
|
||||
app.use(base, sirv('./dist/client', { extensions: [] }))
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,7 @@ onMounted(async () => {
|
||||
<li v-for="item in routeStore.allRoutes"
|
||||
:key="item.path"
|
||||
:class="{ 'active-item' : item.path == $route.path }"
|
||||
>{{ item.name }}</li>
|
||||
><a :href="item.path">{{ item.name }}</a></li>
|
||||
</ul>
|
||||
</template></ClientOnly>
|
||||
</nav>
|
||||
|
@ -5,6 +5,7 @@ import App from './App.vue'
|
||||
|
||||
import ClientOnly from './ssr/ClientOnly.vue'
|
||||
import Hr from './ui/BetterHr.vue'
|
||||
import Form from './ui/Form.vue'
|
||||
|
||||
export function createApp() {
|
||||
const app = createSSRApp(App)
|
||||
@ -13,5 +14,6 @@ export function createApp() {
|
||||
app
|
||||
.component('ClientOnly', ClientOnly)
|
||||
.component('Hr', Hr)
|
||||
.component('Form', Form)
|
||||
return { app, pinia }
|
||||
}
|
||||
|
@ -21,8 +21,8 @@ body {
|
||||
|
||||
// MDUI 组件样式
|
||||
mdui-card {
|
||||
width: 100%;
|
||||
padding: 0 16px 16px;
|
||||
width: 98%;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
mdui-text-field {
|
||||
|
@ -12,14 +12,27 @@ export const useWorkReadState = defineStore('workRead', () => {
|
||||
const pesud = ref(null)
|
||||
const title = ref(null)
|
||||
const text = ref(null)
|
||||
const publishedTime = ref(null)
|
||||
const state = ref('')
|
||||
const publishedTime = ref(null)
|
||||
const wordCount = ref(0)
|
||||
const kudoCount = ref(0)
|
||||
const hitCount = ref(0)
|
||||
const category = ref([])
|
||||
const fandom = ref([])
|
||||
const lang = ref(null)
|
||||
function setData(data) {
|
||||
id.value = data.workId
|
||||
title.value = data.title
|
||||
summary.value = [escapeAndFormatText(data.summary)]
|
||||
pesud.value = data.pesud
|
||||
text.value = data.text.split('\n\n')
|
||||
publishedTime.value = data.stats.publishedTime
|
||||
wordCount.value = data.stats.wordCount
|
||||
kudoCount.value = data.stats.kudoCount
|
||||
hitCount.value = data.stats.hitCount
|
||||
category.value = data.category
|
||||
fandom.value = data.fandom
|
||||
lang.value = data.lang
|
||||
}
|
||||
async function loadWork(target) {
|
||||
if (target == id.value || state.value == 'loading') return
|
||||
@ -39,8 +52,14 @@ export const useWorkReadState = defineStore('workRead', () => {
|
||||
summary,
|
||||
pesud,
|
||||
text,
|
||||
publishedTime,
|
||||
state,
|
||||
publishedTime,
|
||||
wordCount,
|
||||
kudoCount,
|
||||
hitCount,
|
||||
category,
|
||||
fandom,
|
||||
lang,
|
||||
setData,
|
||||
loadWork
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
---
|
||||
- MDUI 2 [mdui.org](https://mdui.org)
|
||||
- Vue 3 [vuejs.org](https://vuejs.org)
|
||||
- Vite 6 [vitejs.dev](https://vitejs.dev)
|
||||
- Vite 6 [vitejs.dev](https://vite.dev)
|
||||
|
||||
其他
|
||||
---
|
||||
|
@ -1,8 +1,16 @@
|
||||
<script setup>import 'mdui/components/divider.js'</script>
|
||||
<script setup>
|
||||
import 'mdui/components/divider.js'
|
||||
defineProps(['class']) // 接收外部 class 属性
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ClientOnly><mdui-divider class='hr-divider'></mdui-divider>
|
||||
<template #ssr><hr/></template></ClientOnly>
|
||||
<ClientOnly>
|
||||
<!-- 将 class 传入 mdui-divider 中 -->
|
||||
<mdui-divider :class="['hr-divider', $attrs.class]"></mdui-divider>
|
||||
<template #ssr><hr :class="['hr-divider', $attrs.class]" /></template>
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.hr-divider {
|
||||
margin: 8px 0px;
|
||||
|
20
src/ui/Form.vue
Normal file
20
src/ui/Form.vue
Normal file
@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<form @submit="handleSubmit">
|
||||
<slot></slot>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const emit = defineEmits(['submit'])
|
||||
|
||||
function handleSubmit(event) {
|
||||
event.preventDefault()
|
||||
const form = event.target
|
||||
const formData = new FormData(form)
|
||||
const data = Object.fromEntries(formData.entries())
|
||||
emit('submit', data, event)
|
||||
}
|
||||
</script>
|
||||
|
@ -9,13 +9,13 @@ import Intro from '../texts/intro.md'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const src = ref('')
|
||||
const srcText = ref(null)
|
||||
const err = ref(false)
|
||||
const srcText = ref(null)
|
||||
|
||||
function convert(from) {
|
||||
if( Number(from) ) {
|
||||
return {
|
||||
type: 's',
|
||||
id: Number(from)
|
||||
}
|
||||
} else if (from.includes('https://archiveofourown.org/works/')) {
|
||||
@ -35,9 +35,10 @@ function convert(from) {
|
||||
}
|
||||
}
|
||||
|
||||
function onConvert() {
|
||||
const { id, cid } = convert(src.value)
|
||||
if (id == null) {
|
||||
function onConvert(data) {
|
||||
const { type, id, cid } = convert(data.src)
|
||||
console.log(type, id, cid)
|
||||
if (type == null) {
|
||||
err.value = true
|
||||
srcText.value?.focus()
|
||||
} else {
|
||||
@ -56,17 +57,17 @@ function onConvert() {
|
||||
<section id="converter">
|
||||
<h2>链接转换</h2>
|
||||
<p>输入完整链接或者 ID</p>
|
||||
<ClientOnly>
|
||||
<mdui-text-field variant="filled" label="链接" placeholder="https://archiveofourown.org/works/114514" @input="src = $event.target.value" ref='srcText'>
|
||||
<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><br/>
|
||||
<div style="display: flex">
|
||||
<div style="flex-grow: 1"></div>
|
||||
<mdui-button @click='onConvert'>-></mdui-button>
|
||||
<mdui-button type="submit">-></mdui-button>
|
||||
</div>
|
||||
{{ src }}
|
||||
<template #ssr>
|
||||
Padding...
|
||||
</template></ClientOnly>
|
||||
<input type="text" id="src" name="src" />
|
||||
<input type="submit" />
|
||||
</template></ClientOnly></Form>
|
||||
</section>
|
||||
</template>
|
||||
|
@ -22,6 +22,9 @@ import 'mdui/components/button.js'
|
||||
import 'mdui/components/dropdown.js'
|
||||
import 'mdui/components/menu.js'
|
||||
import 'mdui/components/menu-item.js'
|
||||
import 'mdui/components/collapse.js'
|
||||
import 'mdui/components/collapse-item.js'
|
||||
import 'mdui/components/card.js'
|
||||
|
||||
import '@mdui/icons/bookmark.js'
|
||||
|
||||
@ -47,6 +50,12 @@ let bookmarkStore = null
|
||||
let paragraphs = []
|
||||
let currentParagraph = null
|
||||
|
||||
const categoryName = {
|
||||
mm: "男/男",
|
||||
ff: "女/女",
|
||||
fm: '女/男'
|
||||
}
|
||||
|
||||
async function addBookmark() {
|
||||
if (currentParagraph) {
|
||||
const id = await bookmarkStore.add(workReadState.id, readIndex, currentParagraph.textContent.slice(0,20), '')
|
||||
@ -120,7 +129,7 @@ function openBookmarkMenu(bk, index) {
|
||||
async function deleteBookmark() {
|
||||
if (bookmarkSelect.value) {
|
||||
bookmarkStore.del(bookmarkSelect.value.bk.id)
|
||||
bookmarks.value.splice(bookmarkSelect.value.index)
|
||||
bookmarks.value.splice(bookmarkSelect.value.index,1)
|
||||
bookmarkSelect.value = null
|
||||
}
|
||||
}
|
||||
@ -187,10 +196,42 @@ onBeforeUnmount(() => {
|
||||
<article>
|
||||
<h1 style="margin: auto">{{ workReadState.title }}</h1>
|
||||
<h4>{{ workReadState.pesud }}</h4>
|
||||
<mdui-card style="margin: 8px; padding: 0px;"><mdui-collapse acc>
|
||||
<mdui-collapse-item value="info"><mdui-list-item class="infoblockhead" slot="header">
|
||||
作品信息
|
||||
</mdui-list-item><div class="infoblock"><dl>
|
||||
<dt>分类</dt><ul>
|
||||
<li v-for="item in workReadState.category" :key="item">
|
||||
{{ categoryName[item] }}</li>
|
||||
</ul>
|
||||
<dt>原著</dt><ul>
|
||||
<li v-for="item in workReadState.fandom" :key="item">
|
||||
{{ item }}</li>
|
||||
</ul>
|
||||
<dt>语言</dt><dd>
|
||||
{{ workReadState.lang }}
|
||||
</dd>
|
||||
</dl></div></mdui-collapse-item>
|
||||
<mdui-collapse-item value="stats"><mdui-list-item class="infoblockhead" slot="header">
|
||||
作品状态
|
||||
</mdui-list-item><div class="infoblock"><dl>
|
||||
<dt>发布时间</dt><dd>
|
||||
{{ workReadState.publishedTime.year }} -
|
||||
{{ workReadState.publishedTime.month }} -
|
||||
{{ workReadState.publishedTime.date }}
|
||||
</dd>
|
||||
<dt>字数</dt><dd>
|
||||
{{ workReadState.wordCount }}
|
||||
</dd>
|
||||
<dt>点击</dt><dd>
|
||||
{{ workReadState.hitCount }}
|
||||
</dd>
|
||||
</dl></div></mdui-collapse-item>
|
||||
</mdui-collapse></mdui-card>
|
||||
<blockquote>
|
||||
<p v-for="para in workReadState.summary" :key="para" v-html='para'></p>
|
||||
</blockquote>
|
||||
<Hr/>
|
||||
<Hr />
|
||||
<div ref='content'>
|
||||
<p v-for="(para, index) in workReadState.text" :key="para" :data-index="index">{{ para }}</p>
|
||||
</div>
|
||||
@ -237,6 +278,31 @@ onBeforeUnmount(() => {
|
||||
<template v-if="workReadState.state == 'ready'">
|
||||
<h1>{{ workReadState.title }}</h1>
|
||||
<h2>{{ workReadState.pesud }}</h2>
|
||||
<dl>
|
||||
<dt>分类</dt><ul>
|
||||
<li v-for="item in workReadState.category" :key="item">
|
||||
{{ categoryName[item] }}</li>
|
||||
</ul>
|
||||
<dt>原著</dt><ul>
|
||||
<li v-for="item in workReadState.fandom" :key="item">
|
||||
{{ item }}</li>
|
||||
</ul>
|
||||
<dt>语言</dt><dd>
|
||||
{{ workReadState.lang }}
|
||||
</dd>
|
||||
<dt>发布时间</dt><dd>
|
||||
{{ workReadState.publishedTime.year }} -
|
||||
{{ workReadState.publishedTime.month }} -
|
||||
{{ workReadState.publishedTime.date }}
|
||||
</dd>
|
||||
<dt>字数</dt><dd>
|
||||
{{ workReadState.wordCount }}
|
||||
</dd>
|
||||
<dt>点击</dt><dd>
|
||||
{{ workReadState.hitCount }}
|
||||
</dd>
|
||||
</dl>
|
||||
<Hr />
|
||||
<blockquote>
|
||||
<p v-for="para in workReadState.summary" :key="para" v-html='para'></p>
|
||||
</blockquote>
|
||||
@ -254,4 +320,12 @@ onBeforeUnmount(() => {
|
||||
z-index: 1000; /* 确保悬浮按钮在其他内容上方 */
|
||||
animation: slideInFromRight var(--mdui-motion-duration-medium2) var(--mdui-motion-easing-standard); /* 动画时长和缓动效果 */
|
||||
}
|
||||
|
||||
.infoblock {
|
||||
margin: 8px 16px;
|
||||
}
|
||||
|
||||
.infoblockhead {
|
||||
background-color: rgb(var(--mdui-color-primary-container));
|
||||
}
|
||||
</style>
|
||||
|
@ -19,8 +19,11 @@ export default defineConfig({
|
||||
}),
|
||||
vueJsx(),
|
||||
vueDevTools(),
|
||||
markdown()
|
||||
|
||||
markdown({
|
||||
markdownItSetup(md) {
|
||||
md.renderer.rules.hr = () => "<Hr />"
|
||||
}
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
|
Reference in New Issue
Block a user