diff --git a/README.md b/README.md index ff96c353..2d9a889f 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,8 @@ This plugin supports almost all devices and platforms of Siyuan Note, and the sp **It may be migrated to the official forward proxy to achieve zero configuration in the future, but for now you must set it yourself, you can follow the progress here.** +- Progress 1: The Yuque and Notion platforms have used the built-in forward proxy and do not need to be configured. + ## Platform List Names not listed in order diff --git a/README_zh_CN.md b/README_zh_CN.md index be94eabc..d65be114 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -61,6 +61,8 @@ **后续可能会迁移到官方的正向代理实现零配置,但是目前还是必须要自己设置,可在这里关注进展。** +- 进度1:语雀、Notion平台已使用内置正向代理,无需配置。 + ## 平台列表 排名不分先后 diff --git a/package.json b/package.json index a9b9cc3e..5f64330d 100644 --- a/package.json +++ b/package.json @@ -60,13 +60,13 @@ "vue-i18n": "^9.2.2", "vue-router": "^4.2.4", "xmlbuilder2": "^3.1.1", - "zhi-blog-api": "^1.20.8", + "zhi-blog-api": "^1.20.9", "zhi-common": "^1.11.7", "zhi-device": "^2.3.0", "zhi-fetch-middleware": "^0.2.7", "zhi-github-middleware": "^0.1.4", "zhi-lib-base": "^0.4.3", - "zhi-siyuan-api": "^1.29.9", + "zhi-siyuan-api": "^1.29.10", "zhi-xmlrpc-middleware": "^0.4.2" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cb35ee80..801a9bec 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -51,8 +51,8 @@ dependencies: specifier: ^3.1.1 version: 3.1.1 zhi-blog-api: - specifier: ^1.20.8 - version: 1.20.8 + specifier: ^1.20.9 + version: 1.20.9 zhi-common: specifier: ^1.11.7 version: 1.11.7 @@ -69,8 +69,8 @@ dependencies: specifier: ^0.4.3 version: 0.4.3 zhi-siyuan-api: - specifier: ^1.29.9 - version: 1.29.9 + specifier: ^1.29.10 + version: 1.29.10 zhi-xmlrpc-middleware: specifier: ^0.4.2 version: 0.4.2 @@ -2118,7 +2118,7 @@ packages: /browser-resolve@2.0.0: resolution: {integrity: sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==} dependencies: - resolve: 1.22.2 + resolve: 1.22.4 dev: true /browserify-aes@1.2.0: @@ -4014,8 +4014,8 @@ packages: engines: {node: '>= 0.4'} dev: true - /is-core-module@2.12.1: - resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==} + /is-core-module@2.13.0: + resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} dependencies: has: 1.0.3 dev: true @@ -5169,11 +5169,11 @@ packages: engines: {node: '>=8'} dev: true - /resolve@1.22.2: - resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} + /resolve@1.22.4: + resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==} hasBin: true dependencies: - is-core-module: 2.12.1 + is-core-module: 2.13.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 dev: true @@ -5889,7 +5889,7 @@ packages: local-pkg: 0.4.3 magic-string: 0.30.2 minimatch: 9.0.3 - resolve: 1.22.2 + resolve: 1.22.4 unplugin: 1.4.0 vue: 3.3.4 transitivePeerDependencies: @@ -6357,8 +6357,8 @@ packages: engines: {node: '>=12.20'} dev: true - /zhi-blog-api@1.20.8: - resolution: {integrity: sha512-dUcvdEbr2matntqvQFECT0xQxRwPU9RAExxMu6qDQgmzFucv4VsKY9FKEqsDO+0dp74AcJUjwjyTq8Rhd+Klnw==} + /zhi-blog-api@1.20.9: + resolution: {integrity: sha512-0tar9MkVmb2rI6NP4dSipJzBIecNiVoglfp2t45mqVvadJso1SZNC4cPbL/I3LAxO8YDlaq+GDKQ44lWjldAtA==} dependencies: zhi-lib-base: 0.4.3 dev: false @@ -6394,10 +6394,10 @@ packages: resolution: {integrity: sha512-jahOcJ4MjJ9gAPM/nwgF65p2dPyggRgKFJPT0WDtyoabQw4sCUSOJ1Cps18Rq6lt4agH5yqAObz/mPdVz/bHWw==} dev: false - /zhi-siyuan-api@1.29.9: - resolution: {integrity: sha512-PoGLbjNDTvjqmh6x3A4FsbU2jCbEe3ilfPtMFmY6RymSryOEBaSuPlmoLwyaNbFw71zWPrkcORjD/kBOKcd17g==} + /zhi-siyuan-api@1.29.10: + resolution: {integrity: sha512-gpDdlnqPQjBAOIYYja5M8dBArhX/cwWUpTpdIXhbOGcYYxY67E0bhyWdEyA/yl+AGGmmyOY94aoKMQ/d1+24XQ==} dependencies: - zhi-blog-api: 1.20.8 + zhi-blog-api: 1.20.9 zhi-common: 1.11.7 zhi-lib-base: 0.4.3 dev: false diff --git a/src/adaptors/api/base/baseBlogApi.ts b/src/adaptors/api/base/baseBlogApi.ts index 2f211275..8d82e684 100644 --- a/src/adaptors/api/base/baseBlogApi.ts +++ b/src/adaptors/api/base/baseBlogApi.ts @@ -84,7 +84,7 @@ export class BaseBlogApi extends BlogApi { url: string, headers: any[], params: any = {}, - method: "GET" | "POST" = "GET", + method: "GET" | "POST" | "PUT" | "DELETE" = "GET", contentType: string = "application/json" ): Promise { if (this.isInChromeExtension) { diff --git a/src/adaptors/api/notion/adaptor/notionApiAdaptor.ts b/src/adaptors/api/notion/adaptor/notionApiAdaptor.ts index cee396c9..0bf96ba4 100644 --- a/src/adaptors/api/notion/adaptor/notionApiAdaptor.ts +++ b/src/adaptors/api/notion/adaptor/notionApiAdaptor.ts @@ -41,6 +41,10 @@ class NotionApiAdaptor extends BaseBlogApi { const result: UserBlog[] = [] // https://developers.notion.com/reference/post-search + const headers = { + Authorization: `Bearer ${this.cfg.password}`, + "Notion-Version": "2022-06-28", + } const params = { page_size: 10, filter: { @@ -48,17 +52,13 @@ class NotionApiAdaptor extends BaseBlogApi { property: "object", }, } - const headers = { - Authorization: `Bearer ${this.cfg.password}`, - "Notion-Version": "2022-06-28", - } const searchResp = await this.proxyFetch("/search", [headers], params, "POST", "application/json") - this.logger.debug("notion searchResp results=>", searchResp) - if (searchResp.status === 401) { - throw new Error(searchResp.message) + this.logger.debug("notion searchResp=>", searchResp) + if (searchResp?.status === 401) { + throw new Error(searchResp?.message) } const pages = searchResp.results as any - this.logger.debug("notion database results=>", pages) + this.logger.debug("notion pages=>", pages) // https://stackoverflow.com/a/75537092/4037224 if (pages.length === 0) { diff --git a/src/adaptors/api/yuque/adaptor/yuqueApi.ts b/src/adaptors/api/yuque/adaptor/yuqueApi.ts deleted file mode 100644 index aa775701..00000000 --- a/src/adaptors/api/yuque/adaptor/yuqueApi.ts +++ /dev/null @@ -1,223 +0,0 @@ -/* - * 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. - */ - -import { CommonFetchClient } from "zhi-fetch-middleware" -import { createAppLogger } from "~/src/utils/appLogger.ts" -import { ObjectUtil } from "zhi-common" -import { isDev } from "~/src/utils/constants.ts" - -/** - * 语雀API - * - * https://www.yuque.com/yuque/developer - */ -export class YuqueApi { - private readonly logger - private readonly commonFetchClient - private readonly baseUrl: string - private readonly blogid: string - private readonly username: string - private readonly token: string - private readonly middlewareUrl: string - - constructor( - appInstance: any, - baseUrl: string, - blogid: string, - username: string, - token: string, - middlewareUrl?: string - ) { - this.logger = createAppLogger("yuque-api") - this.commonFetchClient = new CommonFetchClient(appInstance, baseUrl, middlewareUrl, isDev) - this.baseUrl = baseUrl - this.blogid = blogid - this.username = username - this.token = token - this.middlewareUrl = middlewareUrl - } - - /** - * 语雀知识库列表 - */ - public async repos(): Promise { - const url = "/users/" + this.username + "/repos" - const data = {} - return await this.yuqueRequest(url, data, "GET") - } - - /** - * 向默认知识库添加文档 - * - * @param title 标题 - * @param slug 别名 - * @param content 内容 - * @param repo 知识库(可选) - */ - public async addDoc(title: string, slug: string, content: string, repo?: string): Promise { - let url = "/repos/" + this.blogid + "/docs" - if (repo) { - url = "/repos/" + repo + "/docs" - this.logger.warn("yuque addDoc with repo", repo) - } - const data = { - title, - slug, - format: "markdown", - body: content, - } - const result = await this.yuqueRequest(url, data, "POST") - this.logger.debug("yuqueRequest addDoc=>", result) - if (!result) { - throw new Error("请求语雀API异常") - } - - // 包含了笔记本需要返回标识笔记本的ID,否则更新可能报错 - if (repo) { - return `${result.id}_${repo}` - } else { - return `${result.id}` - } - } - - /** - * 更新语雀文档 - * - * @param docId 文档ID - * @param title 标题 - * @param slug 别名 - * @param content 内容 - * @param repo 知识库(可选) - */ - public async updateDoc(docId: string, title: string, slug: string, content: string, repo?: string): Promise { - let url = "/repos/" + this.blogid + "/docs/" + docId - if (repo) { - url = "/repos/" + repo + "/docs/" + docId - this.logger.warn("yuque updateDoc with repo", repo) - } - const data = { - title, - slug, - body: content, - _force_asl: 1, - } - const result = await this.yuqueRequest(url, data, "PUT") - if (!result) { - throw new Error("请求语雀API异常") - } - - return true - } - - /** - * 删除 yuque 文档 - * - * @param docId 文档ID - * @param repo 知识库(可选) - */ - public async delDoc(docId: string, repo?: string): Promise { - let url = "/repos/" + this.blogid + "/docs/" + docId - if (repo) { - url = "/repos/" + repo + "/docs/" + docId - this.logger.warn("yuque delDoc with repo", repo) - } - const data = {} - const result = await this.yuqueRequest(url, data, "DELETE") - if (!result) { - throw new Error("请求语雀API异常") - } - - return true - } - - /** - * 获取 yuque 文档 - * - * @param docId 文档ID - * @param repo 知识库(可选) - */ - public async getDoc(docId: string, repo?: string): Promise { - let url = "/repos/" + this.blogid + "/docs/" + docId - if (repo) { - url = "/repos/" + repo + "/docs/" + docId - this.logger.warn("yuque getDoc with repo", repo) - } - const data = {} - const result = await this.yuqueRequest(url, data, "GET") - if (!result) { - throw new Error("请求语雀API异常") - } - - return result - } - - // ========================================================================== - // ========================================================================== - /** - * 向语雀请求数据 - * - * @param url 请求地址 - * @param data 数据 - * @param method 请求方法 GET | POST - * @private - */ - private async yuqueRequest(url: string, data?: any, method?: string): Promise { - let m = "POST" - if (method) { - m = method - } - - const fetchOptions = { - method: m, - } - - // 数据不为空才传递 - if (!ObjectUtil.isEmptyObject(data)) { - Object.assign(fetchOptions, { - body: JSON.stringify(data), - }) - } - - Object.assign(fetchOptions, { - headers: { - "Content-Type": "application/json", - "X-Auth-Token": this.token, - "User-Agent": "Terwer/0.1.0", - }, - }) - - // 发送请求 - // 设置请求参数 - const apiUrl = this.baseUrl + url - this.logger.debug("向语雀请求数据,apiUrl=>", apiUrl) - this.logger.debug("向语雀请求数据,fetchOps=>", fetchOptions) - - // 使用兼容的fetch调用并返回统一的JSON数据 - const resJson = await this.commonFetchClient.fetchCall(url, fetchOptions, this.middlewareUrl) - - this.logger.debug("向语雀请求数据,resJson=>", resJson) - return resJson.data ? resJson.data : null - } -} diff --git a/src/adaptors/api/yuque/adaptor/yuqueApiAdaptor.ts b/src/adaptors/api/yuque/adaptor/yuqueApiAdaptor.ts index 61ab8d28..ca72b609 100644 --- a/src/adaptors/api/yuque/adaptor/yuqueApiAdaptor.ts +++ b/src/adaptors/api/yuque/adaptor/yuqueApiAdaptor.ts @@ -23,40 +23,26 @@ * questions. */ -import { BlogApi, CategoryInfo, Post, UserBlog } from "zhi-blog-api" -import { YuqueApi } from "~/src/adaptors/api/yuque/adaptor/yuqueApi.ts" +import { CategoryInfo, Post, UserBlog } from "zhi-blog-api" import { YuqueConfig } from "~/src/adaptors/api/yuque/config/yuqueConfig.ts" import { createAppLogger } from "~/src/utils/appLogger.ts" +import { BaseBlogApi } from "~/src/adaptors/api/base/baseBlogApi.ts" import { StrUtil } from "zhi-common" /** * Yuque API 适配器 + * @see [Yuque API](https://www.yuque.com/yuque/developer) */ -class YuqueApiAdaptor extends BlogApi { - private readonly logger - private readonly yuqueApi: YuqueApi - private readonly cfg - +class YuqueApiAdaptor extends BaseBlogApi { constructor(appInstance: any, cfg: YuqueConfig) { - super() + super(appInstance, cfg) this.logger = createAppLogger("yuque-api-adaptor") - this.cfg = cfg - this.yuqueApi = new YuqueApi( - appInstance, - cfg.apiUrl, - cfg.blogid ?? "", - cfg.username ?? "", - cfg.password ?? "", - cfg.middlewareUrl - ) } public async getUsersBlogs(): Promise { const result: UserBlog[] = [] - const repos = await this.yuqueApi.repos() - this.logger.debug("repos=>", repos) - + const repos = await this.getRepos() // 数据适配 repos.forEach((item: any) => { const userblog: UserBlog = new UserBlog() @@ -69,14 +55,22 @@ class YuqueApiAdaptor extends BlogApi { return result } - public async deletePost(postid: string): Promise { - const yuquePostidKey = this.getYuquePostKey(postid) - return await this.yuqueApi.delDoc(yuquePostidKey.docId, yuquePostidKey.docRepo) + public async newPost(post: Post, publish?: boolean): Promise { + if (post.cate_slugs != null && post.cate_slugs.length > 0) { + const repo = post.cate_slugs[0] + return await this.addDoc(post.title, post.wp_slug, post.description, repo) + } else if (!StrUtil.isEmptyString(this.cfg.blogid)) { + // 确保最新的文章ID都包含了笔记本信息,防止以后文章出错 + const repo = this.cfg.blogid + return await this.addDoc(post.title, post.wp_slug, post.description, repo) + } else { + return await this.addDoc(post.title, post.wp_slug, post.description) + } } public async editPost(postid: string, post: Post, publish?: boolean): Promise { const yuquePostidKey = this.getYuquePostKey(postid) - return await this.yuqueApi.updateDoc( + return await this.updateDoc( yuquePostidKey.docId, post.title, post.wp_slug, @@ -85,23 +79,15 @@ class YuqueApiAdaptor extends BlogApi { ) } - public async newPost(post: Post, publish?: boolean): Promise { - if (post.cate_slugs != null && post.cate_slugs.length > 0) { - const repo = post.cate_slugs[0] - return await this.yuqueApi.addDoc(post.title, post.wp_slug, post.description, repo) - } else if (!StrUtil.isEmptyString(this.cfg.blogid)) { - // 确保最新的文章ID都包含了笔记本信息,防止以后文章出错 - const repo = this.cfg.blogid - return await this.yuqueApi.addDoc(post.title, post.wp_slug, post.description, repo) - } else { - return await this.yuqueApi.addDoc(post.title, post.wp_slug, post.description) - } + public async deletePost(postid: string): Promise { + const yuquePostidKey = this.getYuquePostKey(postid) + return await this.delDoc(yuquePostidKey.docId, yuquePostidKey.docRepo) } public async getPost(postid: string, useSlug?: boolean): Promise { const yuquePostidKey = this.getYuquePostKey(postid) - const yuqueDoc = await this.yuqueApi.getDoc(yuquePostidKey.docId, yuquePostidKey.docRepo) + const yuqueDoc = await this.getDoc(yuquePostidKey.docId, yuquePostidKey.docRepo) this.logger.debug("yuqueDoc=>", yuqueDoc) const commonPost = new Post() @@ -124,8 +110,7 @@ class YuqueApiAdaptor extends BlogApi { public async getCategories(): Promise { const cats = [] as CategoryInfo[] - const repos: any[] = await this.yuqueApi.repos() - this.logger.debug("yuque repos=>", repos) + const repos: any[] = await this.getRepos() if (repos && repos.length > 0) { repos.forEach((repo) => { // 只获取文档库 @@ -143,7 +128,7 @@ class YuqueApiAdaptor extends BlogApi { return cats } - async getPreviewUrl(postid: string): Promise { + public async getPreviewUrl(postid: string): Promise { // 替换文章链接 const purl = this.cfg.previewUrl ?? "" const yuquePostidKey = this.getYuquePostKey(postid) @@ -153,6 +138,102 @@ class YuqueApiAdaptor extends BlogApi { return StrUtil.pathJoin(this.cfg.home ?? "", postUrl) } + // ================ + // private methods + // ================ + /** + * 语雀知识库列表 + */ + private async getRepos() { + const url = "/users/" + this.cfg.username + "/repos" + const headers = { + "X-Auth-Token": this.cfg.password, + } + const repoResp = await this.proxyFetch(url, [headers], {}, "GET", "application/json") + this.logger.debug("yuque repoResp=>", repoResp) + if (repoResp?.status === 401) { + throw new Error(repoResp?.message) + } + const repos = repoResp.data + this.logger.debug("yuque repos=>", repos) + return repos + } + + /** + * 向默认知识库添加文档 + * + * @param title 标题 + * @param slug 别名 + * @param content 内容 + * @param repo 知识库(可选) + */ + private async addDoc(title: string, slug: string, content: string, repo?: string): Promise { + let url = "/repos/" + this.cfg.blogid + "/docs" + if (repo) { + url = "/repos/" + repo + "/docs" + this.logger.warn("yuque addDoc with repo", repo) + } + const headers = { + "X-Auth-Token": this.cfg.password, + } + const params = { + title, + slug, + format: "markdown", + body: content, + } + const result = await this.proxyFetch(url, [headers], params, "POST", "application/json") + this.logger.debug("yuqueRequest addDoc=>", result) + if (!result) { + throw new Error("请求语雀API异常") + } + + // 包含了笔记本需要返回标识笔记本的ID,否则更新可能报错 + if (repo) { + return `${result.id}_${repo}` + } else { + return `${result.id}` + } + } + + /** + * 更新语雀文档 + * + * @param docId 文档ID + * @param title 标题 + * @param slug 别名 + * @param content 内容 + * @param repo 知识库(可选) + */ + private async updateDoc( + docId: string, + title: string, + slug: string, + content: string, + repo?: string + ): Promise { + let url = "/repos/" + this.cfg.blogid + "/docs/" + docId + if (repo) { + url = "/repos/" + repo + "/docs/" + docId + this.logger.warn("yuque updateDoc with repo", repo) + } + const headers = { + "X-Auth-Token": this.cfg.password, + } + const params = { + title, + slug, + body: content, + _force_asl: 1, + } + const result = await this.proxyFetch(url, [headers], params, "PUT", "application/json") + if (!result) { + throw new Error("请求语雀API异常") + } + + return true + } + /** * 获取封装的postid * @@ -176,6 +257,52 @@ class YuqueApiAdaptor extends BlogApi { docRepo, } } + + /** + * 删除 yuque 文档 + * + * @param docId 文档ID + * @param repo 知识库(可选) + */ + private async delDoc(docId: string, repo?: string): Promise { + let url = "/repos/" + this.cfg.blogid + "/docs/" + docId + if (repo) { + url = "/repos/" + repo + "/docs/" + docId + this.logger.warn("yuque delDoc with repo", repo) + } + const headers = { + "X-Auth-Token": this.cfg.password, + } + const result = await this.proxyFetch(url, [headers], {}, "DELETE", "application/json") + if (!result) { + throw new Error("请求语雀API异常") + } + + return true + } + + /** + * 获取 yuque 文档 + * + * @param docId 文档ID + * @param repo 知识库(可选) + */ + public async getDoc(docId: string, repo?: string): Promise { + let url = "/repos/" + this.cfg.blogid + "/docs/" + docId + if (repo) { + url = "/repos/" + repo + "/docs/" + docId + this.logger.warn("yuque getDoc with repo", repo) + } + const headers = { + "X-Auth-Token": this.cfg.password, + } + const result = await this.proxyFetch(url, [headers], {}, "GET", "application/json") + if (!result) { + throw new Error("请求语雀API异常") + } + + return result + } } export { YuqueApiAdaptor } diff --git a/src/components/set/publish/singleplatform/CommonBlogSetting.vue b/src/components/set/publish/singleplatform/CommonBlogSetting.vue index bba6683c..7b2b659e 100644 --- a/src/components/set/publish/singleplatform/CommonBlogSetting.vue +++ b/src/components/set/publish/singleplatform/CommonBlogSetting.vue @@ -231,6 +231,13 @@ onMounted(async () => { + @@ -287,6 +294,7 @@ onMounted(async () => { v-model="formData.cfg.blogid" class="m-2" :placeholder="t('main.opt.select')" + :no-data-text="t('main.data.empty')" @change="handleKeSpaceChange" > diff --git a/src/locales/en_US.ts b/src/locales/en_US.ts index e0b4992a..e21a302b 100644 --- a/src/locales/en_US.ts +++ b/src/locales/en_US.ts @@ -533,4 +533,6 @@ export default { "main.publish.start": "Start syncing", "main.publish.remove": "Remove", "setting.blog.knowledge.space": "Knowledge space/Knowledge base", + "main.data.empty": "No data", + "enableKnowledgeSpace.Tips": "After validation, a list of available knowledge spaces is listed, and you can modify the default knowledge spaces as needed and save them", } diff --git a/src/locales/zh_CN.ts b/src/locales/zh_CN.ts index 340ec7ae..315573fa 100644 --- a/src/locales/zh_CN.ts +++ b/src/locales/zh_CN.ts @@ -349,7 +349,8 @@ export default { "setting.yuque.previewUrl.tip": "语雀平台的文章预览规则,通常是:/[notebook]/[postid]", "setting.notion.home.tip": "Notion平台首页,通常固定是:https://www.notion.so/", - "setting.notion.password.tip": "Notion平台的Token,请按照链接点击获取,需要勾选【Read content】、【Update content】、【Insert content】三个权限", + "setting.notion.password.tip": + "Notion平台的Token,请按照链接点击获取,需要勾选【Read content】、【Update content】、【Insert content】三个权限", "setting.notion.apiurl.tip": "Notion平台的API地址,通常固定是:https://api.notion.com/v1", "setting.notion.previewUrl.tip": "Notion平台的文章预览规则,通常是:/[postid]", @@ -520,5 +521,7 @@ export default { "setting.upgrade.syp.doTip4": "没有版本更新,跳过升级", "main.publish.start": "开始同步", "main.publish.remove": "批量删除", - "setting.blog.knowledge.space":"知识空间/知识库" + "setting.blog.knowledge.space": "知识空间/知识库", + "main.data.empty": "暂无数据", + "enableKnowledgeSpace.Tips": "验证通过之后,将列出可用的 [[knowledge-space-title]] 列表,您可以根据需要修改默认 [[knowledge-space-title]] 并保存", }