Skip to content

Commit

Permalink
feat: 在线分享第一版-完成设置页面
Browse files Browse the repository at this point in the history
  • Loading branch information
terwer committed Jun 19, 2023
1 parent 30b3e85 commit 9911274
Show file tree
Hide file tree
Showing 19 changed files with 408 additions and 60 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ The notions sharing function you want is here too
* [ ] Latex formula rendering
* [ ] PlantUML chart support
* [ ] Echarts chart support
* [ ] Support for SVG with the ribbon, eg `<use xlink:href="#iconMore"></use>`

## Changelog

Expand Down
3 changes: 2 additions & 1 deletion README_zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
- **一键分享**:支持一键分享文档到局域网,如果需要远程分享,可使用 docker 部署在服务器,然后安装插件
- **权限控制**:只能查看已分享的页面,未分享的页面无权限查看
- **个人主页**:支持设置已分享的某个页面为主页,可作为自定义博客主页
- **主题集成**:默认集成 [Zhihu](https://github.com/terwer/siyuan-theme-zhihu) 主题,后续可支持切换其他主题
- **主题集成**:默认集成 默认主题 和 [Zhihu](https://github.com/terwer/siyuan-theme-zhihu) 主题,后续可支持切换其他主题
- **SEO优化**:支持自动生成标题、摘要、首图,便于SEO
- **多种部署**:支持思源笔记插件、docker自部署、Vercel托管满足各种人群的需求,详情请看 [docs](./docs.md)
- [入门级]思源笔记插件:零配置,开箱即用,本地SPA应用,直接访问思源本体,因此速度极快,但是SEO不太友好
Expand All @@ -34,6 +34,7 @@
- [ ] Latex 公式渲染
- [ ] plantuml 图表支持
- [ ] echats 图表支持
- [ ] 支持思源自带的svg,例如 `<use xlink:href="#iconMore"></use>`

## 更新历史

Expand Down
3 changes: 3 additions & 0 deletions app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
type ThemeType = "system" | "dark" | "light"

interface AppConfig {
lang?: string
siteTitle?: string
siteSlogan?: string
siteDescription?: string
homePageId?: string

theme?: {
mode?: ThemeType
Expand All @@ -41,6 +43,7 @@ interface AppConfig {
}

export default defineAppConfig<AppConfig>({
lang: "zh_CN",
siteTitle: "浅海拾贝",
siteSlogan: "寻找未知的技术拼图",
siteDescription: "专注于Java后端开发及服务端、软件架构、微服务、自然语言处理等领域的技术分享。",
Expand Down
45 changes: 26 additions & 19 deletions components/default/Detail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,31 +29,39 @@ import { getFirstImageSrc, getSummery } from "~/utils/utils"
import { createAppLogger } from "~/common/appLogger"
const logger = createAppLogger("share-page")
const { t } = useI18n()
const { currentPost, setCurrentPost } = usePost()
await setCurrentPost()
// props
const props = defineProps({
showTitleSign: Boolean,
overrideSeo: Boolean,
pageId: {
type: String,
default: undefined,
},
})
const { t } = useI18n()
const { currentPost, setCurrentPost } = usePost()
await setCurrentPost(props.pageId)
// datas
const titleSign = " - " + t("blog.share")
const title = `${currentPost.post.title}${props.showTitleSign ? titleSign : ""}`
const desc = getSummery(currentPost.post.description)
const headImage = await getFirstImageSrc(currentPost.post.description)
const seoMeta = {
title: title,
ogTitle: title,
description: desc,
ogDescription: desc,
} as any
if (headImage) {
logger.info("get a head image from doc=>", headImage)
seoMeta.ogImage = headImage
if (!props.overrideSeo) {
const titleSign = " - " + t("blog.share")
const title = `${currentPost.post.title}${props.showTitleSign ? titleSign : ""}`
const desc = getSummery(currentPost.post.description)
const headImage = await getFirstImageSrc(currentPost.post.description)
const seoMeta = {
title: title,
ogTitle: title,
description: desc,
ogDescription: desc,
} as any
if (headImage) {
logger.info("get a head image from doc=>", headImage)
seoMeta.ogImage = headImage
}
useSeoMeta(seoMeta)
}
useSeoMeta(seoMeta)
// https://stackoverflow.com/a/71781246/4037224
const VNode = () =>
Expand All @@ -66,9 +74,8 @@ const VNode = () =>
<template>
<div class="fn__flex-1 protyle" data-loading="finished">
<div class="protyle-content protyle-content--transition" data-fullwidth="true">
<div class="protyle-title protyle-wysiwyg--attr" style="margin: 16px 96px 0">
<div class="protyle-title protyle-wysiwyg--attr">
<div
style="margin: 20px 0"
contenteditable="false"
data-position="center"
spellcheck="false"
Expand Down
113 changes: 113 additions & 0 deletions components/default/setting/Basic.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<!--
- Copyright (c) 2023, Terwer . All rights reserved.
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
- This code is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License version 2 only, as
- published by the Free Software Foundation. Terwer designates this
- particular file as subject to the "Classpath" exception as provided
- by Terwer in the LICENSE file that accompanied this code.
-
- This code is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- version 2 for more details (a copy is included in the LICENSE file that
- accompanied this code).
-
- You should have received a copy of the GNU General Public License version
- 2 along with this work; if not, write to the Free Software Foundation,
- Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
- Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com
- or visit www.terwer.space if you need additional information or have any
- questions.
-->

<script setup lang="ts">
import { useSettingStore } from "~/stores/useSettingStore"
import { createAppLogger } from "~/common/appLogger"
const logger = createAppLogger("setting-page")
const { t } = useI18n()
const { getSetting, updateSetting } = useSettingStore()
const setting = await getSetting()
const title = `${t("blog.share")} - ${t("blog.share.setting")}`
const seoMeta = {
title: title,
ogTitle: title,
} as any
useSeoMeta(seoMeta)
// datas
const formData = reactive({
homePageId: setting.homePageId,
themes: {
light: [
{
value: "daylight",
label: "daylight",
},
{
value: "Zhihu",
label: "Zhihu",
},
],
dark: [
{
value: "midlight",
label: "midlight",
},
{
value: "Zhihu",
label: "Zhihu",
},
],
},
lightTheme: setting?.theme?.lightTheme ?? "Zhihu",
darkTheme: setting?.theme?.darkTheme ?? "Zhihu",
})
// methods
const onSubmit = async () => {
try {
setting.homePageId = formData.homePageId
setting.theme ||= {}
setting.theme.lightTheme = formData.lightTheme
setting.theme.darkTheme = formData.darkTheme
await updateSetting(setting)
ElMessage.success(t("main.opt.success"))
} catch (e) {
logger.error(t("main.opt.failure"), e)
ElMessage({
type: "error",
message: t("main.opt.failure") + e,
})
}
}
</script>

<template>
<div class="basic-setting">
<el-form label-width="85px">
<el-form-item :label="t('setting.basic.homePageId')">
<el-input v-model="formData.homePageId" />
</el-form-item>
<el-form-item :label="t('siyuan.theme.light')">
<el-select v-model="formData.lightTheme" class="m-2" :placeholder="t('siyuan.theme.select')">
<el-option v-for="item in formData.themes.light" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item :label="t('siyuan.theme.dark')">
<el-select v-model="formData.darkTheme" class="m-2" :placeholder="t('siyuan.theme.select')">
<el-option v-for="item in formData.themes.dark" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">{{ t("main.opt.save") }}</el-button>
</el-form-item>
</el-form>
</div>
</template>

<style scoped></style>
74 changes: 74 additions & 0 deletions components/default/setting/ChangeLocal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<!--
- Copyright (c) 2022-2023, Terwer . All rights reserved.
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
- This code is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License version 2 only, as
- published by the Free Software Foundation. Terwer designates this
- particular file as subject to the "Classpath" exception as provided
- by Terwer in the LICENSE file that accompanied this code.
-
- This code is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- version 2 for more details (a copy is included in the LICENSE file that
- accompanied this code).
-
- You should have received a copy of the GNU General Public License version
- 2 along with this work; if not, write to the Free Software Foundation,
- Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
- Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com
- or visit www.terwer.space if you need additional information or have any
- questions.
-->

<script lang="ts" setup>
import { useI18n } from "vue-i18n"
import { useSettingStore } from "~/stores/useSettingStore"
import { createAppLogger } from "~/common/appLogger"
const logger = createAppLogger("change-local")
const { getSetting, updateSetting } = useSettingStore()
const { t, locale } = useI18n()
const langs = [
{
value: "zh_CN",
label: "简体中文",
},
{
value: "en_US",
label: "English",
},
]
const setting = await getSetting()
const langChanged = async (lang: string) => {
locale.value = lang
setting.lang = lang
await updateSetting(setting)
logger.info("lang changed to", lang)
}
// lifecycles
onBeforeMount(() => {
// 设置默认语言
if (setting?.lang) {
locale.value = setting?.lang
}
})
</script>

<template>
<div class="locale-changer">
<el-form label-width="85px">
<!-- 语言选项 -->
<el-form-item :label="t('lang.choose')">
<el-select v-model="locale" :placeholder="t('lang.choose.placeholder')" @change="langChanged">
<el-option v-for="(lang, i) in langs" :key="i" :label="lang.label" :value="lang.value" />
</el-select>
</el-form-item>
</el-form>
</div>
</template>
80 changes: 80 additions & 0 deletions components/default/setting/Preference.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!--
- Copyright (c) 2023, Terwer . All rights reserved.
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
- This code is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License version 2 only, as
- published by the Free Software Foundation. Terwer designates this
- particular file as subject to the "Classpath" exception as provided
- by Terwer in the LICENSE file that accompanied this code.
-
- This code is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- version 2 for more details (a copy is included in the LICENSE file that
- accompanied this code).
-
- You should have received a copy of the GNU General Public License version
- 2 along with this work; if not, write to the Free Software Foundation,
- Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
- Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com
- or visit www.terwer.space if you need additional information or have any
- questions.
-->

<script setup lang="ts">
import { createAppLogger } from "~/common/appLogger"
import { useSettingStore } from "~/stores/useSettingStore"
const logger = createAppLogger("preference-page")
const { t } = useI18n()
const { getSetting, updateSetting } = useSettingStore()
const setting = await getSetting()
// datas
const formData = reactive({
siteTitle: setting?.siteTitle ?? t("blog.site.title"),
siteSlogan: setting?.siteSlogan ?? t("blog.site.slogan"),
siteDescription: setting?.siteDescription ?? "",
})
// methods
const onSubmit = async () => {
try {
setting.siteTitle = formData.siteTitle
setting.siteSlogan = formData.siteSlogan
setting.siteDescription = formData.siteDescription
await updateSetting(setting)
ElMessage.success(t("main.opt.success"))
} catch (e) {
logger.error(t("main.opt.failure"), e)
ElMessage({
type: "error",
message: t("main.opt.failure") + e,
})
}
}
</script>

<template>
<div class="preference-setting">
<el-form label-width="85px">
<el-form-item :label="t('blog.site.title.label')">
<el-input v-model="formData.siteTitle" />
</el-form-item>
<el-form-item :label="t('blog.site.slogan.label')">
<el-input v-model="formData.siteSlogan" />
</el-form-item>
<el-form-item :label="t('blog.site.desc.label')">
<el-input v-model="formData.siteDescription" :rows="4" type="textarea" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">{{ t("main.opt.save") }}</el-button>
</el-form-item>
</el-form>
</div>
</template>

<style scoped></style>
4 changes: 2 additions & 2 deletions composables/usePost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ export const usePost = () => {
/**
* 如果缓存已有直接返回,否则去远程抓取数据
*/
const setCurrentPost = async () => {
const setCurrentPost = async (pageId?: string) => {
if (ObjectUtil.isEmptyObject(currentPost.post)) {
const route = useRoute()
const id = (route.params.id ?? "") as string
const id = pageId ?? ((route.params.id ?? "") as string)
currentPost.post = await getPost(id)
} else {
logger.info("Post already cached, skip fetch")
Expand Down
Loading

0 comments on commit 9911274

Please sign in to comment.