feat: 提交多个新UI组件模块spec和相关属性设定,包括卡片封装、渐变卡片、列式布局组件等,重写了readme.md,用于AI Coding
Some checks are pending
Call HTTPS API / build (push) Waiting to run

This commit is contained in:
2025-12-27 15:42:57 +08:00
parent fc9c726de4
commit 55abf26cfa
78 changed files with 3024 additions and 103 deletions

View File

@@ -0,0 +1,9 @@
# 00. 快速画像(给 AI 的 30 秒摘要)
- **技术栈**`Vue 3` + `Vue CLI 5` + `TypeScript` + `Pinia` + `Vue Router` + `Element Plus`
- **入口链路**`src/main.ts``setupVab(app)``setupI18n(app)``setupStore(app)``setupRouter(app)`
- **Mock**:开发环境由 `vue.config.js``mock/index.js` 挂载到 devServer 中间件;路由集合来自 `mock/controller/*`
- **别名**`@``src``@vab``library``~`→根目录,`/#``types`
- **用途定位**:既是可运行的后台 Demo也是可拆分的能力集合`library/layouts/ library/components/ library/ src/utils/ mock/ src/api/ types/`
> 推荐阅读顺序:本文件 → [01-Directory-Map.md](01-Directory-Map.md) → [AI-Reuse-Playbook.md](AI-Reuse-Playbook.md)

View File

