mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-05-09 12:17:29 +08:00
Merge branch 'main' of github.com:nagisa77/OpenIsle
This commit is contained in:
33
backend/open-isle.env.example
Normal file
33
backend/open-isle.env.example
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# === Database ===
|
||||||
|
MYSQL_URL=jdbc:mysql://<数据库地址>:<端口>/<数据库名>?useUnicode=yes&characterEncoding=UTF-8&useInformationSchema=true&useSSL=false&serverTimezone=UTC
|
||||||
|
MYSQL_USER=<数据库用户名>
|
||||||
|
MYSQL_PASSWORD=<数据库密码>
|
||||||
|
|
||||||
|
|
||||||
|
# === Resend ===
|
||||||
|
RESEND_API_KEY=<你的resend-api-key>
|
||||||
|
|
||||||
|
# === COS ===
|
||||||
|
# COS_BASE_URL=https://<你的cos>.cos.ap-guangzhou.myqcloud.com
|
||||||
|
COS_BASE_URL=https://<你的cos>.cos.accelerate.myqcloud.com
|
||||||
|
COS_SECRET_ID=<你的cos-secret-id>
|
||||||
|
COS_SECRET_KEY=<你的cos-secret-key>
|
||||||
|
COS_BUCKET_NAME=<你的cos-bucket-name>
|
||||||
|
|
||||||
|
# === OAuth ===
|
||||||
|
GOOGLE_CLIENT_ID=<你的google-client-id>
|
||||||
|
GITHUB_CLIENT_ID=<你的github-client-id>
|
||||||
|
GITHUB_CLIENT_SECRET=<你的github-client-secret>
|
||||||
|
TWITTER_CLIENT_ID=<你的twitter-client-id>
|
||||||
|
TWITTER_CLIENT_SECRET=<你的-twitter-client-secret>
|
||||||
|
DISCORD_CLIENT_ID=<你的discord-client-id>
|
||||||
|
DISCORD_CLIENT_SECRET=<你的discord-client-secret>
|
||||||
|
|
||||||
|
# === OPENAI ===
|
||||||
|
OPENAI_API_KEY=<你的openai-api-key>
|
||||||
|
|
||||||
|
# === Webpush ===
|
||||||
|
WEBPUSH_PUBLIC_KEY=<你的webpush-public-key>
|
||||||
|
WEBPUSH_PRIVATE_KEY=<你的webpush-private-key>
|
||||||
|
|
||||||
|
# LOG_LEVEL=DEBUG
|
||||||
@@ -9,7 +9,12 @@
|
|||||||
<MenuComponent :visible="!hideMenu && menuVisible" @item-click="menuVisible = false" />
|
<MenuComponent :visible="!hideMenu && menuVisible" @item-click="menuVisible = false" />
|
||||||
</div>
|
</div>
|
||||||
<div class="content" :class="{ 'menu-open': menuVisible && !hideMenu }">
|
<div class="content" :class="{ 'menu-open': menuVisible && !hideMenu }">
|
||||||
<router-view />
|
<router-view v-slot="{ Component }">
|
||||||
|
<keep-alive>
|
||||||
|
<component :is="Component" v-if="$route.meta.keepAlive" />
|
||||||
|
</keep-alive>
|
||||||
|
<component :is="Component" v-if="!$route.meta.keepAlive" />
|
||||||
|
</router-view>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<GlobalPopups />
|
<GlobalPopups />
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ const routes = [
|
|||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
component: HomePageView
|
component: HomePageView,
|
||||||
|
meta: { keepAlive: true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/message',
|
path: '/message',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="home-page" @scroll="handleScroll">
|
<div ref="homePage" class="home-page" @scroll="handleScroll">
|
||||||
<div v-if="!isMobile" class="search-container">
|
<div v-if="!isMobile" class="search-container">
|
||||||
<div class="search-title">一切可能,从此刻启航</div>
|
<div class="search-title">一切可能,从此刻启航</div>
|
||||||
<div class="search-subtitle">愿你在此遇见灵感与共鸣。若有疑惑,欢迎发问,亦可在知识的海洋中搜寻答案。</div>
|
<div class="search-subtitle">愿你在此遇见灵感与共鸣。若有疑惑,欢迎发问,亦可在知识的海洋中搜寻答案。</div>
|
||||||
@@ -107,7 +107,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ref, onMounted, watch } from 'vue'
|
import { ref, onMounted, watch, onActivated, nextTick } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { stripMarkdown } from '../utils/markdown'
|
import { stripMarkdown } from '../utils/markdown'
|
||||||
import { API_BASE_URL } from '../main'
|
import { API_BASE_URL } from '../main'
|
||||||
@@ -134,6 +134,8 @@ export default {
|
|||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const homePage = ref(null)
|
||||||
|
const savedScrollTop = ref(0)
|
||||||
const selectedCategory = ref('')
|
const selectedCategory = ref('')
|
||||||
if (route.query.category) {
|
if (route.query.category) {
|
||||||
const c = decodeURIComponent(route.query.category)
|
const c = decodeURIComponent(route.query.category)
|
||||||
@@ -165,6 +167,14 @@ export default {
|
|||||||
const pageSize = 10
|
const pageSize = 10
|
||||||
const allLoaded = ref(false)
|
const allLoaded = ref(false)
|
||||||
|
|
||||||
|
onActivated(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
if (homePage.value) {
|
||||||
|
homePage.value.scrollTop = savedScrollTop.value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
const countComments = (list) =>
|
const countComments = (list) =>
|
||||||
list.reduce((sum, c) => sum + 1 + countComments(c.replies || []), 0)
|
list.reduce((sum, c) => sum + 1 + countComments(c.replies || []), 0)
|
||||||
|
|
||||||
@@ -359,6 +369,7 @@ export default {
|
|||||||
|
|
||||||
const handleScroll = (e) => {
|
const handleScroll = (e) => {
|
||||||
const el = e.target
|
const el = e.target
|
||||||
|
savedScrollTop.value = el.scrollTop
|
||||||
if (el.scrollHeight - el.scrollTop <= el.clientHeight + 50) {
|
if (el.scrollHeight - el.scrollTop <= el.clientHeight + 50) {
|
||||||
fetchContent()
|
fetchContent()
|
||||||
}
|
}
|
||||||
@@ -379,7 +390,7 @@ export default {
|
|||||||
|
|
||||||
const sanitizeDescription = (text) => stripMarkdown(text)
|
const sanitizeDescription = (text) => stripMarkdown(text)
|
||||||
|
|
||||||
return { topics, selectedTopic, articles, sanitizeDescription, isLoadingPosts, handleScroll, selectedCategory, selectedTags, tagOptions, categoryOptions, isMobile }
|
return { topics, selectedTopic, articles, sanitizeDescription, isLoadingPosts, handleScroll, selectedCategory, selectedTags, tagOptions, categoryOptions, isMobile, homePage }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user