--- description: Element Plus 使用规范、权限控制与 Pinia 状态管理约定 globs: ["src/**/*.{vue,ts}", "src/styles/**/*.scss", "src/router/**/*.ts", "src/store/**/*.ts", "src/directives/**/*.ts"] --- # UI、权限与状态管理 ## Element Plus 1. 组件与图标通过 `unplugin-vue-components` / `unplugin-auto-import` **按需自动导入**;必须手动补充的(如 `ElMessage`、`ElMessageBox`、`ElLoading`)在 `src/types/element-plus.d.ts` 声明,禁止全量 `import ElementPlus from 'element-plus'`。 2. 消息提示统一使用 `ElMessage` / `ElMessageBox` / `ElNotification`,**禁止 `alert` / `confirm` 原生弹窗**。 - 成功 `ElMessage.success`,失败由拦截器统一处理,删除确认用 `ElMessageBox.confirm`。 - 同一操作不要堆叠多条 message。 3. 全局默认配置(size、zIndex、中文语言包)在 `main.ts` 或 `App.vue` 的 `ElConfigProvider` 中统一设置,不在每个组件重复传 `size`。 4. 表单统一 `label-width` 与布局:搜索栏 `inline`,弹窗表单 `label-position="right"`,标签宽度按项目约定(默认 `100px`)。 5. 表格空数据、图片加载失败等边界状态必须处理(`empty-text`、默认头像)。 6. 主题定制通过 `src/styles/element/index.scss` 覆盖 SCSS 变量,**禁止用 `!important` 打补丁**;确需覆盖内部样式时用 `:deep()` 且限定作用域。 ## 权限 1. 采用「动态路由 + 按钮级权限」双层控制: - 菜单/页面:后端返回路由表,前端 `router/index.ts` 中动态 `addRoute`,静态路由仅保留登录、404、首页。 - 按钮:`v-hasPerm="['sys:user:add']"` 指令,指令实现从用户 store 读取权限集合,无权限时**移除 DOM 节点**而非仅禁用。 2. 路由元信息 `meta` 字段固定:`title`、`icon`、`hidden`、`roles`、`keepAlive`、`breadcrumb`。 3. 路由守卫必须处理:已登录访问登录页跳转首页、无 Token 跳登录并携带 `redirect`、路由不存在跳 404。 4. 权限判断不得散落在业务代码里写字符串比较,统一走指令或 store 中的 `hasPermission()`。 ## Pinia 1. 一律使用 **setup store** 语法: ```ts export const useUserStore = defineStore('user', () => { const token = ref('') const permissions = ref([]) function resetToken() { token.value = '' } return { token, permissions, resetToken } }, { persist: true }) ``` 2. 一个业务域一个 store,放 `src/store/modules/{module}.ts`,index 统一导出。 3. 需要持久化的字段(token、主题、标签栏)必须显式声明 `persist` 路径,**禁止整个 store 无脑持久化**,敏感信息不落 localStorage。 4. 组件内不得直接修改其他模块的 store 状态,需通过该 store 暴露的 action。 5. 接口请求优先放 API 层;store 只做状态存放与跨组件共享,不承载大量业务过程。 ## 路由与页面缓存 - 页面组件 `name` 必须与路由 `name` 一致,否则 `` 的 `include/exclude` 失效。 - 列表页默认开启缓存;从详情页返回时保留查询条件,从菜单进入时重置。