@@ -0,0 +1,51 @@
# 01. 仓库地图Directory Map
> 目标:让 AI 快速定位“要复用的能力”在哪个目录、入口是什么、依赖闭包有哪些。
## `src/`(应用主代码)
- `src/main.ts`:应用入口;决定 mock/pwa 与各子系统初始化顺序
- `src/App.vue`:根组件;包含生产环境禁调试逻辑(`disable-devtool`
- `src/router/`:路由与权限控制(重点:`index.ts``permissions`
- `src/store/`Pinia 初始化与业务 store 模块
- `src/i18n/`:国际化初始化、语言获取与翻译辅助
- `src/api/`:按域拆分 API 调用函数(示例:`src/api/router.ts`
- `src/utils/`通用工具与基础能力时间格式化、树结构转换、UUID 等)
- `src/views/`:业务页面集合(通常与路由对应)
- `src/icon/`:图标加载(由 `library/index.ts` 里的 `import '@/icon'` 引入)
- `src/config/`:运行时/构建期配置聚合导出(`vue.config.js``require('./src/config')`
## `library/`(模板基础库)
- `library/index.ts``setupVab(app)` 的实现:
- 全局样式:`library/styles/vab.scss`
- 图标注册:`vab-icons` + `@element-plus/icons-vue`
- 背景样式:`library/styles/background/*.scss`
- 插件加载:`library/plugins/**/*.ts``app.use()`
- `library/build/`构建期扩展webpack chain、vue plugins
## `library/plugins/`(全局插件)
- `vab.ts`全局注入gp与事件总线`$pub/$sub/$unsub`
- `directive.ts`:指令(`v-permissions`
- `errorLog.ts`:全局错误捕获(`app.config.errorHandler`
- `support.ts`:构建信息输出/依赖检查
## `library/components/`(可复用 UI 组件库)
- `Vab*` 前缀:约定为基础组件/布局子组件菜单、tabs、header、breadcrumb 等)
- `VabTheme`:主题系统入口(主题抽屉/设置面板),依赖 `$pub/$sub` 与 settings store
## `library/layouts/`(布局体系)
- `library/layouts/index.vue`:主 Layout 入口(路由壳)
- `library/layouts/VabLayout*`:多套布局可选(垂直/横向/综合/浮动/分栏等)
## `mock/`(开发期 Mock
- `mock/index.js`devServer 中间件;读取并注册 `mock/controller/*`
- `mock/controller/*.js`:每个文件导出路由数组(`url/type/response`
## `types/`(类型声明)
- `types/*.d.ts`:路由/store/theme/vab 等声明,配合 `/#` 别名使用

View File

@@ -0,0 +1,28 @@
# 02. 关键入口与初始化顺序Boot Sequence
## 入口文件:`src/main.ts`
AI 需要知道“系统从哪里开始、按什么顺序挂载能力”。关键点:
1. `validateSecretKey()`:启动前校验(与授权/环境有关)
2. 生产环境 Mock
- 条件:`process.env.NODE_ENV === 'production'``baseURL` 不是外链(`!isExternal(baseURL)`
- 动作:`require('@/utils/static').mockXHR()`
3. 初始化链路:
- `setupVab(app)`(全局样式、图标、插件)
- `setupI18n(app)`
- `setupStore(app)`
- `setupRouter(app).isReady().then(mount)`
## 全局插件聚合:`library/index.ts`
`setupVab(app)` 做了这些事:
- 引入全局样式:`library/styles/vab.scss`
- 注册图标:
- `VabIcon`(来自 `vab-icons`
- `@element-plus/icons-vue` 全量组件注册
- 自动加载背景样式:`library/styles/background/*.scss`
- 自动加载插件:`library/plugins/**/*.ts`(默认导出 Vue 插件)
> 复用提示:自动全量加载在“抽取模块”时容易带入不必要依赖;迁移时应以“最小闭包”为原则(见 [AI-Reuse-Playbook.md](AI-Reuse-Playbook.md))。

View File

@@ -0,0 +1,23 @@
# 03. Mock 系统(开发联调与脱网演示)
## 挂载方式
- `vue.config.js``devServer.setupMiddlewares = require('./mock')`
- `mock/index.js`
- 将路由集合转换为 express 形式
- 使用 `mockjs` 返回数据
- 监听 `mock/` 变更并热更新(`chokidar`
## 路由定义约定(供 AI 生成/扩展)
`mock/controller/*.js` 中,每个路由对象通常包含:
- `url`:不含 `baseURL` 前缀的路径(中间件会自动拼上 `baseURL`
- `type``get` / `post` / ...
- `response(req, res)`:返回对象或函数
## AI 新增业务 API 的推荐动作
1) 在 `src/api/<domain>.ts` 新增函数(调用 `request({ url, method })`
2) 在 `mock/controller/<domain>.js` 新增对应 mock 路由,路径保持一致
3) 在模块规格中补充接口契约(建议写到 `openspec-lite/modules/<domain>.yaml`

View File

@@ -0,0 +1,46 @@
# 04. 路由与页面组织Router & Views
- 路由文件:`src/router/index.ts`
- 核心结构:
- `constantRoutes`:登录/注册/404 等公共路由
- `asyncRoutes`:业务路由,通常以 `Layout` 为根节点容器
## Views 目录约定src/views
本仓库页面主要集中在:
- `src/views/index/`:工作台/仪表盘等示例首页
- `src/views/vab/`:组件/表单/表格等示例页(演示用途居多)
- `src/views/other/`杂项示例页iframe/excel/drag/nested 等)
- `src/views/setting/`:后台管理相关页面(用户/角色/部门/菜单/字典/任务/日志等)
- `src/views/tools/`:工具类页面(如 EyeDropper/SpeechSynthesis
- `src/views/login/``src/views/register/``src/views/callback/`:登录链路
- `src/views/403.vue``src/views/404.vue`:错误页
路由对页面的引用方式以动态导入为主:`component: () => import('@/views/...')`
## meta 约定(给菜单/面包屑/行为用)
常见 meta 字段(与组件实现强相关):
- `meta.title`:菜单/面包屑/页面标题(`VabLanguage` 会用它更新 `document.title`
- `meta.icon` + `meta.isCustomSvg`:菜单与面包屑图标(`VabMenu`/`VabBreadcrumb`
- `meta.hidden`:是否从菜单隐藏(`VabMenu`
- `meta.breadcrumbHidden`:是否从面包屑隐藏(`VabBreadcrumb`
- `meta.noColumn`Column 布局下的特殊处理(`VabColumnBar` 会折叠菜单并隐藏 fold 按钮)
- `meta.target`(如 `_blank`):点击菜单时打开方式(`VabMenuItem`
- `meta.badge` / `meta.dot`:菜单右侧标记(`VabMenuItem`
## AI 生成新模块页面的最小流程
-`src/views/<module>/` 创建页面组件
-`src/router/index.ts`(或其拆分文件)添加路由记录
- 如涉及权限/菜单:同步 `meta``title/icon/guard/...`
建议:新增页面后运行一次 [AI-Coding/Validation.md](AI-Coding/Validation.md) 里的“router ↔ views 对账”脚本,防止路由引用了不存在的 .vue或新页面忘记挂到路由上。
## 验收点
- 访问路由能渲染页面
- 菜单与面包屑符合 `meta` 约定
- 刷新后路由仍可恢复

16
AI-Coding/05-Store.md Normal file
View File

@@ -0,0 +1,16 @@
# 05. 状态管理Pinia Store
- `src/store/index.ts``createPinia()``app.use(pinia)`
- i18n 语言读取:`src/i18n/index.ts` 通过 `useSettingsStore(pinia)` 获取语言
## AI 提取/迁移注意
- 迁移 `src/store/index.ts` 时,通常也需要迁移:
- `src/store/modules/settings.ts`(见 `12-Settings-Store.md` / `openspec-lite/modules/store-settings.yaml`
- `src/store/modules` 下其它基础模块(见 `14-Store-Modules.md`
- 与其相关的类型(`types/`,即 `/#` 别名指向的目录)
## 验收点
- Store 能正常注入
- 关键 store如 settings能在不报错情况下读取

17
AI-Coding/06-i18n.md Normal file
View File

@@ -0,0 +1,17 @@
# 06. 国际化i18n
- 文件:`src/i18n/index.ts`
- 关键点:
- `legacy: false`Composition API 模式)
- 内置 `en``zh` 为空对象(等待补充)
- 提供 `translate(message)` 辅助函数
- 导出 Element Plus 语言包:`enLocale` / `zhLocale`
## 扩展建议
- 新增语言:在 `src/i18n/locales/` 添加 `xx.json` 并合并到 `messages`
## 验收点
- 切换语言后页面能按预期渲染
- Element Plus 语言包切换有效

17
AI-Coding/07-API.md Normal file
View File

@@ -0,0 +1,17 @@
# 07. API 层(请求封装与域拆分)
- 示例:`src/api/router.ts` 调用 `request({ url: '/router/getList', method: 'get' })`
- 请求封装:`src/utils/request.ts`axios 拦截器、token 注入、401/402/403 处理、错误提示)
- 刷新令牌:`src/api/refreshToken.ts`402 时重试队列)
- 请求异常入库:通过 `@vab/plugins/errorLog`(见 `library/plugins/errorLog.ts`
## AI 复用原则
- 以“域”为单位抽取:`src/api/<domain>.ts`
- 抽取前先定位 `request` 封装(通常在 `src/utils/request` 或相近位置)
- 若新项目变更 baseURL/token/error 规范,优先在规格里声明差异,然后再做迁移适配
## 验收点
- 基础请求能发起
- 错误处理与鉴权逻辑符合项目约束

View File

@@ -0,0 +1,20 @@
# 08. Alias 与类型(迁移必须同步)
## Alias
- `@``src`
- `~` → 根目录
- `/#``types`
- `@vab``library`
- `@gp``library/plugins/vab`
来源:`vue.config.js``tsconfig.json`
## 类型声明
- `types/*.d.ts`:路由/store/theme/vab 等声明
## 迁移到不同构建工具(如 Vite时的最低要求
- alias 需要在新工具里重新配置
- `types/` 需要进入 tsconfig 的 `include`

15
AI-Coding/09-Plop.md Normal file
View File

@@ -0,0 +1,15 @@
# 09. 代码生成Plop
- 文件:`plopfile.js`
- 生成器:`view` / `curd` / `component` / `mock&api`
运行:
```powershell
pnpm run template
```
## AI 使用建议
- 如果后续 AI 以“生成代码”为策略,可优先复用 plop 模板,而不是从零写
- 新增生成器前,先在 `openspec-lite/project.yaml` 里补充命名/目录约束

View File

@@ -0,0 +1,38 @@
# 10. Theme 系统VabTheme + settings
> 目标:让 AI 在抽取/复用 Layout 时,不会漏掉主题抽屉、事件总线与 settings 的主题变量闭包。
## 入口与组成
- 主题入口组件:`library/components/VabTheme/index.vue`
- 主题抽屉:`library/components/VabTheme/components/VabThemeDrawer.vue`
- 主题设置入口:`library/components/VabTheme/components/VabThemeSetting.vue`
- 主题状态与持久化:`src/store/modules/settings.ts`
## 关键机制
- 事件总线:通过 `library/plugins/vab.ts` 注入 `$pub/$sub/$unsub`
- 打开抽屉:`$pub('theme')`
- 随机换肤:`$pub('random-theme')`
- 主题应用:`useSettingsStore().updateTheme()`
- 动态 `require(@vab/styles/variables/vab-*-variables.module.scss)`
-`vab-` 前缀变量映射到 `--el-` CSS 变量
- 设置 `body` class`vab-theme-*`)与背景类
## 最小依赖闭包(抽取时必须带上)
- `library/components/VabTheme/`
- `src/store/modules/settings.ts`(至少 theme/showTheme/saveTheme/resetTheme/updateTheme
- `library/plugins/vab.ts`(提供 `$pub/$sub``$baseLoading`
- `library/styles/variables/`(所有 `vab-*-variables.module.scss`
- Element Plus + i18n组件内有 `translate()` 与 el-* 组件)
## 验收点smoke
- 触发 `$pub('theme')` 抽屉能打开/关闭
- 保存/重置主题后,刷新页面主题能持久化且变量生效
## 常见坑
- `updateTheme()` 使用 webpack 风格的动态 `require`:迁移到非 webpack 构建(如部分 Vite 场景)需要等效实现
- 主题抽屉/设置依赖事件总线注入:未安装 `vab` 插件时会“看起来渲染了但不工作”

View File

@@ -0,0 +1,29 @@
# 11. Plugins 系统library/plugins/*
> 目标:明确本仓库“全局注入能力/指令/错误处理”的来源,避免抽取组件时漏掉运行时注入。
## 插件目录
- `library/plugins/vab.ts`:全局 gp 注入 + mitt 事件总线(`$pub/$sub/$baseMessage/...`
- `library/plugins/directive.ts`:自定义指令(`v-permissions`
- `library/plugins/errorLog.ts`:全局错误捕获(`app.config.errorHandler`)并写入 store
- `library/plugins/support.ts`:构建信息输出与依赖存在性检查
## 安装方式
- 正常路径:`library/index.ts` 会自动加载 `library/plugins/**/*.ts``app.use()`setupVab 链路内)
- 抽取到目标项目:
- 若不复用 `library/index.ts` 的自动加载逻辑,需要在入口手动 `app.use(plugin)`
## 最小依赖闭包
- `vab.ts`:依赖 Element Plus 全局 APIElMessage/ElLoading/ElMessageBox/ElNotification+ lodash + mitt + `src/config`
- `directive.ts`:依赖 `src/utils/permission`hasPermission 及其权限数据来源)
- `errorLog.ts`:依赖 `src/store/modules/errorLog``src/config/errorLog`
- `support.ts`:依赖 `__APP_INFO__` 构建注入
## 验收点smoke
- `vab``$baseMessage('ok')` 能弹出 message`$pub/$sub` 能收发事件
- `directive`:模板中 `v-permissions` 不报错且能按权限生效
- `errorLog`:手动触发异常能写入 errorLog store

View File

@@ -0,0 +1,35 @@
# 12. Settings Store主题/布局等全局配置)
> 目标:把 Theme/Layout 的“根依赖”讲清楚,避免 AI 抽取时只搬组件却漏掉主题变量注入与持久化逻辑。
## 入口
- `src/store/modules/settings.ts``useSettingsStore`
## 管理的核心状态
- `theme`:包含 `layout/themeName/background/menuWidth/showTheme/showThemeSetting/tabsBarStyle...`
- `device``desktop | mobile`(布局响应式需要)
- `collapse`:侧边栏折叠状态
- `language`:国际化语言
## 关键动作
- `saveTheme()`:持久化 theme
- `resetTheme()`:恢复默认 theme并调用 `updateTheme()`
- `updateTheme()`
- 通过 `@vab/styles/variables/vab-*-variables.module.scss` 读取变量
-`vab-` 前缀映射到 `--el-`,动态写入 Element Plus CSS 变量
- 设置 body class`vab-theme-*`,并按 background 追加 class
- 设置 `--el-left-menu-width`
## 最小闭包Theme/Layout 抽取必须带上)
- `src/store/modules/settings.ts`
- `library/styles/variables/vab-*-variables.module.scss`
- `library/plugins/vab.ts`Theme 事件总线注入)
## 常见坑
- `updateTheme()` 使用 webpack 风格动态 `require`,迁移到非 webpack 构建器需要等效替代
- `useCssVar` 的导入方式依赖工程约定(自动导入 vs 显式 import

View File

@@ -0,0 +1,70 @@
# 13. 组件清单library/components
> 目的:让 AI 在新项目中“选组件/抽组件”时,先从**可复用目录清单**开始,避免漏组件或重复造轮子。
## 组件根目录
- `library/components/`(约定:每个 `Vab*` 目录是一组可复用组件)
## 当前组件目录(按仓库实际目录列出)
- `VabApp`:应用壳/全局 Provider
- `VabAppMain`:主内容区(与 Layout 配合)
- `VabAvatar`
- `VabBreadcrumb`
- `VabCard`
- `VabColorfulCard`
- `VabColumnBar`
- `VabErrorLog`
- `VabFold`
- `VabFooter`
- `VabFullScreen`
- `VabHeader`
- `VabLanguage`
- `VabLink`
- `VabLock`
- `VabLogo`
- `VabMenu`
- `VabNav`
- `VabNotice`
- `VabQueryForm`
- `VabRefresh`
- `VabRouterView`
- `VabSearch`
- `VabSideBar`
- `VabTabs`
- `VabTheme`
## 抽取建议(最小闭包)
- 优先使用任务模板:`openspec-lite/tasks/extract-component.yaml`
- 若组件涉及 Layout/Theme先抽 `layouts``vab-theme`,再补 `store-settings``plugin-vab`
高耦合组件规格(机读):
- `vab-app-main``openspec-lite/modules/vab-app-main.yaml`
- `vab-avatar``openspec-lite/modules/vab-avatar.yaml`
- `vab-breadcrumb``openspec-lite/modules/vab-breadcrumb.yaml`
- `vab-card``openspec-lite/modules/vab-card.yaml`
- `vab-colorful-card``openspec-lite/modules/vab-colorful-card.yaml`
- `vab-column-bar``openspec-lite/modules/vab-column-bar.yaml`
- `vab-router-view``openspec-lite/modules/vab-router-view.yaml`
- `vab-error-log``openspec-lite/modules/vab-error-log.yaml`
- `vab-fold``openspec-lite/modules/vab-fold.yaml`
- `vab-query-form``openspec-lite/modules/vab-query-form.yaml`
- `vab-refresh``openspec-lite/modules/vab-refresh.yaml`
- `vab-search``openspec-lite/modules/vab-search.yaml`
- `vab-lock``openspec-lite/modules/vab-lock.yaml`
- `vab-notice``openspec-lite/modules/vab-notice.yaml`
- `vab-logo``openspec-lite/modules/vab-logo.yaml`
- `vab-nav``openspec-lite/modules/vab-nav.yaml`
- `vab-language``openspec-lite/modules/vab-language.yaml`
- `vab-full-screen``openspec-lite/modules/vab-full-screen.yaml`
- `vab-footer``openspec-lite/modules/vab-footer.yaml`
- `vab-link``openspec-lite/modules/vab-link.yaml`
## 快速定位grep/语义检索)
- `library/components/<VabName>/index.vue`
- `VabThemeDrawer` / `VabThemeSetting`
- `VabMenu` / `VabTabs` / `VabSideBar`(通常与路由/权限/store 强相关)

View File

@@ -0,0 +1,32 @@
# 14. Store 模块清单src/store/modules
> 目的:让 AI 明确“权限/路由/主题/标签页”等基础能力分别由哪个 store 提供,抽取时不遗漏。
## 模块列表(按仓库实际文件列出)
- `acl.ts`:角色/权限/admin配合 `hasPermission()`
- `errorLog.ts`:错误日志收集(配合 `library/plugins/errorLog.ts`
- `routes.ts`:路由模式/菜单路由设置(前端/后端路由切换)
- `settings.ts`:主题/布局/语言/折叠等全局配置(见 `12-Settings-Store.md`
- `tabs.ts`:标签页 visitedRoutes 管理
- `user.ts`:登录/用户信息/登出/重置(联动 acl/routes/tabs/settings
对应模块规格(机读):
- `access-control``openspec-lite/modules/access-control.yaml`(覆盖 acl + hasPermission + 指令)
- `store-errorlog``openspec-lite/modules/store-errorlog.yaml`
- `store-routes``openspec-lite/modules/store-routes.yaml`
- `store-settings``openspec-lite/modules/store-settings.yaml`
- `store-tabs``openspec-lite/modules/store-tabs.yaml`
- `store-user``openspec-lite/modules/store-user.yaml`
## 最小依赖闭包提示
- 权限链路:`acl.ts` + `src/utils/permission.ts` + `library/plugins/directive.ts`
- 路由链路:`routes.ts` + `src/router/*` + `src/utils/routes.ts` +(可选)`src/api/router.ts`
- 主题链路:`settings.ts` + `library/styles/variables/vab-*-variables.module.scss`
## 验收点smoke
- 能创建 Pinia 并正常读取 settings/acl/user 等 store
- `hasPermission()` 能按 acl 状态返回布尔值

115
AI-Coding/15-Snippet-Map.md Normal file
View File

@@ -0,0 +1,115 @@
# 15. 代码段地图Snippet Map
> 目的:给后续 AI coding 的“最常用代码段”提供**稳定来源与检索方式**,直接指向文件/关键词。
## 初始化与自动加载
- `setupVab(app)``library/index.ts`
- 背景 SCSS 自动加载:`require.context('./styles/background', false, /\\.scss$/)`
- 插件自动加载:`require.context('./plugins', true, /\\.ts$/)` + `app.use(Plugins(key).default)`
## Theme主题
- 打开抽屉事件:`$pub('theme')``library/components/VabTheme/*`
- 随机换肤事件:`$pub('random-theme')`
- 主题变量注入:`useSettingsStore().updateTheme()``src/store/modules/settings.ts`
- scss module 来源:`@vab/styles/variables/vab-*-variables.module.scss`
## Plugins全局注入/事件总线/指令)
- 事件总线注入:`$pub/$sub/$unsub``library/plugins/vab.ts`
- 权限指令:`v-permissions``library/plugins/directive.ts`
- 权限判断:`hasPermission()``src/utils/permission.ts`
## IconsSVG
- SVG 自动加载:`require.context('.', true, /\\.svg$/)``src/icon/index.ts`
## Router/Routes
- 后端路由转换:`convertRouter()``src/utils/routes.ts`
- 路由模式切换:`authentication === 'all'``src/store/modules/routes.ts`
- 过滤可访问路由:`filterRoutes([...constantRoutes, ...routes], control)``src/store/modules/routes.ts`
- 重置路由:`resetRouter(accessRoutes)``src/store/modules/routes.ts` / `src/router`
## Router Permissions
- 路由守卫入口:`setupPermissions(router)``src/router/permissions.ts`
- 白名单/登录拦截开关:`routesWhiteList` / `loginInterception` / `authentication``src/router/permissions.ts` / `src/config`
- 更新标题:`document.title = getPageTitle(to.meta.title)``src/router/permissions.ts`
## Config
- 配置聚合入口:`module.exports = { ...cli, ...setting, ...theme, ...network }``src/config/index.js`
- 路由/登录关键开关:`authentication/loginInterception/routesWhiteList/supportVisit``src/config/setting.config.js`
- 菜单关键开关:`defaultOpeneds/uniqueOpened/openFirstMenu``src/config/setting.config.js`
- 网络请求关键开关:`baseURL/successCode/statusName/messageName/requestTimeout``src/config/net.config.js`
## Router View
- 刷新当前视图缓存:`$sub('reload-router-view', ...)``library/components/VabRouterView/index.vue`
## Menu
- 点击当前菜单刷新:`$pub('reload-router-view')``library/components/VabMenu/components/VabMenuItem.vue`
## Refresh
- 刷新按钮触发:`$pub('reload-router-view')``library/components/VabRefresh/index.vue`
## Search
- 打开搜索快捷键:`ctrlKey/metaKey + 'k'``library/components/VabSearch/index.vue`
- 历史记录 key`vab_search_history``library/components/VabSearch/index.vue`
## Lock
- 锁屏开关:`handleLock()` / `handleUnLock()``library/components/VabLock/index.vue`
- 直接操作侧边栏:`document.querySelector('.vab-side-bar')``library/components/VabLock/index.vue`
## Notice
- 拉取通知:`getList()``library/components/VabNotice/index.vue` / `src/api/notice.ts`
## Language
- 语言切换:`useI18n().locale` / `changeLanguage(``library/components/VabLanguage/index.vue` / `src/store/modules/settings.ts`
- 切换后更新标题:`getPageTitle(``library/components/VabLanguage/index.vue` / `src/utils/pageTitle.ts`
## FullScreen
- 全屏切换:`useFullscreen().toggle``library/components/VabFullScreen/index.vue`
## Footer
- 页脚标题来源:`settings.title``library/components/VabFooter/index.vue` / `src/store/modules/settings.ts`
## Nav/Breadcrumb
- 顶部导航聚合:`<vab-nav />``library/components/VabNav/index.vue`
- 面包屑生成:`handleMatched(``library/components/VabBreadcrumb/index.vue` / `src/utils/routes.ts`
## Column Bar
- Column 二级菜单:`partialRoutes` + `defaultOpeneds``library/components/VabColumnBar/index.vue` / `src/store/modules/routes.ts` / `src/config`
## Avatar/Logo
- 用户下拉退出:`case 'logout'` + `toLoginRoute(route.fullPath)``library/components/VabAvatar/index.vue` / `src/utils/routes.ts`
- Logo/Title 来源:`logo/title``library/components/VabLogo/index.vue` / `src/store/modules/settings.ts`
## Link/Fold/Card
- 外链/内链切换:`isExternal(props.to)``library/components/VabLink/index.vue` / `src/utils/validate.ts`
- 折叠按钮:`toggleCollapse``library/components/VabFold/index.vue` / `src/store/modules/settings.ts`
- Skeleton 卡片:`el-skeleton``library/components/VabCard/index.vue`
## User/Auth
- 登出重置闭包:`resetAll()``src/store/modules/user.ts`,联动 acl/routes/tabs/resetRouter/removeToken
## API/Request
- axios 实例与拦截器:`axios.create` / `instance.interceptors``src/utils/request.ts`
- 401/402/403 分支:`case 401` / `case 402` / `case 403``src/utils/request.ts`
- token 注入:`Authorization: Bearer``src/utils/request.ts`

View File

@@ -0,0 +1,76 @@
# 16. Config Key Mapsrc/config
> 目的:让 AI 在迁移/新项目开发时,明确“哪些行为由哪些 config key 控制”,并能快速定位 key 的定义与使用点。
## 聚合入口
- `src/config/index.js` 会把 4 份配置聚合导出:
- `cli.config.js`(构建/CLI 相关)
- `setting.config.js`(通用/登录/路由/菜单/缓存等)
- `theme.config.js`(主题与 UI 开关默认值)
- `net.config.js`(网络请求相关)
注意:`src/config/*` 可能会被 `vue.config.js` 在 Node 环境 `require()` 读取,因此配置文件应避免使用 `window/document`
## 高影响 keys按子系统分组
### 路由/权限/登录
- `authentication`:路由模式(`intelligence` 前端路由 / `all` 后端路由)
- `loginInterception`:是否开启登录拦截(影响 `setupPermissions` 行为)
- `routesWhiteList`:白名单路由(不校验 token
- `supportVisit`:游客模式
- `rolesControl`:是否按 `roles` 字段进行角色控制
- `isHashRouterMode`hash/history 模式相关逻辑(菜单里对 `_blank` 打开内部路由有分支)
- `publicPath`:路由/跳转时可能需要的 publicPath
### Token/存储
- `tokenName`token 字段名
- `tokenTableName`:存储 key 名
- `storage``localStorage/sessionStorage/cookie`
- `recordRoute`token 失效回到登录页时是否记录本次路由
### 页面标题
- `title`:系统标题(影响 `getPageTitle`/浏览器标题/雪花屏标题等)
- `titleSeparator`:标题分隔符
- `titleReverse`:标题是否反转
### 菜单/导航体验
- `uniqueOpened`:是否只保持一个子菜单展开
- `defaultOpeneds`:默认展开菜单 path 列表
- `openFirstMenu`:是否点击一级菜单默认开启二级菜单
- `debounce`:需要加 loading 层防重复提交的请求标识列表
- `keepAliveMaxNum`keep-alive 最大缓存数量
### Theme 默认值与开关theme.config.js
- 默认值:`layout/themeName/background/menuWidth/columnStyle/...`
- UI 开关:`showProgressBar/showTabs/showLanguage/showRefresh/showSearch/showTheme/showNotice/showFullScreen/showThemeSetting/showLock/...`
### 网络请求net.config.js
- `baseURL` / `contentType` / `requestTimeout`
- `successCode` / `statusName` / `messageName`
### 构建/CLIcli.config.js
- `devPort/outputDir/assetsDir/publicPath`
- `pwa/buildOptimize/noDebugger/lintOnSave`
## 常见使用点(快速定位)
- 路由守卫:`src/router/permissions.ts``authentication/loginInterception/routesWhiteList/supportVisit` + `showProgressBar`
- Router 定义:`src/router/index.ts``authentication/isHashRouterMode/publicPath`
- 菜单:`library/components/VabMenu/components/VabMenuItem.vue``isHashRouterMode`
- 路由 store`src/store/modules/routes.ts``authentication/rolesControl`
- 标题工具:`src/utils/pageTitle.ts``titleSeparator/titleReverse`
- token 工具:`src/utils/token.ts``storage/tokenTableName`
- request`src/utils/request.ts``baseURL/successCode/statusName/messageName/requestTimeout/contentType` 等)
## 迁移/复用提示(最小闭包)
-`router`/`request`/`menu` 等模块时,**优先把 `src/config/*` 一并带走**,避免 key 缺失导致行为变化。
- 如果目标项目要改 key 名或改配置来源(例如改成 `.env` 或远端配置),建议先在规格里写清“映射关系”和“验收点”。

View File

@@ -0,0 +1,54 @@
# AI 复用操作手册(轻量化)
> 目标:在“不改动现有代码”的前提下,用文档约束 AI 从本仓库抽取能力,并确保抽取结果可验证。
## A. 选模块(先确定要什么)
在开始任何代码生成/迁移前AI 必须先回答:
- 我要复用的能力类型:`layout | component | plugin | util | store | i18n | api | mock | config`
- 复用方式:`copy-snippet`(复制片段)或 `copy-module`(整目录)
- 目标项目构建工具:`Vue CLI` / `Vite` / 其他
> 推荐:优先 `copy-module`(减少遗漏依赖),再做裁剪。
## B. 定位入口(必须列出入口文件)
- 全局能力:`library/index.ts``setupVab`
- 初始化:`src/main.ts`
- 路由:`src/router/index.ts`
- 状态:`src/store/index.ts`
- i18n`src/i18n/index.ts`
- Mock`mock/index.js`
AI 输出中必须包含:入口文件列表 + 为什么需要它们。
## C. 最小闭包(必须列出依赖闭包)
AI 必须同时列出:
- 直接依赖import 的文件/包)
- 运行时依赖例如全局样式、icons、插件自动加载
- 类型依赖(`types/` 目录与 `/#`
- alias 依赖(`@``@vab``~``/#`
> 如果依赖闭包不清晰,禁止直接迁移;应先补规格(见 `openspec-lite/`)。
## D. 迁移后验收(必须可执行)
最低验收:
- `pnpm run serve` 能启动
- 页面可渲染
- 路由能跳转
- i18n/store 能注入
- Mock若启用能命中
## E. 输出格式(给 OpenSpec/AI 工具链用)
当 AI 完成一次抽取/复用任务时,输出必须包含:
- **变更文件清单**(新增/修改/删除)
- **复用模块清单**(从哪里来、被用在何处)
- **验收命令**lint/test/build/serve
- **风险说明**可能破坏的点alias、插件自动加载、生产 mock 等)

8
AI-Coding/Pitfalls.md Normal file
View File

@@ -0,0 +1,8 @@
# 已知陷阱与迁移雷区Pitfalls
- **生产环境禁调试**`src/App.vue` 使用 `disable-devtool`,可能影响某些测试/调试环境。
- **生产环境默认 Mock**`src/main.ts` 中存在“生产启用 mockXHR”的逻辑做真实项目发布时要确认策略。
- **配置入口**`vue.config.js` 通过 `require('./src/config')` 读取配置;`src/config/index.js` 会聚合导出多个子配置。
- **自动插件加载**`library/index.ts``require.context('./plugins', true, /\\.ts$/)` 全量加载;抽取模块时容易带入不需要依赖。
> 对应的约束与处理建议:见 [openspec-lite/project.yaml](openspec-lite/project.yaml)。

56
AI-Coding/README.md Normal file
View File

@@ -0,0 +1,56 @@
# AI-CodingAI 取材与约束入口)
> 本目录是“轻量化模板库”形态下的 AI 指南:**不改动现有业务代码**,尽量用文档与规格约束引导 OpenSpec 开发模式的 AI 快速、准确地复用本仓库能力。
## 你应该从这里开始读
1. [00-Quick-Profile.md](00-Quick-Profile.md) —— 30 秒摘要栈、入口链路、Mock、alias
2. [01-Directory-Map.md](01-Directory-Map.md) —— 仓库地图(模块在哪、职责是什么)
3. [02-Boot-Sequence.md](02-Boot-Sequence.md) —— 初始化链路(`src/main.ts` / `setupVab`
4. [10-Theme-System.md](10-Theme-System.md) —— Theme 系统VabTheme + settings + 变量注入)
5. [11-Plugins-System.md](11-Plugins-System.md) —— Pluginsgp 注入/指令/错误捕获)
6. [12-Settings-Store.md](12-Settings-Store.md) —— Settings Store主题/布局等全局配置)
7. [13-Component-Inventory.md](13-Component-Inventory.md) —— 组件清单library/components
8. [14-Store-Modules.md](14-Store-Modules.md) —— Store 模块清单src/store/modules
9. [15-Snippet-Map.md](15-Snippet-Map.md) —— 代码段地图(常用片段稳定来源)
10. [16-Config-Keys.md](16-Config-Keys.md) —— Config keys 地图(高影响开关与使用点)
11. [AI-Reuse-Playbook.md](AI-Reuse-Playbook.md) —— AI 复用操作手册(最小闭包、迁移步骤、验收)
12. [Pitfalls.md](Pitfalls.md) —— 已知陷阱与迁移雷区
## OpenSpec-lite轻量规格
- [openspec-lite/project.yaml](openspec-lite/project.yaml) —— 项目级约束(技术栈/目录/禁止项/验收门槛)
- [openspec-lite/manifest.yaml](openspec-lite/manifest.yaml) —— 模块清单(供 AI 选模块与定位)
- [openspec-lite/tasks/](openspec-lite/tasks/) —— 任务模板AI 按模板输出文件与验收项)
- [openspec-lite/modules/](openspec-lite/modules/) —— 模块规格(按需逐步补全;先从高频模块开始)
推荐从这些高频模块规格开始:
- `setup-vab``openspec-lite/modules/setup-vab.yaml`
- `config-system``openspec-lite/modules/config-system.yaml`
- `api-system``openspec-lite/modules/api-system.yaml`
- `icons``openspec-lite/modules/icons.yaml`
- `styles``openspec-lite/modules/styles.yaml`
- `access-control``openspec-lite/modules/access-control.yaml`
- `layouts``openspec-lite/modules/layouts.yaml`
- `ui-components``openspec-lite/modules/ui-components.yaml`
- `store-settings``openspec-lite/modules/store-settings.yaml`
- `vab-theme``openspec-lite/modules/vab-theme.yaml`
- `plugin-vab``openspec-lite/modules/plugin-vab.yaml`
- `plop``openspec-lite/modules/plop.yaml`
- `plugin-directive``openspec-lite/modules/plugin-directive.yaml`
- `plugin-errorlog``openspec-lite/modules/plugin-errorlog.yaml`
- `plugin-support``openspec-lite/modules/plugin-support.yaml`
- `VabApp``openspec-lite/modules/vab-app.yaml`
- `VabMenu``openspec-lite/modules/vab-menu.yaml`
- `VabTabs``openspec-lite/modules/vab-tabs.yaml`
- `VabHeader``openspec-lite/modules/vab-header.yaml`
- `VabSideBar``openspec-lite/modules/vab-sidebar.yaml`
更多模块(例如 `store-user` / `store-routes` / `store-tabs` / `store-errorlog`)已收录在 `openspec-lite/manifest.yaml` 中,可按需从清单选取。
## 本目录的“轻量化原则”
- **不要求改代码**:所有约束优先通过文档/规格落地;如必须改代码,应先在规格里写明原因与影响面。
- **先可用,再完美**:优先把“模块定位、最小闭包、验收门槛”写清楚。
- **一切可检索**:每份文档都应包含明确关键词与入口文件路径,方便 AI 语义检索/grep。

View File

@@ -0,0 +1,40 @@
# 可供 AI 检索的关键锚点Search Anchors
> 这些关键词可用于语义检索或 grep。
- 入口:`createApp(App)``setupVab(app)``setupRouter(app).isReady()`
- setupVab`require.context('./plugins'``require.context('./styles/background'``app.component('VabIcon'``createHead()`
- Mock`setupMiddlewares: require('./mock')``mockjs``responseFake`
- Alias`alias``@vab``/#`
- i18n`createI18n({ legacy: false })``translate(`
- Store`createPinia()``useSettingsStore(pinia)`
- Routes Store`setRoutes(``filterRoutes(``resetRouter(`
- Router/Views`component: () => import('@/views/``constantRoutes``asyncRoutes``breadcrumbHidden``noColumn``isCustomSvg``meta.target``meta.badge``meta.dot`
- Router Guard`setupPermissions(``router.beforeEach``routesWhiteList``loginInterception``authentication``supportVisit``VabProgress.start()``document.title = getPageTitle`
- User Store`getUserInfo(``resetAll(``removeToken(`
- Tabs Store`visitedRoutes``noClosable`
- RouterView`reload-router-view``keepAliveNameList``<keep-alive :include=`
- Refresh`theme.showRefresh``$pub('reload-router-view')`
- Search`Ctrl+K``vab_search_history``flattenMenus(``teleport to="body"`
- Lock`theme.showLock``settings.lock``.vab-side-bar``handleUnLock`
- Menu`menuComponent``VabSubMenu``VabMenuItem``inject('$pub')``reload-router-view``isHashRouterMode``teleported=false`
- Notice`api/notice``getList()``theme.showNotice``notice-popover``清空消息成功`
- Language`theme.showLanguage``useI18n().locale``changeLanguage(``getPageTitle(`
- FullScreen`theme.showFullScreen``useFullscreen()``isFullscreen``toggle()`
- Footer`vab-footer``$base-padding``$base-border-color`
- Avatar`useUserStore()``toLoginRoute(``command="logout"``/setting/personalCenter`
- Breadcrumb`handleMatched(``breadcrumbHidden``el-breadcrumb-item`
- Nav`layout === 'comprehensive'``openFirstMenu``tabMenu.value.path``<vab-breadcrumb`
- ColumnBar`theme.layout === 'column'``route.meta.noColumn``partialRoutes``defaultOpeneds`
- Logo`settingsStore``logo``is-custom-svg``theme.layout`
- Link`isExternal(``rel: 'noopener'``router-link`
- Fold`toggleCollapse``collapse ? 'menu-unfold-line'`
- Card`el-skeleton``skeletonRows``onBeforeRouteLeave`
- Theme`updateTheme()``vab-*-variables.module.scss``$pub('theme')``$pub('random-theme')`
- Plugins`app.config.globalProperties``app.provide(``v-permissions``app.config.errorHandler`
- ACL`useAclStore``hasPermission(`
- Icons`require.context('.', true, /\\.svg$/)`
- Config`require('./src/config')``src/config/index.js`
- Config Keys`authentication``loginInterception``routesWhiteList``supportVisit``rolesControl``isHashRouterMode``defaultOpeneds``uniqueOpened``openFirstMenu``tokenTableName``storage``titleSeparator``titleReverse`
- API`src/utils/request.ts``axios.create``instance.interceptors``refreshToken``Authorization: Bearer`
- Plop`plop.setGenerator``plopfile.js``plop-templates/`

104
AI-Coding/Validation.md Normal file
View File

@@ -0,0 +1,104 @@
# 最小验证Validation
在本仓库验证:
```powershell
pnpm i
pnpm run serve
```
迁移到新仓库后,至少验证:
- 首页可渲染Layout 正常)
- 路由跳转正常
- Pinia 与 i18n 可注入
- Mock 请求可命中(开发环境)
建议附加:
```powershell
pnpm run lint
pnpm run test:unit
pnpm run build
```
## 文档/清单对账(防止漏登记模块)
对账 `library/components/*` 是否都已登记到 `AI-Coding/openspec-lite/manifest.yaml`
```powershell
$repo = (Get-Location).Path;
$componentDirs = Get-ChildItem -LiteralPath "$repo\library\components" -Directory | Select-Object -ExpandProperty Name | Sort-Object;
$manifest = Get-Content -LiteralPath "$repo\AI-Coding\openspec-lite\manifest.yaml" -Raw;
$manifestComponents = [regex]::Matches($manifest,'library/components/(?<name>Vab[^/]+)/') | ForEach-Object { $_.Groups['name'].Value } | Sort-Object -Unique;
Compare-Object -ReferenceObject $componentDirs -DifferenceObject $manifestComponents
```
对账 `library/layouts/*` 子目录是否都被 `AI-Coding/openspec-lite/modules/layouts.yaml` 覆盖:
```powershell
$repo = (Get-Location).Path;
$layoutDirs = Get-ChildItem -LiteralPath "$repo\library\layouts" -Directory | Select-Object -ExpandProperty Name | Sort-Object;
$layoutsSpec = Get-Content -LiteralPath "$repo\AI-Coding\openspec-lite\modules\layouts.yaml" -Raw;
$specDirs = [regex]::Matches($layoutsSpec,'library/layouts/(?<name>VabLayout[^/]+)/') | ForEach-Object { $_.Groups['name'].Value } | Sort-Object -Unique;
Compare-Object -ReferenceObject $layoutDirs -DifferenceObject $specDirs
```
对账 `components.d.ts` 里自动导入的 `Vab*` 组件是否都被任一 module spec 覆盖(按源文件路径精确匹配):
```powershell
$repo = (Get-Location).Path;
$dtsPath = "$repo\library\build\vuePlugins\components.d.ts";
$specDir = "$repo\AI-Coding\openspec-lite\modules";
$dts = Get-Content -LiteralPath $dtsPath -Raw;
$specText = (Get-ChildItem -LiteralPath $specDir -Filter '*.yaml' | ForEach-Object { Get-Content -LiteralPath $_.FullName -Raw }) -join "`n---`n";
$imports = [regex]::Matches(
$dts,
"Vab[A-Za-z0-9_]+:\\s*typeof\\s+import\\('(?<p>[^']+)'\\)\\['default'\\]",
[System.Text.RegularExpressions.RegexOptions]::Multiline
) | ForEach-Object { $_.Groups['p'].Value } | Where-Object { $_ -like '*components*' } | ForEach-Object {
$p = $_;
$p = $p -replace "^\\./\\.\\./\\.\\./","";
$p = $p -replace "^\\./\\.\\./","";
$p = $p -replace "^\\./","";
if ($p -like 'components/*') { $p = "library/" + $p }
$p
} | Sort-Object -Unique;
$missing = foreach ($p in $imports) { if ($specText -notmatch [regex]::Escape($p)) { $p } };
if ($missing) { $missing } else { '(none)' }
```
对账 `src/router/index.ts` 引用的 `@/views/*.vue` 是否都存在,并列出未被路由引用的 views
```powershell
$repo = (Get-Location).Path;
$routerPath = "$repo\src\router\index.ts";
$viewsRoot = "$repo\src\views";
$router = Get-Content -LiteralPath $routerPath -Raw;
# 只提取“非注释行”中的 views 引用,避免把 // 注释的 demo 路由当成缺失文件
$routeViewRefs = [regex]::Matches(
$router,
"(?m)^(?!\\s*//).*@/views/(?<p>[^'\\\"\\)]+\\.vue)",
[System.Text.RegularExpressions.RegexOptions]::Multiline
) | ForEach-Object { $_.Groups['p'].Value } | Sort-Object -Unique;
$missingFiles = foreach ($p in $routeViewRefs) {
$abs = Join-Path $viewsRoot ($p -replace '/', '\\');
if (-not (Test-Path -LiteralPath $abs)) { "src/views/$p" }
};
$allViews = Get-ChildItem -LiteralPath $viewsRoot -Recurse -File -Filter '*.vue' | ForEach-Object {
$_.FullName.Substring($viewsRoot.Length + 1).Replace('\\','/')
} | Sort-Object -Unique;
$unreferenced = Compare-Object -ReferenceObject $allViews -DifferenceObject $routeViewRefs -PassThru | Where-Object { $_ -in $allViews } | Sort-Object;
'--- router references missing files ---';
if ($missingFiles) { $missingFiles } else { '(none)' };
'--- views not referenced by router ---';
if ($unreferenced) { $unreferenced | ForEach-Object { "src/views/$_" } } else { '(none)' };
```

View File

@@ -0,0 +1,414 @@
# OpenSpec-lite: 模块清单(可逐步补全)
# 目的:让 AI 在“选模块”阶段就能定位入口与主要依赖。
modules:
- id: boot
name: 应用入口与初始化
type: core
entrypoints:
- src/main.ts
- library/index.ts
keywords:
- createApp
- setupVab
- setupI18n
- setupStore
- setupRouter
- id: setup-vab
name: setupVablibrary/index.ts 自动加载/图标/样式/插件)
type: core
entrypoints:
- library/index.ts
- library/plugins/
- library/styles/
- src/icon/index.ts
keywords:
- require.context
- VabIcon
- createHead
- id: router
name: 路由与权限
type: core
entrypoints:
- src/router/index.ts
- src/router/permissions.ts
keywords:
- constantRoutes
- asyncRoutes
- meta
- id: store
name: Pinia 状态
type: core
entrypoints:
- src/store/index.ts
- src/store/modules
keywords:
- createPinia
- id: store-settings
name: Settings Store主题/布局等全局配置)
type: store
entrypoints:
- src/store/modules/settings.ts
- library/styles/variables/
keywords:
- updateTheme
- themeName
- menuWidth
- id: store-routes
name: Routes Store路由拦截/菜单路由设置)
type: store
entrypoints:
- src/store/modules/routes.ts
keywords:
- setRoutes
- resetRouter
- id: store-user
name: User Store登录/用户信息/登出)
type: store
entrypoints:
- src/store/modules/user.ts
keywords:
- getUserInfo
- resetAll
- id: store-tabs
name: Tabs StorevisitedRoutes
type: store
entrypoints:
- src/store/modules/tabs.ts
keywords:
- visitedRoutes
- noClosable
- id: store-errorlog
name: ErrorLog Store错误日志收集
type: store
entrypoints:
- src/store/modules/errorLog.ts
keywords:
- addErrorLog
- id: i18n
name: 国际化
type: core
entrypoints:
- src/i18n/index.ts
keywords:
- createI18n
- translate
- id: api-system
name: API 层src/api + request 封装)
type: core
entrypoints:
- src/api/
- src/utils/request.ts
keywords:
- axios
- interceptors
- refreshToken
- id: config-system
name: 配置系统src/config 聚合)
type: core
entrypoints:
- src/config/index.js
- src/config
keywords:
- cli.config
- theme.config
- net.config
- id: access-control
name: 访问控制ACL + hasPermission + v-permissions
type: core
entrypoints:
- src/store/modules/acl.ts
- src/utils/permission.ts
- library/plugins/directive.ts
keywords:
- hasPermission
- v-permissions
- id: mock
name: 本地 Mock
type: tooling
entrypoints:
- mock/index.js
- mock/controller
keywords:
- setupMiddlewares
- mockjs
- responseFake
- id: icons
name: SVG Iconssrc/icon
type: ui
entrypoints:
- src/icon/index.ts
- src/icon
keywords:
- require.context
- svg
- id: styles
name: 样式体系library/styles
type: ui
entrypoints:
- library/styles/vab.scss
- library/styles/variables
- library/styles/background
keywords:
- scss
- variables
- id: ui-components
name: Vab 组件库
type: ui
entrypoints:
- library/components/
keywords:
- Vab
- ElementPlus
- id: vab-app
name: VabApp
type: ui
entrypoints:
- library/components/VabApp/
- id: vab-app-main
name: VabAppMain
type: ui
entrypoints:
- library/components/VabAppMain/
- id: vab-avatar
name: VabAvatar
type: ui
entrypoints:
- library/components/VabAvatar/
- id: vab-breadcrumb
name: VabBreadcrumb
type: ui
entrypoints:
- library/components/VabBreadcrumb/
- id: vab-card
name: VabCard
type: ui
entrypoints:
- library/components/VabCard/
- id: vab-colorful-card
name: VabColorfulCard
type: ui
entrypoints:
- library/components/VabColorfulCard/
- id: vab-column-bar
name: VabColumnBar
type: ui
entrypoints:
- library/components/VabColumnBar/
- id: vab-fold
name: VabFold
type: ui
entrypoints:
- library/components/VabFold/
- id: vab-footer
name: VabFooter
type: ui
entrypoints:
- library/components/VabFooter/
- id: vab-full-screen
name: VabFullScreen
type: ui
entrypoints:
- library/components/VabFullScreen/
- id: vab-language
name: VabLanguage
type: ui
entrypoints:
- library/components/VabLanguage/
- id: vab-link
name: VabLink
type: ui
entrypoints:
- library/components/VabLink/
- id: vab-logo
name: VabLogo
type: ui
entrypoints:
- library/components/VabLogo/
- id: vab-router-view
name: VabRouterView
type: ui
entrypoints:
- library/components/VabRouterView/
- id: vab-query-form
name: VabQueryForm
type: ui
entrypoints:
- library/components/VabQueryForm/
- id: vab-error-log
name: VabErrorLog
type: ui
entrypoints:
- library/components/VabErrorLog/
- id: vab-menu
name: VabMenu
type: ui
entrypoints:
- library/components/VabMenu/
- id: vab-nav
name: VabNav
type: ui
entrypoints:
- library/components/VabNav/
- id: vab-tabs
name: VabTabs
type: ui
entrypoints:
- library/components/VabTabs/
- id: vab-refresh
name: VabRefresh
type: ui
entrypoints:
- library/components/VabRefresh/
- id: vab-search
name: VabSearch
type: ui
entrypoints:
- library/components/VabSearch/
- id: vab-lock
name: VabLock
type: ui
entrypoints:
- library/components/VabLock/
- id: vab-notice
name: VabNotice
type: ui
entrypoints:
- library/components/VabNotice/
- id: vab-header
name: VabHeader
type: ui
entrypoints:
- library/components/VabHeader/
- id: vab-sidebar
name: VabSideBar
type: ui
entrypoints:
- library/components/VabSideBar/
- id: layouts
name: 布局体系
type: ui
entrypoints:
- library/layouts/index.vue
- library/layouts/
keywords:
- Layout
- id: vab-theme
name: Theme 系统VabTheme
type: ui
entrypoints:
- library/components/VabTheme/
- src/store/modules/settings.ts
- library/plugins/vab.ts
keywords:
- theme
- updateTheme
- $pub
- id: plugins
name: Plugins全局注入/指令/错误处理)
type: core
entrypoints:
- library/plugins/
keywords:
- app.use
- globalProperties
- id: plugin-vab
name: plugin-vabgp + mitt 事件总线)
type: plugin
entrypoints:
- library/plugins/vab.ts
keywords:
- $pub
- $sub
- mitt
- id: plugin-directive
name: plugin-directivev-permissions
type: plugin
entrypoints:
- library/plugins/directive.ts
keywords:
- v-permissions
- hasPermission
- id: plugin-errorlog
name: plugin-errorlog全局错误捕获
type: plugin
entrypoints:
- library/plugins/errorLog.ts
keywords:
- errorHandler
- useErrorLogStore
- id: plugin-support
name: plugin-support构建信息/依赖检查)
type: plugin
entrypoints:
- library/plugins/support.ts
keywords:
- __APP_INFO__
- id: build
name: 构建扩展
type: tooling
entrypoints:
- vue.config.js
- library/build
keywords:
- chainWebpack
- createVuePlugin
- id: plop
name: Plop 代码生成器
type: tooling
entrypoints:
- plopfile.js
- plop-templates/
keywords:
- plop
- setGenerator

View File

@@ -0,0 +1,27 @@
# Module Specaccess-controlACL + hasPermission + v-permissions
module:
id: access-control
name: 访问控制(角色/权限/指令)
type: core
entrypoints:
- src/store/modules/acl.ts
- src/utils/permission.ts
- library/plugins/directive.ts
public_api:
concept:
- "useAclStore 保存 admin/role/permission"
- "hasPermission(target) 统一判断路由/按钮权限"
- "v-permissions 指令在模板侧消费 hasPermission"
dependency_closure:
runtime:
- "Pinia store 初始化src/store/index.ts"
acceptance:
- "acl 中 admin=true 时 hasPermission 永远为 true"
- "指令 v-permissions 可用且不报错(具体隐藏/移除行为以实现为准)"
pitfalls:
- "权限数据来源通常由 user.getUserInfo() 写入 acl抽取时需明确数据流"

View File

@@ -0,0 +1,34 @@
# Module Specapi-systemsrc/api + axios request 封装)
module:
id: api-system
name: API 层src/api 域拆分 + src/utils/request.ts
type: core
entrypoints:
- src/api/
- src/utils/request.ts
public_api:
concept:
- "src/api/<domain>.ts按业务域拆分 API 函数"
- "src/utils/request.tsaxios 实例 + 拦截器 + 统一错误处理 + token 注入"
dependency_closure:
runtime:
- "axiosinstance + interceptors"
- "qsx-www-form-urlencoded 序列化)"
- "store/usertoken 注入、401/402 时 resetAll / refresh token"
- "plugin-vabgp.$baseMessage / gp.$baseLoadingloading 与错误提示)"
- "plugin-errorlogneedErrorLog/addErrorLog请求异常入库"
- "router401/403 跳转"
- "configbaseURL/requestTimeout/contentType/successCode/statusName/messageName/debounce 等"
- "api/refreshToken402 刷新 token 重试队列"
acceptance:
- "正常接口返回 code=200 时返回 data"
- "401 跳转 /login 且 resetAll 执行"
- "402 触发 refreshToken 并重放队列请求"
pitfalls:
- "request.ts 强依赖 gp全局注入与 user store抽取到新项目需明确入口安装顺序"
- "successCode/statusName/messageName 等与后端协议强耦合,迁移时先在规格声明差异"

View File

@@ -0,0 +1,31 @@
# Module Specconfig-systemsrc/config配置聚合
module:
id: config-system
name: 配置系统src/config 聚合导出)
type: core
entrypoints:
- src/config/index.js
- src/config/cli.config.js
- src/config/setting.config.js
- src/config/theme.config.js
- src/config/net.config.js
public_api:
concept:
- "src/config/index.js 将 4 个子配置聚合导出cli/setting/theme/network"
- "部分配置会被 vue.config.js 以 Node 方式 require 读取,因此子配置文件应保持 Node 兼容(避免 window/document"
key_index:
- "authentication/loginInterception/routesWhiteList/supportVisit/rolesControl/isHashRouterMode"
- "tokenName/tokenTableName/storage/recordRoute"
- "title/titleSeparator/titleReverse"
- "defaultOpeneds/uniqueOpened/openFirstMenu"
- "layout/themeName/menuWidth/columnStyle/showProgressBar/showTabs/showTheme/showThemeSetting"
- "baseURL/contentType/requestTimeout/successCode/statusName/messageName"
acceptance:
- "运行构建/启动时vue.config.js require config 不报错"
pitfalls:
- "配置文件在 Node 侧执行:避免使用浏览器对象"

View File

@@ -0,0 +1,20 @@
# Module Speciconssrc/iconSVG 自动加载)
module:
id: icons
name: SVG Iconssrc/icon require.context 自动加载)
type: ui
entrypoints:
- src/icon/index.ts
- src/icon/*.svg
public_api:
concept:
- "通过 require.context 自动加载 src/icon 下的 svg构建期打包进 sprite/资源管线,取决于 webpack 配置)"
dependency_closure:
bundler:
- "webpack require.context"
acceptance:
- "启动后 svg 资源被打包且可引用(具体引用方式取决于项目现有 svg loader 配置)"

View File

@@ -0,0 +1,40 @@
# Module Speclayouts布局体系
module:
id: layouts
name: 布局体系Layout Shell + 多布局实现)
type: ui
entrypoints:
- library/layouts/index.vue
- library/layouts/VabLayoutVertical/
- library/layouts/VabLayoutHorizontal/
- library/layouts/VabLayoutCommon/
- library/layouts/VabLayoutComprehensive/
- library/layouts/VabLayoutFloat/
- library/layouts/VabLayoutColumn/
public_api:
concept:
- "通过 theme.layout 选择渲染的布局组件:<component :is=\"'vab-layout-' + theme.layout\" />"
usage_examples:
- "在 settings store 中设置 theme.layout 为 vertical/horizontal/...Layout 会动态切换"
dependency_closure:
runtime:
- "Pinia settings storesrc/store/modules/settingstheme/layout/collapse/device"
- "Element Plusel-backtop"
- "Theme 组件library/components/VabThemeVabThemeDrawer/VabThemeSetting"
- "事件总线注入library/plugins/vab.ts$pub/$sub/$unsubTheme 抽屉依赖该注入)"
styles:
- "library/styles/variables/variables.module.scss布局 SCSS 变量)"
- "library/styles/variables/vab-*-variables.module.scssTheme 注入 Element Plus CSS 变量)"
acceptance:
- "Layout 可渲染并不报错"
- "窗口宽度 < 992 时进入 mobile 模式并能折叠菜单watch/resize 生效)"
- "Theme 抽屉/设置入口存在时不报错(缺失 $pub/$sub 注入会导致 Theme 不工作)"
pitfalls:
- "Layout 通过 require.context 自动注册 layouts 子目录下的 .vue迁移到非 webpack 环境时需要等效能力或手动注册"
- "Layout 与 Theme 都依赖 webpack 能力require.context / 动态 require scss module抽取到非 webpack 构建器时需要等效替代方案"

View File

@@ -0,0 +1,21 @@
# Module Spec示例mock
module:
id: mock
name: 本地 MockdevServer 中间件)
entrypoints:
- mock/index.js
- mock/controller
public_api:
concept:
- "route object: { url, type, response }"
usage_examples:
- "在 mock/controller/<domain>.js 增加路由对象devServer 会自动注册"
acceptance:
- "启动开发服务器后,请求命中 mock 并返回 mockjs 数据"
pitfalls:
- "路由匹配会自动拼 baseURL 前缀(来自 src/config"

View File

@@ -0,0 +1,19 @@
# Module Specplop代码生成器
module:
id: plop
name: Plop 代码生成器view/curd/component/mock&api
type: tooling
entrypoints:
- plopfile.js
- plop-templates/
public_api:
concept:
- "通过 plop generators 生成页面、curd、组件以及 mock&api 框架代码"
acceptance:
- "执行 plop 命令可正常出现 generators 并生成文件"
pitfalls:
- "生成结果依赖仓库既有目录约定src/views、src/api、mock/controller 等);新项目需对齐目录或改模板"

View File

@@ -0,0 +1,24 @@
# Module Specplugin-directive自定义指令v-permissions
module:
id: plugin-directive
name: 自定义指令v-permissions 权限控制)
type: plugin
entrypoints:
- library/plugins/directive.ts
public_api:
concept:
- "注册 v-permissions 指令,用于按权限隐藏/禁用 UI"
dependency_closure:
runtime:
- "权限判断src/utils/permissionhasPermission"
- "路由/用户权限数据:通常来自 store/user 或 routes 权限模块(视实现而定)"
acceptance:
- "模板中存在 v-permissions 使用时不报错"
- "无权限时能按设计移除/隐藏元素(以 hasPermission 实现为准)"
pitfalls:
- "指令依赖 hasPermission 的语义;抽取到目标项目需同步其实现与权限数据来源"

View File

@@ -0,0 +1,24 @@
# Module Specplugin-errorlog全局错误捕获与上报 store
module:
id: plugin-errorlog
name: 错误日志插件app.config.errorHandler + store 收集)
type: plugin
entrypoints:
- library/plugins/errorLog.ts
public_api:
concept:
- "根据配置决定是否启用全局 errorHandler"
- "将错误写入 useErrorLogStore用于页面展示/上报)"
dependency_closure:
runtime:
- "Piniasrc/store/modules/errorLoguseErrorLogStore"
- "configsrc/config/errorLog或 src/config/index.js 聚合)"
acceptance:
- "启用后,运行时异常会进入 error log store"
pitfalls:
- "若 store 未初始化或模块缺失,会导致 errorHandler 内再次报错"

View File

@@ -0,0 +1,23 @@
# Module Specplugin-support生产环境信息/依赖检查)
module:
id: plugin-support
name: Support 插件(构建信息输出/依赖检查)
type: plugin
entrypoints:
- library/plugins/support.ts
public_api:
concept:
- "生产环境输出构建信息__APP_INFO__"
- "检查关键依赖是否存在(例如 vab-icons"
dependency_closure:
runtime:
- "__APP_INFO__ 全局常量(通常由构建注入)"
acceptance:
- "生产环境能按预期打印/校验,不影响运行"
pitfalls:
- "依赖检查失败可能影响全局能力(与 vab 插件的保护逻辑相关)"

View File

@@ -0,0 +1,29 @@
# Module Specplugin-vab全局能力注入 + 事件总线)
module:
id: plugin-vab
name: Vab 插件gp 全局方法 + mitt 事件总线)
type: plugin
entrypoints:
- library/plugins/vab.ts
public_api:
concept:
- "通过 app.provide + app.config.globalProperties 注入 gp$baseLoading/$baseMessage/$baseAlert/$baseConfirm/$baseNotify/$baseTableHeight/$pub/$sub/$unsub"
- "内部使用 mitt 作为事件总线实现 $pub/$sub/$unsub"
dependency_closure:
runtime:
- "Element PlusElLoading / ElMessage / ElMessageBox / ElNotification"
- "mitt"
- "lodash"
- "src/configloadingText/messageDuration"
types:
- "types/library.d.tsglobalPropertiesType"
acceptance:
- "安装插件后,可通过 inject('$pub')/this.$pub 发布事件"
- "$baseMessage/$baseLoading 能正常工作"
pitfalls:
- "生产环境存在授权/依赖检查逻辑,可能将 app.config.globalProperties 置空(不要在外部假设 gp 永远存在)"

View File

@@ -0,0 +1,37 @@
# Module Specrouter路由与权限守卫
module:
id: router
name: 路由与页面组织
entrypoints:
- src/router/index.ts
- src/router/permissions.ts
public_api:
exports:
- constantRoutes
- asyncRoutes
- setupPermissions(router)
usage_examples:
- "新增页面:在 src/views/<module>/ 添加 Vue 文件,并在 asyncRoutes 中挂载到 Layout children"
dependency_closure:
runtime:
- "routervue-routerbeforeEach/afterEach"
- "store-usertoken/getUserInfo/resetAll/setVirtualRoles"
- "store-routessetRoutes(authentication)"
- "store-settingstheme.showProgressBar"
- "configauthentication/loginInterception/routesWhiteList/supportVisit"
- "utils/pageTitlegetPageTitle(to.meta.title)"
- "utils/routestoLoginRoute"
- "nprogressVabProgress含 nprogress.css"
acceptance:
- "路由可跳转"
- "刷新后路由仍可恢复"
pitfalls:
- "如涉及权限/菜单,需同步 metatitle/icon/...);同时注意 routesWhiteList/loginInterception/authentication 等开关影响守卫逻辑"
- "permissions.ts 直接写 document.title若新项目改为 useHead 等方式需统一"

View File

@@ -0,0 +1,30 @@
# Module Specsetup-vablibrary/index.ts自动加载、图标、样式、插件
module:
id: setup-vab
name: setupVab(app)(自动加载 styles/background/plugins + 图标注册)
type: core
entrypoints:
- library/index.ts
public_api:
concept:
- "setupVab(app) 是本模板把 'library/' 能力接入应用的总入口"
- "它负责:加载 svg 图标、全局样式、注册图标组件、自动加载背景样式与 plugins"
dependency_closure:
runtime:
- "src/icon/index.tssvg require.context"
- "library/styles/vab.scss全局样式入口"
- "@vueuse/headcreateHead"
- "vab-iconsVabIcon 组件 + CSS"
- "@element-plus/icons-vue全量注册 ElementPlus 图标组件)"
bundler:
- "webpack require.contextbackground scss / plugins ts 自动加载"
acceptance:
- "调用 setupVab(app) 后VabIcon 可用、ElementPlus 图标组件可用"
- "plugins 自动 app.use 安装,$pub/$sub 等全局注入可用(由 plugin-vab 决定)"
pitfalls:
- "setupVab 依赖 require.context迁移到非 webpack 构建器需要替代实现(手动 import 或 glob"

View File

@@ -0,0 +1,23 @@
# Module Specstore-errorlog错误日志收集 store
module:
id: store-errorlog
name: ErrorLog Store错误日志收集
type: store
entrypoints:
- src/store/modules/errorLog.ts
public_api:
concept:
- "addErrorLog追加错误日志"
- "clearErrorLog清空错误日志"
dependency_closure:
runtime:
- "通常由 plugin-errorloglibrary/plugins/errorLog.ts与 request 异常写入触发"
acceptance:
- "触发 addErrorLog 后 errorLogs 可读取"
pitfalls:
- "若错误处理链路缺失plugin/request 未接入store 仍可用但不会自动产生数据"

View File

@@ -0,0 +1,28 @@
# Module Specstore-routes路由模式/菜单路由状态)
module:
id: store-routes
name: Routes Store路由拦截/菜单路由设置)
type: store
entrypoints:
- src/store/modules/routes.ts
public_api:
concept:
- "setRoutes(mode):根据 authentication/rolesControl 生成可访问路由并 resetRouter"
- "支持前端路由asyncRoutes与后端路由getList -> convertRouter两种模式"
dependency_closure:
runtime:
- "routersrc/routerasyncRoutes/constantRoutes/resetRouter"
- "utils/routesconvertRouter/filterRoutes"
- "api/routergetList后端路由模式"
- "configauthentication/rolesControl"
- "plugin-vabgp.$baseMessage后端路由格式异常提示"
acceptance:
- "前端路由模式下setRoutes() 后 routes 可用于菜单渲染"
- "后端路由模式下getList 返回 list 后可 convertRouter 并 resetRouter"
pitfalls:
- "后端路由 list 格式必须符合 convertRouter 预期;否则会提示错误"

View File

@@ -0,0 +1,36 @@
# Module Specstore-settings全局配置/主题/布局状态)
module:
id: store-settings
name: Settings Store主题/布局/语言/折叠等全局配置)
type: store
entrypoints:
- src/store/modules/settings.ts
public_api:
concept:
- "集中管理全局配置theme、device、collapse、language、lock、logo、title"
- "持久化localStoragetheme/collapse/language/..."
- "主题注入updateTheme() 动态加载 scss module 并写入 CSS 变量(--el-*"
usage_examples:
- "useSettingsStore().updateTheme() 在应用启动或主题变更后调用"
- "useSettingsStore().toggleCollapse() 控制侧边栏折叠"
dependency_closure:
runtime:
- "src/config默认 theme/layout/开关项等)"
- "@vueuse/coreuseCssVar如果项目通过 auto-import 或显式引入提供)"
bundler:
- "webpack dynamic requirerequire(`@vab/styles/variables/vab-${themeName}-variables.module.scss`)"
alias:
- "@ -> src"
- "@vab -> library"
acceptance:
- "切换 themeName 后 updateTheme() 能更新 Element Plus CSS 变量"
- "刷新后 theme/collapse/language 等能从 localStorage 恢复"
pitfalls:
- "updateTheme() 使用动态 require scss module非 webpack 构建需替代实现"
- "useCssVar 的来源依赖工程约定(若未自动注入,需要显式 import"

View File

@@ -0,0 +1,24 @@
# Module Specstore-tabs标签页 visitedRoutes
module:
id: store-tabs
name: Tabs StorevisitedRoutes 管理)
type: store
entrypoints:
- src/store/modules/tabs.ts
public_api:
concept:
- "addVisitedRoute/delVisitedRoute/delOthers/delLeft/delRight/delAll"
- "确保至少存在一个 noClosable tab默认第一个"
dependency_closure:
runtime:
- "router typesVabRouteRecord/#/router"
acceptance:
- "路由切换时 addVisitedRoute 可累积标签页"
- "关闭/关闭其它/左右/全部等操作不报错"
pitfalls:
- "对 meta 合并有特殊逻辑dynamicNewTab/noClosable迁移时避免改坏行为"

View File

@@ -0,0 +1,31 @@
# Module Specstore-user登录/用户信息/登出/重置)
module:
id: store-user
name: User Store登录/用户信息/登出/重置)
type: store
entrypoints:
- src/store/modules/user.ts
public_api:
concept:
- "login/socialLogin登录并 afterLogin通知、设置 token"
- "getUserInfo拉取 username/avatar/roles/permissions 并写入 acl"
- "logout/resetAll清空 token/acl/routes/tabs 并 resetRouter"
dependency_closure:
runtime:
- "api/userlogin/getUserInfo/logout/socialLogin"
- "utils/tokengetToken/setToken/removeToken"
- "configtokenName"
- "storeacl/routes/tabs/settings 联动"
- "routerresetRouter"
- "plugin-vabgp.$baseNotify/$baseMessage提示"
acceptance:
- "登录成功后 token 写入并能继续请求"
- "getUserInfo 后 acl 中 roles/permissions 生效"
- "logout 后 resetAll 清理完成且路由重置"
pitfalls:
- "logout 内含 location.reload迁移到新项目需确认是否保留该行为"

View File

@@ -0,0 +1,22 @@
# Module Specstyleslibrary/styles全局样式/变量/背景)
module:
id: styles
name: 样式体系(全局样式 + 变量 + 背景)
type: ui
entrypoints:
- library/styles/vab.scss
- library/styles/variables/
- library/styles/background/
public_api:
concept:
- "vab.scss 是全局样式入口normalize/transition/变量等聚合)"
- "variables 下含布局变量与 Theme 变量vab-*-variables.module.scss"
dependency_closure:
bundler:
- "scss/sass loader由 Vue CLI 提供)"
acceptance:
- "引入 vab.scss 后基础样式生效,不影响 Element Plus"

View File

@@ -0,0 +1,27 @@
# Module Specui-componentsVab 组件库总览)
module:
id: ui-components
name: Vab 组件库library/components/Vab*
type: ui
entrypoints:
- library/components/
public_api:
concept:
- "每个组件目录对应一个 Vab* 组件族;复用优先按目录整包搬运"
dependency_closure:
runtime:
- "Element Plus大量 el-* 依赖)"
- "iconsvab-icons 与 @element-plus/icons-vue常通过 setupVab 全局注册)"
- "全局样式library/styles/vab.scss"
alias:
- "@ -> src"
- "@vab -> library"
acceptance:
- "目标项目能渲染组件(至少 smoke render"
pitfalls:
- "部分组件可能依赖路由、store、权限指令等全局插件抽取前必须列出依赖闭包"

View File

@@ -0,0 +1,27 @@
# Module Specvab-app-main主内容区联动 routes store
module:
id: vab-app-main
name: VabAppMain主内容区
type: ui
entrypoints:
- library/components/VabAppMain/index.vue
public_api:
concept:
- "监听 route 变化,更新 routes store 的 tab/activeMenu"
- "渲染 vab-router-view + vab-footer"
dependency_closure:
runtime:
- "vue-routeruseRoute"
- "store-routestab/activeMenu"
- "utils/routeshandleActivePath"
- "组件依赖VabRouterView、VabFooter需同时可用/注册)"
acceptance:
- "路由变化时 activeMenu.data 更新为当前激活路径"
- "主内容区能渲染 router-view 与 footer"
pitfalls:
- "tab 使用 route.matched[0].name若路由层级/匹配为空需要在目标项目确认兼容"

View File

@@ -0,0 +1,21 @@
# Module SpecVabApp
module:
id: vab-app
name: VabApp应用壳/全局容器)
type: ui
entrypoints:
- library/components/VabApp/index.vue
- library/components/VabApp/
usage_examples:
- "App 根组件中使用 <vab-app /> 作为应用容器"
dependency_closure:
runtime:
- "可能依赖 router-view 与 Element Plus ConfigProvider由 VabApp 内部决定)"
- "可能依赖 pwa / i18n / route meta"
acceptance:
- "渲染不报错"
- "路由切换正常(若内部包含 router-view"

View File

@@ -0,0 +1,28 @@
# Module Specvab-avatar用户头像下拉
module:
id: vab-avatar
name: VabAvatar用户头像/用户名下拉)
type: ui
entrypoints:
- library/components/VabAvatar/index.vue
public_api:
concept:
- "右上角用户头像下拉:个人中心/外链/退出登录,并在退出后跳转到登录页(携带回跳参数)"
dependency_closure:
runtime:
- "store-useravatar/username/logout()"
- "vue-routeruseRoute/useRouter"
- "utils/routestoLoginRoute(fullPath)"
- "i18ntranslate()"
- "Element Plusel-dropdown/el-dropdown-menu/el-dropdown-item/el-avatar"
- "VabIcon"
acceptance:
- "下拉可见时箭头激活态切换"
- "点击退出登录会调用 userStore.logout() 并跳转 toLoginRoute(route.fullPath)"
pitfalls:
- "依赖 userStore 提供 avatar/username新项目需保证字段一致"

View File

@@ -0,0 +1,28 @@
# Module Specvab-breadcrumb面包屑
module:
id: vab-breadcrumb
name: VabBreadcrumb面包屑
type: ui
entrypoints:
- library/components/VabBreadcrumb/index.vue
public_api:
concept:
- "根据 routesStore.getRoutes + 当前 route.path 生成面包屑,并支持 meta.icon/meta.isCustomSvg"
dependency_closure:
runtime:
- "store-routesgetRoutes"
- "vue-routeruseRoute"
- "utils/routeshandleMatched(routes, path)"
- "i18ntranslate()"
- "Element Plusel-breadcrumb/el-breadcrumb-item"
- "VabIcon"
acceptance:
- "meta.breadcrumbHidden=true 的路由不出现在面包屑"
- "每个 crumb 的跳转目标使用 item.redirect若存在"
pitfalls:
- "依赖后端路由结构与 meta 字段title/icon/isCustomSvg"

View File

@@ -0,0 +1,25 @@
# Module Specvab-card卡片封装 + Skeleton
module:
id: vab-card
name: VabCard卡片封装
type: ui
entrypoints:
- library/components/VabCard/index.vue
public_api:
concept:
- "对 el-card 的轻封装header slot/prop + 可选 skeleton loading默认 500ms 结束)"
dependency_closure:
runtime:
- "Element Plusel-card/el-skeleton"
- "vue-routeronBeforeRouteLeave清理定时器"
- "SCSS$base-transition"
acceptance:
- "skeleton=true 时先显示 skeleton再渲染默认 slot"
- "路由离开时清理 timer"
pitfalls:
- "skeletonRows 注释提示:显示数量可能比传入多 1Element Plus 行为)"

View File

@@ -0,0 +1,24 @@
# Module Specvab-colorful-card渐变卡片
module:
id: vab-colorful-card
name: VabColorfulCard渐变卡片
type: ui
entrypoints:
- library/components/VabColorfulCard/index.vue
public_api:
concept:
- "基于 el-card 的渐变背景卡片:支持 header 标题与右上角 icon"
dependency_closure:
runtime:
- "Element Plusel-card"
- "VabIcon可选"
acceptance:
- "传入 colorFrom/colorTo 时背景为 linear-gradient"
- "传入 icon 时显示 vab-icon"
pitfalls:
- "colorFrom/colorTo 需为合法 CSS color 字符串"

View File

@@ -0,0 +1,31 @@
# Module Specvab-column-bar列式布局左侧 Tab + 二级菜单)
module:
id: vab-column-bar
name: VabColumnBarColumn 布局列栏)
type: ui
entrypoints:
- library/components/VabColumnBar/index.vue
public_api:
concept:
- "Column 布局专用:左侧 tabs 切换顶级菜单,右侧 el-menu 渲染 partialRoutes二级菜单"
dependency_closure:
runtime:
- "store-settingstheme(layout/columnStyle)/collapse + foldSideBar/openSideBar"
- "store-routestab/tabMenu/activeMenu/routes/partialRoutes"
- "configdefaultOpeneds/openFirstMenu/uniqueOpened"
- "vue-routeruseRoute/useRouter"
- "utils/validateisExternal"
- "i18ntranslate()"
- "styles@vab/styles/variables/variables.module.scsscolumn-second-menu-background 等)"
- "Element Plusel-scrollbar/el-tabs/el-tab-pane/el-menu/el-divider"
- "VabLogo/VabMenu/VabIcon"
acceptance:
- "theme.layout==='column' 时可用route.meta.noColumn=true 时会自动折叠侧边栏并隐藏 fold-unfold"
- "点击 tab若 tabMenu.path 为外链则 window.open否则openFirstMenu=true跳转到 redirect 或自身"
pitfalls:
- "直接操作 DOMdocument.querySelector('.fold-unfold') 修改 style新项目结构不同需适配"

View File

@@ -0,0 +1,28 @@
# Module Specvab-error-log错误日志展示入口
module:
id: vab-error-log
name: VabErrorLog错误日志展示
type: ui
entrypoints:
- library/components/VabErrorLog/index.vue
public_api:
concept:
- "展示 errorLogs 数量徽标,点击打开弹窗列表"
- "提供清空日志入口clearErrorLog"
dependency_closure:
runtime:
- "store-errorloguseErrorLogStoreerrorLogs/clearErrorLog"
- "Element Plusel-badge/el-dialog/el-table/el-tag/el-popover/el-button"
- "VabIcon全局组件由 setup-vab 注册)"
related_modules:
- "plugin-errorlog负责把运行时错误写入 store否则列表为空"
acceptance:
- "errorLogs.length > 0 时显示徽标并可打开弹窗"
- "点击 '暂不显示' 能清空 store"
pitfalls:
- "仅负责展示;日志产生依赖 plugin/request 链路"

View File

@@ -0,0 +1,20 @@
# Module Specvab-fold折叠按钮
module:
id: vab-fold
name: VabFold侧边栏折叠/展开)
type: ui
entrypoints:
- library/components/VabFold/index.vue
public_api:
concept:
- "根据 settings.collapse 展示不同图标,并触发 settings.toggleCollapse()"
dependency_closure:
runtime:
- "store-settingscollapse/toggleCollapse"
- "VabIcon"
acceptance:
- "点击后触发 toggleCollapse 并切换图标"

View File

@@ -0,0 +1,25 @@
# Module Specvab-footer页脚
module:
id: vab-footer
name: VabFooter页脚
type: ui
entrypoints:
- library/components/VabFooter/index.vue
public_api:
concept:
- "展示年份与站点 title来自 settings store"
dependency_closure:
runtime:
- "store-settingstitle"
- "VabIcon"
styles:
- "SCSS 变量:$base-padding / $base-border-color来自 styles 模块)"
acceptance:
- "渲染后能显示年份与 title"
pitfalls:
- "样式依赖全局 SCSS 变量;目标项目缺失变量会导致样式编译失败"

View File

@@ -0,0 +1,24 @@
# Module Specvab-full-screen全屏切换
module:
id: vab-full-screen
name: VabFullScreen全屏切换
type: ui
entrypoints:
- library/components/VabFullScreen/index.vue
public_api:
concept:
- "点击图标切换全屏状态useFullscreen().toggle"
dependency_closure:
runtime:
- "@vueuse/coreuseFullscreen若项目通过 auto-import 或显式引入提供)"
- "store-settingstheme.showFullScreen"
- "VabIcon"
acceptance:
- "theme.showFullScreen=true 时显示图标,点击可进入/退出全屏"
pitfalls:
- "useFullscreen 的来源依赖工程约定(自动导入 vs 显式 import"

View File

@@ -0,0 +1,21 @@
# Module SpecVabHeader
module:
id: vab-header
name: VabHeader头部导航
type: ui
entrypoints:
- library/components/VabHeader/index.vue
- library/components/VabHeader/
usage_examples:
- "布局组件中使用 VabHeader承载用户信息/语言切换/全屏/刷新等入口"
dependency_closure:
runtime:
- "可能依赖 settings storefixedHeader/showTabs 等)"
- "可能依赖 i18n、router"
acceptance:
- "渲染不报错"
- "常用操作(如全屏/刷新/语言切换)不崩溃(若组件支持)"

View File

@@ -0,0 +1,28 @@
# Module Specvab-language语言切换
module:
id: vab-language
name: VabLanguage语言切换
type: ui
entrypoints:
- library/components/VabLanguage/index.vue
public_api:
concept:
- "通过下拉菜单切换语言:更新 settings.language + i18n locale + document.title"
dependency_closure:
runtime:
- "store-settingstheme.showLanguage / changeLanguage(language)"
- "vue-i18nuseI18n().locale"
- "vue-routeruseRoute读取 route.meta.title"
- "utils/pageTitlegetPageTitle"
- "Element Plusel-dropdown/el-dropdown-menu/el-dropdown-item"
- "VabIcon"
acceptance:
- "theme.showLanguage=true 时显示入口"
- "切换后 settings.language 与 i18n locale 同步更新"
pitfalls:
- "document.title 依赖 route.meta.title目标项目若 meta.title 缺失需适配"

View File

@@ -0,0 +1,21 @@
# Module Specvab-link智能链接
module:
id: vab-link
name: VabLink外链/内链统一)
type: ui
entrypoints:
- library/components/VabLink/index.vue
public_api:
concept:
- "根据 isExternal(to) 自动选择渲染 a 或 router-link"
dependency_closure:
runtime:
- "utils/validateisExternal"
- "vue-routerrouter-link"
acceptance:
- "外链target=_blank + rel=noopener"
- "内链:透传 to 给 router-link"

View File

@@ -0,0 +1,29 @@
# Module Specvab-lock锁屏/解锁)
module:
id: vab-lock
name: VabLock屏幕锁
type: ui
entrypoints:
- library/components/VabLock/index.vue
public_api:
concept:
- "点击锁屏图标将 settings.lock 置为 true并隐藏侧边栏 DOM"
- "解锁通过表单校验后将 settings.lock 置为 false并恢复侧边栏"
dependency_closure:
runtime:
- "store-settingstheme.showLock / lock / title / handleLock / handleUnLock"
- "store-useravatar"
- "i18ntranslate"
- "Element Plusel-avatar/el-form/el-form-item/el-input/el-button"
- "浏览器 DOMdocument.querySelector('.vab-side-bar')(直接改 style"
acceptance:
- "theme.showLock=true 时显示锁图标;点击后 lock=true 并出现锁屏层"
- "解锁成功后 lock=false页面恢复"
pitfalls:
- "组件内密码校验为固定值(示例逻辑);迁移到新项目需确认是否替换为真实策略"
- "直接操作 '.vab-side-bar' DOM若目标项目侧边栏类名不同需要适配"

View File

@@ -0,0 +1,26 @@
# Module Specvab-logoLogo + Title
module:
id: vab-logo
name: VabLogoLogo/标题)
type: ui
entrypoints:
- library/components/VabLogo/index.vue
public_api:
concept:
- "读取 settings.logo/settings.title并根据 theme.layout 渲染不同样式的 logo 区域"
dependency_closure:
runtime:
- "store-settingstheme/layout + logo + title"
- "vue-routerrouter-link"
- "VabIcon自定义 svgis-custom-svg"
- "SCSS$base-header-height/$base-logo-height/$base-title-color 等"
acceptance:
- "logo 存在时使用 vab-icon 渲染自定义 svg"
- "theme.layout==='horizontal' 时标题可隐藏hidden-xs-only"
pitfalls:
- "Column 布局会固定定位 logo依赖左侧菜单宽度相关变量"

View File

@@ -0,0 +1,39 @@
# Module SpecVabMenu
module:
id: vab-menu
name: VabMenu菜单体系
type: ui
entrypoints:
- library/components/VabMenu/index.vue
- library/components/VabMenu/components/VabMenuItem.vue
- library/components/VabMenu/components/VabSubMenu.vue
public_api:
concept:
- "递归渲染菜单VabMenu 根据子路由可见性选择渲染 VabSubMenu 或 VabMenuItem"
- "点击菜单:根据 meta.target/_blank、外链/内链、同路由刷新等逻辑进行跳转或触发 reload"
usage_examples:
- "布局组件中引入 VabMenu配合路由 meta 与权限渲染导航"
dependency_closure:
runtime:
- "vue-routeruseRoute/useRouter跳转/判断当前路由)"
- "store-settingscollapse/device/theme(layout) + foldSideBar移动端点击收起"
- "plugin-vabinject('$pub')(同路由点击触发 $pub('reload-router-view')"
- "configisHashRouterModehash 模式下 _blank 打开内部路由)"
- "utils/validateisExternal外链判断"
- "i18ntranslate菜单 title"
- "Element Plusel-menu-item/el-sub-menu/el-tag"
- "VabIcon"
acceptance:
- "item.children 中存在可见子路由时渲染 VabSubMenu否则渲染 VabMenuItem"
- "meta.target === '_blank' 时按外链/内链规则在新窗口打开"
- "点击当前已激活路由时触发 $pub('reload-router-view')"
pitfalls:
- "组件内部使用 webpack require.context 自动注册子组件;迁移到非 webpack 构建器需等效替代"
- "Element Plus 关于 teleported 的历史兼容问题:弹层渲染到 body 下时需要全局样式配合(见 VabMenu/index.vue 注释)"
- "如果菜单权限依赖 ACL/指令v-permissions/hasPermission迁移时必须把相关依赖一起带走"

View File

@@ -0,0 +1,29 @@
# Module Specvab-nav顶部导航条聚合
module:
id: vab-nav
name: VabNav顶部导航条
type: ui
entrypoints:
- library/components/VabNav/index.vue
public_api:
concept:
- "顶部导航聚合左侧Fold + Tabs/Breadcrumb右侧ErrorLog/Lock/Search/Notice/FullScreen/Language/Theme/Refresh/Avatar"
dependency_closure:
runtime:
- "store-routestab/tabMenu/routes"
- "vue-routeruseRouter"
- "utils/validateisExternal"
- "configopenFirstMenu"
- "i18ntranslate()"
- "Element Plusel-row/el-col/el-tabs/el-tab-pane"
- "ComponentsVabFold/VabBreadcrumb/VabErrorLog/VabLock/VabSearch/VabNotice/VabFullScreen/VabLanguage/VabTheme/VabRefresh/VabAvatar"
acceptance:
- "layout='comprehensive' 时显示顶部 tabs否则显示面包屑hidden-xs-only"
- "点击 tab外链 window.open否则openFirstMenu=true跳 redirect 或自身"
pitfalls:
- "强依赖多组件与 routesStore 输出结构;抽取时必须把依赖组件闭包一起带走"

View File

@@ -0,0 +1,31 @@
# Module Specvab-notice消息中心
module:
id: vab-notice
name: VabNotice消息中心/通知)
type: ui
entrypoints:
- library/components/VabNotice/index.vue
public_api:
concept:
- "显示通知 badge弹出 popover + tabs 展示通知/邮件"
- "从 api/notice.getList 拉取数据并计算 badge"
- "提供清空消息入口(仅清空前端列表与 badge并提示"
dependency_closure:
runtime:
- "store-settingstheme.showNotice"
- "api/noticegetList"
- "plugin-vab$baseMessage清空提示通过 inject 获取)"
- "i18ntranslate"
- "Element Plusel-badge/el-popover/el-tabs/el-tab-pane/el-scrollbar/el-avatar/el-button"
- "VabIcon"
acceptance:
- "theme.showNotice=true 时显示通知入口与 badge"
- "点击/切换 tab 会触发 fetchData 更新列表"
pitfalls:
- "数据协议依赖 notice.getList 的返回结构list/total"
- "清空仅影响前端状态,不等价于后端已读/删除"

View File

@@ -0,0 +1,29 @@
# Module Specvab-query-form查询表单布局容器
module:
id: vab-query-form
name: VabQueryForm查询条件容器
type: ui
entrypoints:
- library/components/VabQueryForm/index.vue
- library/components/VabQueryForm/components/VabQueryFormTopPanel.vue
- library/components/VabQueryForm/components/VabQueryFormBottomPanel.vue
- library/components/VabQueryForm/components/VabQueryFormLeftPanel.vue
- library/components/VabQueryForm/components/VabQueryFormRightPanel.vue
public_api:
concept:
- "基于 Element Plus el-row 的 slot 容器,用于统一查询表单布局与间距"
dependency_closure:
runtime:
- "Element Plusel-row"
styles:
- "SCSS 变量:$base-input-height / $base-margin来自全局样式变量体系见 styles 模块)"
acceptance:
- "作为容器包裹 el-form-item/el-button 时布局与间距符合预期"
pitfalls:
- "样式依赖全局 SCSS 变量;目标项目若未引入对应变量会导致样式编译失败"

View File

@@ -0,0 +1,25 @@
# Module Specvab-refresh刷新当前路由视图
module:
id: vab-refresh
name: VabRefresh刷新按钮
type: ui
entrypoints:
- library/components/VabRefresh/index.vue
public_api:
concept:
- "点击后通过事件总线发布 reload-router-view刷新当前 router-view 缓存"
dependency_closure:
runtime:
- "store-settingstheme.showRefresh是否显示按钮"
- "plugin-vab$pub发布事件"
related_modules:
- "vab-router-view订阅并处理 reload-router-view"
acceptance:
- "theme.showRefresh=true 时显示图标,点击触发 $pub('reload-router-view')"
pitfalls:
- "未安装 plugin-vab 或未接入 vab-router-view 时,点击不会产生效果"

View File

@@ -0,0 +1,31 @@
# Module Specvab-router-view路由视图壳keep-alive + 过渡 + reload 事件)
module:
id: vab-router-view
name: VabRouterViewrouter-view + keep-alive + reload
type: ui
entrypoints:
- library/components/VabRouterView/index.vue
public_api:
concept:
- "统一承载页面 router-view提供 keep-alive include 列表与过渡动画"
- "监听事件总线reload-router-view用于刷新当前视图缓存"
dependency_closure:
runtime:
- "vue-routeruseRoute / <router-view>"
- "plugin-vab$sub/$unsub事件订阅"
- "store-settingstheme.showProgressBar / theme.showPageTransition"
- "store-tabsvisitedRoutes生成 keepAliveNameList"
- "utils/routeshandleActivePath生成 routerKey"
- "configkeepAliveMaxNum"
- "nprogress显示刷新进度条"
acceptance:
- "路由切换时 keep-alive include 列表随 visitedRoutes 更新"
- "$sub('reload-router-view') 触发后当前视图能被重新渲染routerKey 变更)"
pitfalls:
- "存在 get-code 事件并依赖组件的 __source 字段;不同构建/插件下可能不存在"
- "未安装 plugin-vab 时 $sub/$unsub 不存在reload/get-code 事件不会工作"

View File

@@ -0,0 +1,30 @@
# Module Specvab-search菜单搜索Ctrl/⌘+K
module:
id: vab-search
name: VabSearch菜单搜索
type: ui
entrypoints:
- library/components/VabSearch/index.vue
public_api:
concept:
- "通过 Ctrl/⌘+K 或点击图标打开搜索面板teleport 到 body"
- "从 routes store 的 getRoutes 平铺菜单项并模糊搜索"
- "维护本地搜索历史 localStorage(key=vab_search_history)"
dependency_closure:
runtime:
- "store-routesgetRoutes菜单路由来源"
- "vue-routeruseRouterrouter.push 内链跳转)"
- "浏览器 APIwindow.addEventListener('keydown'), navigator.userAgent, localStorage"
- "VabIcon搜索图标与历史删除图标"
acceptance:
- "Ctrl/⌘+K 可打开/关闭面板Escape 关闭)"
- "输入关键字能过滤菜单并 Enter 跳转"
- "搜索历史能写入/删除/清空"
pitfalls:
- "该组件包含较多样式与 DOM 交互teleport/fixed mask抽取到新项目需确保全局样式/层级不冲突"
- "菜单来源依赖 routes store 已完成 setRoutes否则列表为空"

View File

@@ -0,0 +1,20 @@
# Module SpecVabSideBar
module:
id: vab-sidebar
name: VabSideBar侧边栏容器
type: ui
entrypoints:
- library/components/VabSideBar/index.vue
- library/components/VabSideBar/
usage_examples:
- "在布局中使用 VabSideBar 包裹 VabMenu实现侧边导航"
dependency_closure:
runtime:
- "settings storecollapse/device 等"
- "Element Plus如内部使用 el-scrollbar 等)"
acceptance:
- "折叠状态切换后布局不崩溃"

View File

@@ -0,0 +1,21 @@
# Module SpecVabTabs
module:
id: vab-tabs
name: VabTabs多标签页/导航标签)
type: ui
entrypoints:
- library/components/VabTabs/index.vue
- library/components/VabTabs/
usage_examples:
- "布局头部或主区域放置 VabTabs展示已访问路由并支持关闭/切换"
dependency_closure:
runtime:
- "vue-router监听路由变化"
- "storetabs 状态(如果实现依赖 store 模块)"
acceptance:
- "访问多个路由后能出现多个 tab如功能支持"
- "切换/关闭 tab 不崩溃"

View File

@@ -0,0 +1,40 @@
# Module Specvab-theme主题系统入口与交互
module:
id: vab-theme
name: VabTheme主题配置入口/抽屉/设置面板)
type: ui
entrypoints:
- library/components/VabTheme/index.vue
- library/components/VabTheme/components/VabThemeDrawer.vue
- library/components/VabTheme/components/VabThemeSetting.vue
- library/components/VabTheme/components/
public_api:
concept:
- "VabTheme一个刷子图标入口用于触发打开主题抽屉Drawer"
- "VabThemeDrawer主题抽屉监听事件总线打开/随机主题,并调用 settings store 的 saveTheme/resetTheme/updateTheme"
- "VabThemeSetting右侧固定设置入口主题配置/随机换肤/购买源码/清理缓存),通过事件总线触发行为"
usage_examples:
- "点击 VabTheme 触发 $pub('theme') 打开抽屉"
- "点击 VabThemeSetting 的随机换肤触发 $pub('random-theme')"
dependency_closure:
runtime:
- "Pinia settings storesrc/store/modules/settingstheme.showTheme、saveTheme/resetTheme/updateTheme 等)"
- "事件总线/全局注入library/plugins/vab.ts$pub/$sub/$unsub/$baseLoading 等)"
- "i18n translatesrc/i18n/index.ts组件内调用 translate"
- "Element PlusDrawer/Radio/Select/Button 等"
styles:
- "主题变量library/styles/variables/vab-*-variables.module.scssupdateTheme() 动态注入 CSS 变量)"
acceptance:
- "页面渲染包含主题入口(刷子图标)"
- "触发 $pub('theme') 时抽屉能打开;关闭时不报错"
- "保存/重置主题后调用 updateTheme() 生效CSS 变量与 body class 变化)"
pitfalls:
- "Theme 依赖 $pub/$sub 注入;若未安装 vab 插件,事件不会触发"
- "settings.updateTheme() 依赖 webpack 的 require 动态引入 scss module迁移到非 webpack 环境需等效实现"
- "移动端(<992某些操作会触发 reload抽取时需确认期望行为"

View File

@@ -0,0 +1,64 @@
# OpenSpec-lite: 项目级规格(轻量版)
# 目的:用“可机读约束”引导 AI 在不改动现有代码的情况下复用资源。
project:
name: admin-plus-template
intent: "公司内部模板库/基础库(轻量化,优先文档约束)"
stack:
framework: "Vue 3"
build: "Vue CLI 5"
language: "TypeScript"
state: "Pinia"
router: "Vue Router"
ui: "Element Plus"
constraints:
no_code_changes_by_default: true
prefer_docs_over_refactor: true
extraction_style:
- "copy-module" # 优先整目录搬运再裁剪
- "copy-snippet" # 仅在模块过大或依赖不清晰时使用
required_output_sections:
- "changed_files" # 变更文件清单
- "extracted_modules" # 抽取模块清单(来源->目标)
- "dependency_closure" # 依赖闭包imports/运行时/类型/alias
- "acceptance_commands" # 验收命令
- "risks" # 风险说明
forbidden_by_default:
- "changing runtime behavior in production" # 禁止默认更改生产行为
- "introducing new global side effects" # 禁止新增全局副作用
- "deep-importing internal paths of modules" # 禁止消费者深层路径引用
acceptance:
minimum_commands:
- "pnpm run serve"
recommended_commands:
- "pnpm run lint"
- "pnpm run test:unit"
- "pnpm run build"
repository:
entrypoints:
- "src/main.ts"
- "library/index.ts"
- "src/router/index.ts"
- "src/store/index.ts"
- "src/i18n/index.ts"
- "mock/index.js"
module_roots:
ui_components_dir: "library/components"
layouts_dir: "library/layouts"
plugins_dir: "library/plugins"
styles_dir: "library/styles"
store_modules_dir: "src/store/modules"
api_dir: "src/api"
utils_dir: "src/utils"
config_dir: "src/config"
icons_dir: "src/icon"
notes:
- "配置读取来自 src/config/index.js被 vue.config.js require"
- "library/index.ts 存在插件自动全量加载;抽取时需显式列出依赖闭包"

View File

@@ -0,0 +1,25 @@
# Task Template: 新增 API + Mock轻量版
task:
id: add-api-and-mock
intent: "新增一个 API 调用函数,并同步补一个 Mock 路由(用于开发联调)"
inputs:
required:
- domain
- function_name
- method # get/post/...
- path # 例如 /router/getList
outputs:
files_to_change:
- "src/api/<domain>.ts"
- "mock/controller/<domain>.js"
rules:
- "API path 与 Mock path 必须一致"
- "Mock 路由对象必须包含 url/type/response"
acceptance:
- "开发环境请求能命中 mock"
- "API 函数能被页面调用且类型不报错(若涉及类型需补 types/"

View File

@@ -0,0 +1,28 @@
# Task Template: 新增页面 + 路由(轻量版)
# 目标:约束 AI 在本仓库(或迁移后的新仓库)新增页面时的输出与验收。
task:
id: add-page
intent: "新增一个页面,并把路由挂载到 Layout如需要同步 meta 供菜单/面包屑使用)"
inputs:
required:
- module # 例如 goods / userManagement
- page_name # 例如 list / detail
- route_path # 例如 /goods/list
- route_name # 例如 GoodsList
outputs:
files_to_change:
- "src/views/<module>/<page>.vue"
- "src/router/index.ts"
rules:
- "页面文件必须位于 src/views/<module>/ 下"
- "路由必须挂载到 asyncRoutes 的 Layout children除非明确说明是 constantRoutes"
- "如需要菜单展示,必须填写 meta.title如需要图标必须填写 meta.icon"
acceptance:
- "访问 route_path 能渲染页面"
- "刷新后仍可访问(路由可恢复)"
- "若配置 meta菜单/面包屑能展示正确标题"

View File

@@ -0,0 +1,37 @@
# Task Template: 抽取组件library/components/Vab*
task:
id: extract-component
intent: "从本仓库抽取一个或多个 Vab 组件到目标项目,确保依赖闭包完整"
inputs:
required:
- components # 例如 ["VabTabs", "VabMenu"]
- target_project_type
- extraction_style
scope:
base_dir: "library/components"
dependency_closure_checklist:
runtime:
- "Element Plus 组件是否使用el-*"
- "iconsvab-icons 与 @element-plus/icons-vue 是否需要"
- "全局样式library/styles/vab.scss 是否是前置依赖"
app_wiring:
- "是否依赖 setupVab 的全局注册VabIcon / 图标注册 / 插件自动加载)"
alias:
- "@ -> src"
- "@vab -> library"
outputs:
required_sections:
- changed_files
- extracted_modules
- dependency_closure
- acceptance_commands
- risks
acceptance:
- "目标项目可渲染组件"
- "关键交互可用(按组件规格中的验收点)"

View File

@@ -0,0 +1,44 @@
# Task Template: 抽取布局体系library/layouts
task:
id: extract-layout
intent: "从本仓库抽取布局体系到目标项目,最小闭包迁移,尽量不改动原仓库代码"
inputs:
required:
- target_project_type # vue-cli | vite | other
- extraction_style # copy-module | copy-snippet
scope:
entrypoints:
- library/layouts/index.vue
- library/layouts/VabLayoutVertical/
- library/layouts/VabLayoutHorizontal/
- library/layouts/VabLayoutCommon/
- library/layouts/VabLayoutComprehensive/
- library/layouts/VabLayoutFloat/
- library/layouts/VabLayoutColumn/
dependency_closure_checklist:
runtime:
- "Element Plusel-backtop 等)"
- "Theme 组件library/components/VabTheme是否随闭包迁移"
- "事件总线注入library/plugins/vab.ts$pub/$sub/$unsub是否可用"
- "Pinia settings storesrc/store/modules/settingstheme/layout/collapse/device"
- "全局样式变量library/styles/variables/(布局 SCSS 使用的变量)"
- "Theme 变量library/styles/variables/vab-*-variables.module.scsssettings.updateTheme() 依赖)"
alias:
- "@ -> src"
- "@vab -> library"
outputs:
required_sections:
- changed_files
- extracted_modules
- dependency_closure
- acceptance_commands
- risks
acceptance:
- "Layout 能渲染"
- "切换移动端/桌面端时不崩溃resize/watch 逻辑生效)"

View File

@@ -0,0 +1,30 @@
# Task Template: 抽取/复用模块(轻量版)
task:
id: extract-module
intent: "从本仓库抽取模块到目标项目,尽量不改动原仓库代码"
inputs:
required:
- module_id
- target_project_type # vue-cli | vite | other
- extraction_style # copy-module | copy-snippet
outputs:
required_sections:
- changed_files
- extracted_modules
- dependency_closure
- acceptance_commands
- risks
procedure:
- step: "从 openspec-lite/manifest.yaml 选择 module_id 并列出 entrypoints"
- step: "读取入口文件,分析 import 依赖与运行时依赖样式、插件、types、alias"
- step: "按 extraction_style 抽取(优先 copy-module"
- step: "在目标项目补齐依赖package.json、alias、types include"
- step: "给出最小验收命令并说明风险"
acceptance:
- "目标项目可启动serve"
- "模块能力可用(根据 module_id 的验收点)"

View File

@@ -0,0 +1,35 @@
# Task Template: 抽取插件library/plugins/*
task:
id: extract-plugin
intent: "从本仓库抽取一个或多个插件到目标项目,确保注入点与依赖闭包完整"
inputs:
required:
- plugins # 例如 ["vab", "directive", "errorLog", "support"]
- target_project_type
- extraction_style
scope:
base_dir: "library/plugins"
dependency_closure_checklist:
runtime:
- "vabElement Plus 的 ElMessage/ElLoading/ElMessageBox/ElNotification 是否全局可用"
- "directivesrc/utils/permission 与权限数据来源是否齐全"
- "errorLogsrc/store/modules/errorLog 与 config/errorLog 是否齐全"
- "support__APP_INFO__ 注入方式是否一致"
wiring:
- "是否通过 setupVab(library/index.ts) 自动 app.use() 安装;若非自动,需要在入口手动 app.use()"
outputs:
required_sections:
- changed_files
- extracted_modules
- dependency_closure
- acceptance_commands
- risks
acceptance:
- "插件安装后,不影响应用启动"
- "涉及的注入能力/指令/错误捕获按模块规格验收"

View File

@@ -0,0 +1,41 @@
# Task Template: 抽取主题系统VabTheme + settings 主题闭包)
task:
id: extract-theme
intent: "从本仓库抽取 Theme 系统到目标项目,确保事件总线 + settings theme 闭包完整"
inputs:
required:
- target_project_type # vue-cli | vite | other
- extraction_style # copy-module | copy-snippet
scope:
entrypoints:
- library/components/VabTheme/
- src/store/modules/settings.ts
- library/plugins/vab.ts
- library/styles/variables/
dependency_closure_checklist:
runtime:
- "Pinia settings store 是否存在并已在入口初始化"
- "vab 插件是否安装($pub/$sub/$baseLoading 注入)"
- "i18n translate 是否可用"
- "Element Plus Drawer/表单控件是否可用"
bundler:
- "settings.updateTheme() 的 require('@vab/styles/variables/vab-*-variables.module.scss') 在目标构建器中是否可用"
alias:
- "@ -> src"
- "@vab -> library"
outputs:
required_sections:
- changed_files
- extracted_modules
- dependency_closure
- acceptance_commands
- risks
acceptance:
- "触发 $pub('theme') 能打开 Theme Drawer"
- "修改主题并保存后,刷新页面主题持久化且样式变量生效"

259
README.md
View File

@@ -1,112 +1,165 @@
<div align="center">
<img width="200" src="https://gcore.jsdelivr.net/gh/zxwk1998/image/logo/vab.svg" alt="VAB"/>
<h1>admin-plus</h1>
</div>
# Admin PlusVue3 企业级开发模板)
## 🔈 框架使用建议
面向公司项目的前端模板与基础库:内置 `Vue 3 + Vue CLI 5 + TypeScript + Pinia + Vue Router + Element Plus`,并集成 Mock、代码生成Plop、多套布局组件与常用工具链支持在此基础上快速裁剪与复用。
- 使用前请一定先阅读 vip 群文档及群文档中的常见问题,一般在群公告前 5 条
- 对于常见问题可直接使用 qq 群【消息记录】功能快速寻找到答案。
- 如果您经过 qq 群聊天记录、翻阅文档、百度后努力尝试仍无法解决问题,可通过 vip 群寻求帮助,讨论时间法定工作日 10 点-16 点。
- 2021 年 3 月 6 日后main 分支支持 ts、js 混合开发,建议不熟悉 ts 的用户继续使用 js熟悉 ts 用户可自行选择开发语言。
- 对于热心回答群内其他成员问题的用户,所提建议将优先被采纳,并可获得部分内测版本体验资格。
- 关于举报盗版侵权请发送举报材料至fanhuihui1998@126.com一经查实官司所得收入 20%归举报人所有80%归律师事务所所有。
- 关于客服人员满意度评价以及相关建议请发送材料至fanhuihui1998@126.com邮件标题满意度评价邮件正文评价依据我们必将认真对待每一位客户的诉求。
- 关于 bug 反馈请发送材料至fanhuihui1998@126.com邮件标题bug 反馈邮件正文bug 截图及描述。
> 本仓库同时提供面向 AI 的结构说明与模块索引:见 [AI-Coding/README.md](AI-Coding/README.md)
## 🔈 框架使用约定
---
- 1.购买者可将授权后的产品用于任意「符合国家法律法规」的应用平台,禁止用于黄赌毒等危害国家安全与稳定的网站,否则我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。
- 2.购买主体购买后可用于开发商业项目,不限制域名和项目数量,购买主体不可将源码分享第三方,否则我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。
- 3.购买者务必尊重知识产权,严格保证不恶意传播产品源码、不得直接对授权的产品本身进行二次转售或倒卖、开源、不得对授权的产品进行简单包装后声称为自己的产品等,无论有意或无意,我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。
- 4.购买者不可将 vip 群文档及资料分享给第三方,否则我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。
- 5.购买者购买项目不可以用来构建存在竞争性质的产品并直接对外销售否则我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。
- 6.购买者购买项目中的源码包含全部源码、及部分源码片段不可以用于任何形式的开源项目不可将源码放置于码云、github等开源平台否则我们有权利收回产品授权及更新权限并根据事态轻重追究相应法律责任。
- 7.购买者用于公司的项目商用时购买必须提供公司名称,用于证明购买过我们的项目来进行商业用途,防范法律风险,我们承诺对购买公司信息信息严格保密,不会泄漏到互联网或用于产品宣传。
- 8.购买者用于个人学习需提供姓名、手机联系方式进行实名认证,如无法提供请勿下单。
- 9.如用于外包项目购买者购买项目中的源码不可直接对外出售npm run build 编译后的项目不受限制。
- 10.如果您的公司基于 Vab Admin 系列自行研发的产品(如 OA、ERP、SASS 等)需对外销售,并且产品中包含我们框架的前端源码,那么您无法购买以上版本,需联系客服购买专属定制版本(不为第三方提供前端框架代码请忽略本条)。
- 11.虚拟物品下单后不支持退货退款。
- 12.购买者需遵守以上约定,最终解释权归 vab 系列著作权人所有,如果您无法遵守以上约定,请勿下单。
## 亮点
```
注:以上协议以 //vuejs-core.cn/authorization/ 底部为准
- **开箱即用**工程化配置齐全TS/ESLint/Prettier/Stylelint/Unit Test
- **可扩展的 UI/布局体系**`library/layouts/``library/components/` 内置多布局与业务型基础组件。
- **Mock 一体化**:开发环境通过 `devServer.setupMiddlewares` 自动挂载 `mock/` 路由。
- **现代依赖栈**`Element Plus` + `@element-plus/icons-vue`,并内置图标组件 `vab-icons`
- **可生成代码**:通过 `plop` 快速生成页面/CRUD/组件/mock&api。
---
## 环境要求
- Node.js建议 **16/18/20 LTS**(与 Vue CLI 5 兼容)
- 包管理器:推荐 `pnpm`(项目脚本也提供 `npm` 用法)
---
## 快速开始
### 1安装依赖
```powershell
cd d:\project\Web_Template_Vue3_Dev
pnpm i
```
## 🔗 链接
- 💻 常规版演示地址:[admin-plus](//vuejs-core.cn/admin-plus/)
- 📝 使用文档:(文档地址及密码请查看 vip 群群公告第一条)
- 🗃 更新日志:[Releases](https://github.com/zxwk2024/admin-plus/releases)
- 📌 付费版及 vip 群购买地址:[购买地址](//vuejs-core.cn/authorization/)
<!-- ## 🌱 版本
- `dev`分支为开发分支,较为激进,不推荐直接使用,非专业前端请勿使用。
- 对于感兴趣的提交(commit),可使用精选(Cherry-Pick)复制到自己的项目中
| 分支名 | 是否精简提交 | 是否精简功能 | 是否支持多国语言 | 同步时间 | 维护人 |
| -------------------------------------------------------------------------------- | :----------: | :----------: | :--------------: | :------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| [dev](https://github.com/zxwk2024/admin-plus/tree/webpack5) | ❌ | ❌ | ✔ | 即时 | All |
| [main](https://github.com/zxwk2024/admin-plus/) | ❌ | ❌ | ✔ | 10-30 天 | <a href="https://github.com/zxwk1998" target="_blank"><img style="border-radius:999px" src="https://avatars3.githubusercontent.com/u/26647258?s=50&u=753921fb23f418996dffd6196e89729fcb2329ed&v=4"/></a> |
| [release/main](https://github.com/zxwk2024/admin-plus/tree/release/main) | ✔ | ❌ | ✔ | 40-60 天 | <a href="https://github.com/FlowPeakFish" target="_blank"><img style="border-radius:999px" src="https://avatars3.githubusercontent.com/u/29328241?s=50&u=bb0977b405ccf1a101ce4e18e4fb8d958854ca60&v=4"/></a> |
| [release/template](https://github.com/zxwk2024/admin-plus/tree/release/template) | ✔ | ✔ | ✔ | 40-60 天 | <a href="https://github.com/FlowPeakFish" target="_blank"><img style="border-radius:999px" src="https://avatars3.githubusercontent.com/u/29328241?s=50&u=bb0977b405ccf1a101ce4e18e4fb8d958854ca60&v=4"/></a> |
| [release/seed](https://github.com/zxwk2024/admin-plus/tree/release/seed) | ✔ | ✔ | ❌ | 40-60 天 | <a href="https://github.com/FlowPeakFish" target="_blank"><img style="border-radius:999px" src="https://avatars3.githubusercontent.com/u/29328241?s=50&u=bb0977b405ccf1a101ce4e18e4fb8d958854ca60&v=4"/></a> | -->
## ✅ 版权须知
Vab Admin 系列产品受国家计算机软件著作权保护(证书号:软著登字第 7051316 号),
禁止公开及传播产品源文件、二次出售等,
违者将承担相应的法律责任,并影响自身使用。
## 🧑‍💻 增值服务
### vip 群
- 每位购买 Admin 的用户均可获得 1 个免费的 vip 互助群免费入群资格,可反馈 bug、协助框架问题解答无需额外购买
- 免费名额之外,额外加入 vip 群 100/人 仅限已购买框架的的公司员工加入,购买后联系 微信 zxwk-bfq 即可)
- [购买地址,网页右下角切换付款码即可](//vuejs-core.cn/authorization/)
### 定制开发
- 承接各类基于 vab 开发的前端项目
- 承接项目范围 3K+ 至 无上限
- 支持签订合同
- 支持提供发票
- 结算流程前期款50%- 中期款30%- 尾款20%
- 联系方式:见当前页底部
### 企业一对一远程培训
- 承接一对一远程培训服务(支持提供发票)
- 承接时间: 周一至周六上午 10 点 - 晚上 10 点
- 价格400 - 10000
- 承接方式:单次、包月、包年
- 联系方式:见当前页底部
### 个人一对一技术指导
- 承接时间: 周一至周六上午 10 点 - 晚上 10 点
- 价格300 - 500
- 承接方式:单日
- 支持零基础远程教学(学员需学习刻苦,有上进心)
- 学员需完成老师布置的任务
- 联系方式:见当前页底部
### 联系方式
```txt
微信客服zxwk-bfq (备注来意)
邮件标题:企业一对一远程培训 - 公司名称,定制开发 - 公司名称,一对一技术支持 - 公司名称
邮件内容:大致描述 + 联系方式 + 预估需要时间 + 预算
后续: 收到邮件后,工作人员会于第一时间回复
如你使用 npm
```powershell
cd d:\project\Web_Template_Vue3_Dev
npm i
```
### 2启动开发环境
```powershell
pnpm run serve
```
### 3构建
```powershell
pnpm run build
```
### 4单元测试 / 代码质量
```powershell
pnpm run test:unit
pnpm run lint
pnpm run lint:eslint
pnpm run lint:prettier
pnpm run lint:stylelint
```
---
## 常用脚本scripts
来自 `package.json`
- **`serve`**:启动开发服务器(本地 Mock 会自动挂载)。
- **`build`**:生产构建。
- **`build:compress` / `compress`**:构建后压缩产物(`scripts/compress.js`)。
- **`build:website`**:站点构建(使用 `VAB_VARIABLE=website` + 压缩)。
- **`test:unit`**:单元测试。
- **`lint`**Vue CLI ESLint。
- **`lint:eslint` / `lint:prettier` / `lint:stylelint`**:更精细的格式化与风格修复。
- **`template`**:启动 `plop` 代码生成。
---
## 项目结构(速览)
> 更完整、可供 AI 检索复用的索引见 [AI-Coding/README.md](AI-Coding/README.md)。
```text
src/ 应用主代码(入口、路由、状态、国际化、业务页面)
library/ 模板基础库(全局样式、插件集合、构建扩展等)
library/components/ 可复用基础组件Vab* 体系)
library/layouts/ 多套布局(含主 Layout 入口)
mock/ 本地 Mock 服务devServer 中间件挂载)
types/ 全局类型声明与业务类型
tests/unit/ 单元测试
scripts/ 构建后处理脚本(如压缩)
public/ 静态资源与 HTML 模板
```
---
## 关键约定与入口
### 应用入口
- `src/main.ts`
- 创建应用并挂载:`createApp(App)`
- 初始化顺序:`setupVab``setupI18n``setupStore``setupRouter`
- 生产环境可自动启用 Mock`baseURL` 不是外链地址时(见 `src/main.ts` 的判断)
### 路由
- `src/router/index.ts`
- `constantRoutes`:如登录/注册/404 等基础路由
- `asyncRoutes`:业务路由(包含 `Layout` 作为壳)
### 状态管理
- `src/store/index.ts`Pinia 初始化与注入。
### 国际化
- `src/i18n/index.ts`
- `createI18n({ legacy:false })`
- 当前语言读取自 `useSettingsStore(pinia)`
### Mock
- `mock/index.js`
- 挂载到开发服务器中间件(在 `vue.config.js``devServer.setupMiddlewares`
- 基于 `mockjs` 返回数据,并支持文件变更热更新
---
## 别名Alias
来自 `vue.config.js` / `tsconfig.json`
- `@``src`
- `~` → 项目根目录
- `/#``types`
- `@vab``library`
- `@gp``library/plugins/vab`
---
## 代码生成Plop
项目提供 `plop` 生成器(见 `plopfile.js`
- `view`:页面
- `curd`CRUD
- `component`:组件
- `mock&api`Mock 与 API 片段
运行:
```powershell
pnpm run template
```
---
## 贡献与团队协作建议
- 建议以“业务模块”为单位在 `src/views/` 组织页面。
- API 按域拆分在 `src/api/`,与 `mock/controller/` 保持同名与路径一致,方便对照。
- 公共能力优先沉淀在 `library/`(全局插件/样式/构建扩展)与 `library/components/`(可视组件)。