diff --git a/components/ArticleFormDrawer.vue b/components/ArticleFormDrawer.vue new file mode 100644 index 00000000..b97c9440 --- /dev/null +++ b/components/ArticleFormDrawer.vue @@ -0,0 +1,225 @@ + + + + + diff --git a/components/CategoryFormDrawer.vue b/components/CategoryFormDrawer.vue new file mode 100644 index 00000000..f3600baa --- /dev/null +++ b/components/CategoryFormDrawer.vue @@ -0,0 +1,153 @@ + + + + + diff --git a/pages/contents/articles.vue b/pages/contents/articles.vue new file mode 100644 index 00000000..244f81c3 --- /dev/null +++ b/pages/contents/articles.vue @@ -0,0 +1,119 @@ + + + + + diff --git a/pages/mall/admin/cms/article/list.uvue b/pages/mall/admin/cms/article/list.uvue index 0e4f3d6e..3f382071 100644 --- a/pages/mall/admin/cms/article/list.uvue +++ b/pages/mall/admin/cms/article/list.uvue @@ -85,14 +85,6 @@ - - - - 文章信息 - - - - @@ -111,15 +103,15 @@ - - + + *文章分类: {{ formCategory || '请选择' }} - + { dropdownVisible.value = false } -const handleAdd = () => { let editorCtx: any = null const onEditorReady = () => { // @ts-ignore @@ -285,6 +276,7 @@ const insertImage = () => { }) } +const handleAdd = () => { formTitle.value = '' formAuthor.value = '' formCategory.value = '' diff --git a/pages/mall/admin/docs/UNI_APP_X_PAGE_FIX_GUIDE.md b/pages/mall/admin/docs/UNI_APP_X_PAGE_FIX_GUIDE.md index da45594f..8185305d 100644 --- a/pages/mall/admin/docs/UNI_APP_X_PAGE_FIX_GUIDE.md +++ b/pages/mall/admin/docs/UNI_APP_X_PAGE_FIX_GUIDE.md @@ -1,3 +1,12 @@ +--- +🚧 注意: + +⚠ 注意:当前使用 mock 数据,后续真实接口完成后替换 +真实接口地址和返回字段未确定,请后续接口联调完成后再替换。 + +文档标记维持在此文件中,以便后续开发和对接。 +--- + # uni-app-x 页面修复指南 ## 📋 文档概述 diff --git a/pages/mall/admin/错误信息.txt b/pages/mall/admin/错误信息.txt index 2e303a13..1c48c1ce 100644 --- a/pages/mall/admin/错误信息.txt +++ b/pages/mall/admin/错误信息.txt @@ -168,445 +168,4 @@ at at at at -at -warnHandler @ uni-h5.es.js:19975 -callWithErrorHandling @ vue.runtime.esm.js:1381 -warn$1 @ vue.runtime.esm.js:1207 -get @ vue.runtime.esm.js:4455 -(anonymous) @ list.uvue?t=1772068177429&import:1028 -renderFnWithContext @ vue.runtime.esm.js:2033 -renderSlot @ vue.runtime.esm.js:4254 -(anonymous) @ uni-h5.es.js:18666 -renderComponentRoot @ vue.runtime.esm.js:2092 -componentUpdateFn @ vue.runtime.esm.js:7365 -run @ vue.runtime.esm.js:153 -instance.update @ vue.runtime.esm.js:7497 -setupRenderEffect @ vue.runtime.esm.js:7507 -mountComponent @ vue.runtime.esm.js:7274 -processComponent @ vue.runtime.esm.js:7228 -patch @ vue.runtime.esm.js:6694 -mountChildren @ vue.runtime.esm.js:6942 -processFragment @ vue.runtime.esm.js:7158 -patch @ vue.runtime.esm.js:6668 -mountChildren @ vue.runtime.esm.js:6942 -mountElement @ vue.runtime.esm.js:6849 -processElement @ vue.runtime.esm.js:6814 -patch @ vue.runtime.esm.js:6682 -componentUpdateFn @ vue.runtime.esm.js:7372 -run @ vue.runtime.esm.js:153 -instance.update @ vue.runtime.esm.js:7497 -setupRenderEffect @ vue.runtime.esm.js:7507 -mountComponent @ vue.runtime.esm.js:7274 -processComponent @ vue.runtime.esm.js:7228 -patch @ vue.runtime.esm.js:6694 -mountChildren @ vue.runtime.esm.js:6942 -processFragment @ vue.runtime.esm.js:7158 -patch @ vue.runtime.esm.js:6668 -mountChildren @ vue.runtime.esm.js:6942 -mountElement @ vue.runtime.esm.js:6849 -processElement @ vue.runtime.esm.js:6814 -patch @ vue.runtime.esm.js:6682 -componentUpdateFn @ vue.runtime.esm.js:7372 -run @ vue.runtime.esm.js:153 -instance.update @ vue.runtime.esm.js:7497 -setupRenderEffect @ vue.runtime.esm.js:7507 -mountComponent @ vue.runtime.esm.js:7274 -processComponent @ vue.runtime.esm.js:7228 -patch @ vue.runtime.esm.js:6694 -mountChildren @ vue.runtime.esm.js:6942 -processFragment @ vue.runtime.esm.js:7158 -patch @ vue.runtime.esm.js:6668 -mountChildren @ vue.runtime.esm.js:6942 -mountElement @ vue.runtime.esm.js:6849 -processElement @ vue.runtime.esm.js:6814 -patch @ vue.runtime.esm.js:6682 -mountChildren @ vue.runtime.esm.js:6942 -mountElement @ vue.runtime.esm.js:6849 -processElement @ vue.runtime.esm.js:6814 -patch @ vue.runtime.esm.js:6682 -mountChildren @ vue.runtime.esm.js:6942 -mountElement @ vue.runtime.esm.js:6849 -processElement @ vue.runtime.esm.js:6814 -patch @ vue.runtime.esm.js:6682 -mountChildren @ vue.runtime.esm.js:6942 -mountElement @ vue.runtime.esm.js:6849 -processElement @ vue.runtime.esm.js:6814 -patch @ vue.runtime.esm.js:6682 -componentUpdateFn @ vue.runtime.esm.js:7372 -run @ vue.runtime.esm.js:153 -instance.update @ vue.runtime.esm.js:7497 -setupRenderEffect @ vue.runtime.esm.js:7507 -mountComponent @ vue.runtime.esm.js:7274 -processComponent @ vue.runtime.esm.js:7228 -patch @ vue.runtime.esm.js:6694 -mountChildren @ vue.runtime.esm.js:6942 -processFragment @ vue.runtime.esm.js:7158 -patch @ vue.runtime.esm.js:6668 -mountChildren @ vue.runtime.esm.js:6942 -mountElement @ vue.runtime.esm.js:6849 -processElement @ vue.runtime.esm.js:6814 -patch @ vue.runtime.esm.js:6682 -componentUpdateFn @ vue.runtime.esm.js:7372 -run @ vue.runtime.esm.js:153 -instance.update @ vue.runtime.esm.js:7497 -setupRenderEffect @ vue.runtime.esm.js:7507 -mountComponent @ vue.runtime.esm.js:7274 -processComponent @ vue.runtime.esm.js:7228 -patch @ vue.runtime.esm.js:6694 -mountChildren @ vue.runtime.esm.js:6942 -processFragment @ vue.runtime.esm.js:7158 -patch @ vue.runtime.esm.js:6668 -mountChildren @ vue.runtime.esm.js:6942 -mountElement @ vue.runtime.esm.js:6849 -processElement @ vue.runtime.esm.js:6814 -patch @ vue.runtime.esm.js:6682 -componentUpdateFn @ vue.runtime.esm.js:7372 -run @ vue.runtime.esm.js:153 -instance.update @ vue.runtime.esm.js:7497 -setupRenderEffect @ vue.runtime.esm.js:7507 -mountComponent @ vue.runtime.esm.js:7274 -processComponent @ vue.runtime.esm.js:7228 -patch @ vue.runtime.esm.js:6694 -patchBlockChildren @ vue.runtime.esm.js:7084 -processFragment @ vue.runtime.esm.js:7176 -patch @ vue.runtime.esm.js:6668 -patchKeyedChildren @ vue.runtime.esm.js:7650 -patchChildren @ vue.runtime.esm.js:7564 -patchElement @ vue.runtime.esm.js:6989 -processElement @ vue.runtime.esm.js:6825 -patch @ vue.runtime.esm.js:6682 -componentUpdateFn @ vue.runtime.esm.js:7453 -run @ vue.runtime.esm.js:153 -instance.update @ vue.runtime.esm.js:7497 -callWithErrorHandling @ vue.runtime.esm.js:1381 -flushJobs @ vue.runtime.esm.js:1585 -Promise.then -queueFlush @ vue.runtime.esm.js:1494 -queueJob @ vue.runtime.esm.js:1488 -(anonymous) @ vue.runtime.esm.js:7491 -resetScheduling @ vue.runtime.esm.js:236 -triggerEffects @ vue.runtime.esm.js:280 -triggerRefValue @ vue.runtime.esm.js:1033 -set value @ vue.runtime.esm.js:1078 -handleAdd @ list.uvue:297 -callWithErrorHandling @ vue.runtime.esm.js:1381 -callWithAsyncErrorHandling @ vue.runtime.esm.js:1388 -invoker @ vue.runtime.esm.js:10253 -uni-h5.es.js:19975 [Vue warn]: Unhandled error during execution of native event handler - at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -warnHandler @ uni-h5.es.js:19975 -callWithErrorHandling @ vue.runtime.esm.js:1381 -warn$1 @ vue.runtime.esm.js:1207 -logError @ vue.runtime.esm.js:1438 -errorHandler @ uni-h5.es.js:19600 -callWithErrorHandling @ vue.runtime.esm.js:1381 -handleError @ vue.runtime.esm.js:1421 -callWithErrorHandling @ vue.runtime.esm.js:1383 -callWithAsyncErrorHandling @ vue.runtime.esm.js:1388 -invoker @ vue.runtime.esm.js:10253 -vue.runtime.esm.js:1443 TypeError: _ctx.formatText is not a function - at _createVNode.onClick._cache.._cache. (list.uvue?t=1772068177429&import:980:85) - at callWithErrorHandling (vue.runtime.esm.js:1381:19) - at callWithAsyncErrorHandling (vue.runtime.esm.js:1388:17) - at UniTextElement.invoker (vue.runtime.esm.js:10253:5) -logError @ vue.runtime.esm.js:1443 -errorHandler @ uni-h5.es.js:19600 -callWithErrorHandling @ vue.runtime.esm.js:1381 -handleError @ vue.runtime.esm.js:1421 -callWithErrorHandling @ vue.runtime.esm.js:1383 -callWithAsyncErrorHandling @ vue.runtime.esm.js:1388 -invoker @ vue.runtime.esm.js:10253 -uni-h5.es.js:19975 [Vue warn]: Unhandled error during execution of native event handler - at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -warnHandler @ uni-h5.es.js:19975 -callWithErrorHandling @ vue.runtime.esm.js:1381 -warn$1 @ vue.runtime.esm.js:1207 -logError @ vue.runtime.esm.js:1438 -errorHandler @ uni-h5.es.js:19600 -callWithErrorHandling @ vue.runtime.esm.js:1381 -handleError @ vue.runtime.esm.js:1421 -callWithErrorHandling @ vue.runtime.esm.js:1383 -callWithAsyncErrorHandling @ vue.runtime.esm.js:1388 -invoker @ vue.runtime.esm.js:10253 -vue.runtime.esm.js:1443 TypeError: _ctx.formatText is not a function - at _createVNode.onClick._cache.._cache. (list.uvue?t=1772068177429&import:990:85) - at callWithErrorHandling (vue.runtime.esm.js:1381:19) - at callWithAsyncErrorHandling (vue.runtime.esm.js:1388:17) - at UniTextElement.invoker (vue.runtime.esm.js:10253:5) -logError @ vue.runtime.esm.js:1443 -errorHandler @ uni-h5.es.js:19600 -callWithErrorHandling @ vue.runtime.esm.js:1381 -handleError @ vue.runtime.esm.js:1421 -callWithErrorHandling @ vue.runtime.esm.js:1383 -callWithAsyncErrorHandling @ vue.runtime.esm.js:1388 -invoker @ vue.runtime.esm.js:10253 -uni-h5.es.js:19975 [Vue warn]: Unhandled error during execution of native event handler - at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -warnHandler @ uni-h5.es.js:19975 -callWithErrorHandling @ vue.runtime.esm.js:1381 -warn$1 @ vue.runtime.esm.js:1207 -logError @ vue.runtime.esm.js:1438 -errorHandler @ uni-h5.es.js:19600 -callWithErrorHandling @ vue.runtime.esm.js:1381 -handleError @ vue.runtime.esm.js:1421 -callWithErrorHandling @ vue.runtime.esm.js:1383 -callWithAsyncErrorHandling @ vue.runtime.esm.js:1388 -invoker @ vue.runtime.esm.js:10253 -vue.runtime.esm.js:1443 TypeError: _ctx.formatText is not a function - at _createVNode.onClick._cache.._cache. (list.uvue?t=1772068177429&import:1000:85) - at callWithErrorHandling (vue.runtime.esm.js:1381:19) - at callWithAsyncErrorHandling (vue.runtime.esm.js:1388:17) - at UniTextElement.invoker (vue.runtime.esm.js:10253:5) -logError @ vue.runtime.esm.js:1443 -errorHandler @ uni-h5.es.js:19600 -callWithErrorHandling @ vue.runtime.esm.js:1381 -handleError @ vue.runtime.esm.js:1421 -callWithErrorHandling @ vue.runtime.esm.js:1383 -callWithAsyncErrorHandling @ vue.runtime.esm.js:1388 -invoker @ vue.runtime.esm.js:10253 -list.uvue?t=1772068177429&import:1010 [Vue warn]: Property "insertImage" was accessed during render but is not defined on instance. - at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -warnHandler @ uni-h5.es.js:19975 -callWithErrorHandling @ vue.runtime.esm.js:1381 -warn$1 @ vue.runtime.esm.js:1207 -get @ vue.runtime.esm.js:4455 -(anonymous) @ list.uvue?t=1772068177429&import:1010 -renderFnWithContext @ vue.runtime.esm.js:2033 -renderSlot @ vue.runtime.esm.js:4254 -(anonymous) @ uni-h5.es.js:18666 -renderComponentRoot @ vue.runtime.esm.js:2092 -componentUpdateFn @ vue.runtime.esm.js:7444 -run @ vue.runtime.esm.js:153 -instance.update @ vue.runtime.esm.js:7497 -updateComponent @ vue.runtime.esm.js:7305 -processComponent @ vue.runtime.esm.js:7239 -patch @ vue.runtime.esm.js:6694 -patchKeyedChildren @ vue.runtime.esm.js:7650 -patchChildren @ vue.runtime.esm.js:7564 -processFragment @ vue.runtime.esm.js:7202 -patch @ vue.runtime.esm.js:6668 -patchKeyedChildren @ vue.runtime.esm.js:7650 -patchChildren @ vue.runtime.esm.js:7564 -patchElement @ vue.runtime.esm.js:6989 -processElement @ vue.runtime.esm.js:6825 -patch @ vue.runtime.esm.js:6682 -componentUpdateFn @ vue.runtime.esm.js:7453 -run @ vue.runtime.esm.js:153 -instance.update @ vue.runtime.esm.js:7497 -updateComponent @ vue.runtime.esm.js:7305 -processComponent @ vue.runtime.esm.js:7239 -patch @ vue.runtime.esm.js:6694 -patchKeyedChildren @ vue.runtime.esm.js:7650 -patchChildren @ vue.runtime.esm.js:7564 -processFragment @ vue.runtime.esm.js:7202 -patch @ vue.runtime.esm.js:6668 -patchKeyedChildren @ vue.runtime.esm.js:7650 -patchChildren @ vue.runtime.esm.js:7564 -patchElement @ vue.runtime.esm.js:6989 -processElement @ vue.runtime.esm.js:6825 -patch @ vue.runtime.esm.js:6682 -componentUpdateFn @ vue.runtime.esm.js:7453 -run @ vue.runtime.esm.js:153 -instance.update @ vue.runtime.esm.js:7497 -updateComponent @ vue.runtime.esm.js:7305 -processComponent @ vue.runtime.esm.js:7239 -patch @ vue.runtime.esm.js:6694 -patchKeyedChildren @ vue.runtime.esm.js:7650 -patchChildren @ vue.runtime.esm.js:7564 -processFragment @ vue.runtime.esm.js:7202 -patch @ vue.runtime.esm.js:6668 -patchKeyedChildren @ vue.runtime.esm.js:7650 -patchChildren @ vue.runtime.esm.js:7564 -patchElement @ vue.runtime.esm.js:6989 -processElement @ vue.runtime.esm.js:6825 -patch @ vue.runtime.esm.js:6682 -patchKeyedChildren @ vue.runtime.esm.js:7650 -patchChildren @ vue.runtime.esm.js:7564 -patchElement @ vue.runtime.esm.js:6989 -processElement @ vue.runtime.esm.js:6825 -patch @ vue.runtime.esm.js:6682 -patchKeyedChildren @ vue.runtime.esm.js:7650 -patchChildren @ vue.runtime.esm.js:7564 -patchElement @ vue.runtime.esm.js:6989 -processElement @ vue.runtime.esm.js:6825 -patch @ vue.runtime.esm.js:6682 -patchKeyedChildren @ vue.runtime.esm.js:7650 -patchChildren @ vue.runtime.esm.js:7564 -patchElement @ vue.runtime.esm.js:6989 -processElement @ vue.runtime.esm.js:6825 -patch @ vue.runtime.esm.js:6682 -componentUpdateFn @ vue.runtime.esm.js:7453 -run @ vue.runtime.esm.js:153 -instance.update @ vue.runtime.esm.js:7497 -updateComponent @ vue.runtime.esm.js:7305 -processComponent @ vue.runtime.esm.js:7239 -patch @ vue.runtime.esm.js:6694 -patchKeyedChildren @ vue.runtime.esm.js:7650 -patchChildren @ vue.runtime.esm.js:7564 -processFragment @ vue.runtime.esm.js:7202 -patch @ vue.runtime.esm.js:6668 -patchKeyedChildren @ vue.runtime.esm.js:7650 -patchChildren @ vue.runtime.esm.js:7564 -patchElement @ vue.runtime.esm.js:6989 -processElement @ vue.runtime.esm.js:6825 -patch @ vue.runtime.esm.js:6682 -componentUpdateFn @ vue.runtime.esm.js:7453 -run @ vue.runtime.esm.js:153 -instance.update @ vue.runtime.esm.js:7497 -updateComponent @ vue.runtime.esm.js:7305 -processComponent @ vue.runtime.esm.js:7239 -patch @ vue.runtime.esm.js:6694 -patchBlockChildren @ vue.runtime.esm.js:7084 -processFragment @ vue.runtime.esm.js:7176 -patch @ vue.runtime.esm.js:6668 -patchKeyedChildren @ vue.runtime.esm.js:7650 -patchChildren @ vue.runtime.esm.js:7564 -patchElement @ vue.runtime.esm.js:6989 -processElement @ vue.runtime.esm.js:6825 -patch @ vue.runtime.esm.js:6682 -componentUpdateFn @ vue.runtime.esm.js:7453 -run @ vue.runtime.esm.js:153 -instance.update @ vue.runtime.esm.js:7497 -updateComponent @ vue.runtime.esm.js:7305 -processComponent @ vue.runtime.esm.js:7239 -patch @ vue.runtime.esm.js:6694 -patchBlockChildren @ vue.runtime.esm.js:7084 -processFragment @ vue.runtime.esm.js:7176 -patch @ vue.runtime.esm.js:6668 -patchKeyedChildren @ vue.runtime.esm.js:7650 -patchChildren @ vue.runtime.esm.js:7564 -patchElement @ vue.runtime.esm.js:6989 -processElement @ vue.runtime.esm.js:6825 -patch @ vue.runtime.esm.js:6682 -componentUpdateFn @ vue.runtime.esm.js:7453 -run @ vue.runtime.esm.js:153 -instance.update @ vue.runtime.esm.js:7497 -callWithErrorHandling @ vue.runtime.esm.js:1381 -flushJobs @ vue.runtime.esm.js:1585 -Promise.then -queueFlush @ vue.runtime.esm.js:1494 -queueJob @ vue.runtime.esm.js:1488 -(anonymous) @ vue.runtime.esm.js:7491 -resetScheduling @ vue.runtime.esm.js:236 -triggerEffects @ vue.runtime.esm.js:280 -triggerRefValue @ vue.runtime.esm.js:1033 -set value @ vue.runtime.esm.js:1078 -closeDrawer @ list.uvue:314 -callWithErrorHandling @ vue.runtime.esm.js:1381 -callWithAsyncErrorHandling @ vue.runtime.esm.js:1388 -invoker @ vue.runtime.esm.js:10253 -list.uvue?t=1772068177429&import:1028 [Vue warn]: Property "onEditorReady" was accessed during render but is not defined on instance. - at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at -at at \ No newline at end of file diff --git a/services/api.js b/services/api.js new file mode 100644 index 00000000..ff368b70 --- /dev/null +++ b/services/api.js @@ -0,0 +1,42 @@ +// ⚠ Mock 数据,后续请替换成真实接口。 +import mockStore from "../stores/useMockData.js"; + +// 模拟网络延迟 +const delay = (ms = 500) => new Promise((resolve) => setTimeout(resolve, ms)); + +export const api = { + // 文章分类接口 + async getCategories() { + await delay(); + return { code: 200, data: mockStore.mockCategories, msg: "success" }; + }, + async addCategory(data) { + await delay(); + mockStore.addCategory(data); + return { code: 200, data: null, msg: "success" }; + }, + async updateCategory(id, data) { + await delay(); + mockStore.updateCategory(id, data); + return { code: 200, data: null, msg: "success" }; + }, + + // 文章接口 + async getArticles(page = 1, pageSize = 10) { + await delay(); + const total = mockStore.mockArticles.length; + const start = (page - 1) * pageSize; + const data = mockStore.mockArticles.slice(start, start + pageSize); + return { code: 200, data: { list: data, total }, msg: "success" }; + }, + async addArticle(data) { + await delay(); + mockStore.addArticle(data); + return { code: 200, data: null, msg: "success" }; + }, + async updateArticle(id, data) { + await delay(); + mockStore.updateArticle(id, data); + return { code: 200, data: null, msg: "success" }; + }, +}; diff --git a/stores/useMockData.js b/stores/useMockData.js new file mode 100644 index 00000000..786e652c --- /dev/null +++ b/stores/useMockData.js @@ -0,0 +1,92 @@ +// ⚠ Mock 数据,后续请替换成真实接口。 +import { reactive, watch } from "vue"; + +export const useMockData = () => { + // 从本地存储读取初始数据,如果没有则使用默认值 + const initialCategories = uni.getStorageSync("mockCategories") || [ + { id: 101, name: "分类 A", status: 1, sort: 1 }, + { id: 102, name: "分类 B", status: 1, sort: 2 }, + ]; + + const initialArticles = uni.getStorageSync("mockArticles") || [ + { + id: 1, + title: "文章 1", + summary: "摘要 1", + cover: "", + categoryId: 101, + content: "

富文本内容 1

", + }, + { + id: 2, + title: "文章 2", + summary: "摘要 2", + cover: "", + categoryId: 102, + content: "

富文本内容 2

", + }, + ]; + + const mockCategories = reactive(initialCategories); + const mockArticles = reactive(initialArticles); + + // 监听数据变化并保存到本地存储 + watch( + mockCategories, + (newVal) => { + uni.setStorageSync("mockCategories", JSON.parse(JSON.stringify(newVal))); + }, + { deep: true }, + ); + + watch( + mockArticles, + (newVal) => { + uni.setStorageSync("mockArticles", JSON.parse(JSON.stringify(newVal))); + }, + { deep: true }, + ); + + const addCategory = (category) => { + const newId = + mockCategories.length > 0 + ? Math.max(...mockCategories.map((c) => c.id)) + 1 + : 101; + mockCategories.push({ ...category, id: newId }); + }; + + const updateCategory = (id, category) => { + const index = mockCategories.findIndex((c) => c.id === id); + if (index !== -1) { + Object.assign(mockCategories[index], category); + } + }; + + const addArticle = (article) => { + const newId = + mockArticles.length > 0 + ? Math.max(...mockArticles.map((a) => a.id)) + 1 + : 1; + mockArticles.push({ ...article, id: newId }); + }; + + const updateArticle = (id, article) => { + const index = mockArticles.findIndex((a) => a.id === id); + if (index !== -1) { + Object.assign(mockArticles[index], article); + } + }; + + return { + mockCategories, + mockArticles, + addCategory, + updateCategory, + addArticle, + updateArticle, + }; +}; + +// 单例模式,确保全局共享状态 +const mockStore = useMockData(); +export default mockStore;