diff --git a/apps/web/package.json b/apps/web/package.json index 0b7e8d772..1c54c204f 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -52,6 +52,7 @@ "highlight.js": "^11.11.1", "html-to-image": "^1.11.13", "isomorphic-dompurify": "^2.29.0", + "js-lite-rest": "^0.0.5", "juice": "^11.0.3", "lucide-vue-next": "^0.545.0", "marked": "^16.4.0", diff --git a/apps/web/src/main.ts b/apps/web/src/main.ts index 29212b918..0a2deac39 100644 --- a/apps/web/src/main.ts +++ b/apps/web/src/main.ts @@ -1,6 +1,8 @@ import { initializeMermaid } from '@md/core/utils' +import JsLiteRest from 'js-lite-rest' import { createPinia } from 'pinia' import { createApp } from 'vue' +import { data } from '@/stores/defaultData' import App from './App.vue' import { setupComponents } from './utils/setup-components' @@ -11,13 +13,38 @@ import 'vue-sonner/style.css' import '@/assets/index.css' import '@/assets/less/theme.less' -// 异步初始化 mermaid,避免初始化顺序问题 -initializeMermaid().catch(console.error) - -setupComponents() - -const app = createApp(App) - -app.use(createPinia()) - -app.mount(`#app`) +; + +(async function () { + const storex = await JsLiteRest.create({ + history: [], + posts: data.posts, + }, { + savePath: `storex`, + }) + storex.use(async (args: any, next: any) => { + const restLog: any = {} + if (args[2]) { + // 统一处理 vue 包装的可能是响应式的特殊对象 + args[2] = JSON.parse(JSON.stringify(args[2])) + } + let result = await next(args) + result = JSON.parse(JSON.stringify(result)) + restLog.args = args + restLog.result = result + console.debug(`restLog`, args.slice(0, 2).join(`/`), args[2], result.data) + return result + }) + window.storex = storex + + // 异步初始化 mermaid,避免初始化顺序问题 + initializeMermaid().catch(console.error) + + setupComponents() + + const app = createApp(App) + + app.use(createPinia()) + + app.mount(`#app`) +})() diff --git a/apps/web/src/stores/defaultData.ts b/apps/web/src/stores/defaultData.ts new file mode 100644 index 000000000..bf6a4a1a5 --- /dev/null +++ b/apps/web/src/stores/defaultData.ts @@ -0,0 +1,21 @@ +import { v4 as uuid } from 'uuid' +import DEFAULT_CONTENT from '@/assets/example/markdown.md?raw' + +const data = { + posts: [ + { + id: uuid(), + title: `内容1`, + content: DEFAULT_CONTENT, + history: [ + { datetime: new Date().toLocaleString(`zh-cn`), content: DEFAULT_CONTENT }, + ], + createDatetime: new Date(), + updateDatetime: new Date(), + }, + ], +} + +export { + data, +} diff --git a/apps/web/src/stores/index.ts b/apps/web/src/stores/index.ts index 4329a35d0..bd5ff8590 100644 --- a/apps/web/src/stores/index.ts +++ b/apps/web/src/stores/index.ts @@ -11,8 +11,8 @@ import { cssSetup, theme as editorTheme } from '@md/shared/editor' import { toPng } from 'html-to-image' import { v4 as uuid } from 'uuid' import DEFAULT_CONTENT from '@/assets/example/markdown.md?raw' - import DEFAULT_CSS_CONTENT from '@/assets/example/theme-css.txt?raw' + import { addPrefix, css2json, @@ -30,6 +30,7 @@ import { sanitizeTitle, } from '@/utils' import { copyPlain } from '@/utils/clipboard' +import { data } from './defaultData' /********************************** * Post 结构接口 @@ -117,18 +118,7 @@ export const useStore = defineStore(`store`, () => { /******************************* * 内容列表 posts:默认就带 id ******************************/ - const posts = useStorage(addPrefix(`posts`), [ - { - id: uuid(), - title: `内容1`, - content: DEFAULT_CONTENT, - history: [ - { datetime: new Date().toLocaleString(`zh-cn`), content: DEFAULT_CONTENT }, - ], - createDatetime: new Date(), - updateDatetime: new Date(), - }, - ]) + const posts = useStorage(addPrefix(`posts`), data.posts) // currentPostId 先存空串 const currentPostId = useStorage(addPrefix(`current_post_id`), ``) @@ -185,7 +175,7 @@ export const useStore = defineStore(`store`, () => { /******************************** * CRUD ********************************/ - const addPost = (title: string, parentId: string | null = null) => { + const addPost = async (title: string, parentId: string | null = null): Promise => { const newPost: Post = { id: uuid(), title, @@ -197,8 +187,12 @@ export const useStore = defineStore(`store`, () => { updateDatetime: new Date(), parentId, } - posts.value.push(newPost) - currentPostId.value = newPost.id + const res = await window.storex.post(`posts`, newPost) + posts.value.push(res) + currentPostId.value = res.id + } + const putPost = async (id: string, data: any): Promise => { + window.storex.put(`posts/${id}`, { ...data, history: undefined }).catch(() => {}) } const renamePost = (id: string, title: string) => { @@ -207,11 +201,12 @@ export const useStore = defineStore(`store`, () => { post.title = title } - const delPost = (id: string) => { + const delPost = async (id: string): Promise => { const idx = findIndexById(id) if (idx === -1) return posts.value.splice(idx, 1) + window.storex.delete(`posts/${id}`).catch(() => {}) currentPostId.value = posts.value[Math.min(idx, posts.value.length - 1)]?.id ?? `` } @@ -803,6 +798,7 @@ export const useStore = defineStore(`store`, () => { currentPostIndex, getPostById, addPost, + putPost, renamePost, delPost, isOpenPostSlider, diff --git a/apps/web/src/types/global.d.ts b/apps/web/src/types/global.d.ts index 154d48f4c..9e093e341 100644 --- a/apps/web/src/types/global.d.ts +++ b/apps/web/src/types/global.d.ts @@ -1,4 +1,5 @@ interface Window { + storex: any __MP_Editor_JSAPI__: { invoke: (params: { apiName: string diff --git a/apps/web/src/views/CodemirrorEditor.vue b/apps/web/src/views/CodemirrorEditor.vue index f73e24673..9ed696901 100644 --- a/apps/web/src/views/CodemirrorEditor.vue +++ b/apps/web/src/views/CodemirrorEditor.vue @@ -420,6 +420,7 @@ function createFormTextArea(dom: HTMLDivElement) { currentPost.updateDatetime = new Date() currentPost.content = value + store.putPost(currentPost.id, currentPost) }, 300) } }), @@ -516,6 +517,10 @@ onMounted(() => { content: currentPost.content, datetime: new Date().toLocaleString(`zh-CN`), }) + window.storex.post(`history`, { + postsId: currentPost.id, + content: currentPost.content, + }) currentPost.history.length = Math.min(currentPost.history.length, 10) }, 30 * 1000) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cc4f66b1e..6d44e49f8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -156,6 +156,9 @@ importers: isomorphic-dompurify: specifier: ^2.29.0 version: 2.29.0(postcss@8.5.6) + js-lite-rest: + specifier: ^0.0.5 + version: 0.0.5 juice: specifier: ^11.0.3 version: 11.0.3 @@ -6977,6 +6980,9 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + js-lite-rest@0.0.5: + resolution: {integrity: sha512-kEwr8iaYM/CTYit+NglC5DK4RkZ0U0F2TAt7ufiI71I1Qd3HA1wPV2YhP+ov/nbYuwGAXYonRCYuiRI0rT628Q==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -18385,6 +18391,8 @@ snapshots: jiti@2.6.1: {} + js-lite-rest@0.0.5: {} + js-tokens@4.0.0: {} js-tokens@9.0.1: {}