pinia 通过结构化 state 管理看板拖拽布局,以 widgets 数组存储各组件 id、位置、尺寸、状态等元信息,配合 actions 封装增删改、移动、缩放及保存逻辑,实现跨组件共享、持久化存储与多端适配。

Pinia 管理数据看板组件拖拽布局的全局状态,核心是把「布局结构」作为可响应、可持久化、可跨组件同步的状态来设计。它不是单纯存几个坐标,而是建模为一个描述“哪些组件在哪、尺寸多少、是否锁定、是否隐藏”的结构化数据体系。
定义布局状态:用 state 描述看板结构
拖拽布局的本质是维护一组「面板(widget)」的位置与元信息。推荐用数组+对象组合方式建模,每个 widget 包含唯一 id、x/y/width/height、type、collapsed、locked 等字段:
- state 中用 ref 声明 widgets 数组,确保响应式更新
- 初始化时从 localStorage 或后端拉取默认布局,避免刷新丢失
- 支持动态增删 widget:添加时生成新 id;删除时过滤数组;拖拽调整时直接修改对应项的 x/y/width/height
封装拖拽逻辑:用 actions 统一处理变更
所有布局变更都应通过 actions 触发,而不是在组件中直接改 state —— 这样便于加校验、日志、防抖或批量提交:
- moveWidget(id, x, y):更新指定 widget 的位置,可加入边界限制(如不能拖出容器)
- resizeWidget(id, width, height):调整尺寸,支持最小宽高约束
- addWidget(config):插入新 widget,自动分配位置(比如追加到右下角空位)
- saveLayout():显式触发本地存储(配合 pinia-plugin-unistorage 或手动调用 uni.setStorageSync)
跨组件协同:让看板和子组件共享同一份状态
数据看板页面、拖拽指令(v-draggable)、配置弹窗、工具栏按钮,都应读写同一个 store:
- 看板容器用 store.widgets 渲染所有 widget,并监听 position 变化重排 DOM
- 每个 widget 子组件通过 props 接收自己的 id,再用 store.$state.find(w => w.id === props.id) 获取实时配置
- 配置弹窗打开时,直接读取并编辑 store 中对应 widget 的字段,关闭即生效,无需额外 emit 回传
- 工具栏的「保存」「重置」「全屏」按钮,全部调用 store 对应 actions,天然保持一致
持久化与多端适配(尤其 uni-app)
看板布局必须刷新不丢、小程序/H5/App 三端一致:
- uni-app 中务必使用 pinia-plugin-unistorage,并手动传入
uni.getStorageSync / setStorageSync适配器 - 不要依赖 pinia-plugin-persistedstate,它在小程序里会失效
- 对 layout state 开启 persist 配置,但排除临时字段(如 dragging: true、hover: false)
- 首次加载时若无本地数据,回退到预设的「默认看板模板」,而非空数组










