# VTJ Prompts 完整文档 > 本文档由 /docs/llms/ 目录下的所有提示词文档合并整理而成,供 AI 大模型深度参考。 --- # VTJ Prompts 索引 > 本文档为 `/docs/llms/` 目录下的所有提示词文档提供标签索引,用于 AI 意图匹配度查询。 --- ## 文档标签索引 ### [api.md](./api.md) - VTJ API 管理指南 **简介:** 详细介绍 VTJ 平台中 API 接口的完整生命周期管理,包括如何通过设计器配置 API、API 的完整字段结构、请求配置选项、Mock 数据设置,以及在组件中如何通过 `__apis` 调用接口。涵盖路径参数、查询参数的正确使用方式,以及 JSONP、请求拦截等特殊场景。 **核心主题:** API 配置、调用、管理工具方法 **标签:** - `API管理` - `HTTP请求` - `setApi工具` - `路径参数` - `查询参数` - `Mock数据` - `接口调用` - `请求配置` - `数据源` - `CRUD接口` - `ApiSchema` - `JSONP请求` - `请求拦截` - `响应校验` - `opts.params` - `opts.query` - `__apis调用` - `模拟数据模板` - `接口测试` - `category分组` --- ### [block.md](./block.md) - 区块管理指南 **简介:** 说明 VTJ 中区块(Block)的三种来源类型(Schema、UrlSchema、Plugin),区块的创建、编辑、删除操作流程,以及区块在页面中的引用方式。同时介绍区块的代码生成规则和与页面的区别,帮助理解如何实现组件的跨页面复用。 **核心主题:** 区块创建、来源类型、复用机制 **标签:** - `区块管理` - `Schema区块` - `UrlSchema` - `Plugin插件` - `组件复用` - `区块工具方法` - `from引用` - `代码生成` - `BlockFile` - `嵌套引用` - `createBlock` - `updateBlock` - `removeBlock` - `getBlocks` - `预设区块` - `市场安装` - `资源URL` - `library库名` - `双向复用` - `页面保存为区块` --- ### [chart.md](./chart.md) - 图表库使用指南 **简介:** 介绍 `@vtj/charts` 图表库的完整使用方法,包括基于 ECharts 封装的 `XChart` 通用图表组件和 `XMapChart` 地图图表组件。涵盖组件 Props、事件监听、响应式 Option 更新、组合式 API(useChart、useMapChart),以及柱状图、折线图、饼图、地图等常用图表类型的配置示例。 **核心主题:** ECharts 图表组件、地图图表、组合式 API **标签:** - `图表库` - `ECharts` - `XChart组件` - `XMapChart` - `地图图表` - `GeoJSON` - `响应式Option` - `useChart` - `数据可视化` - `图表事件` - `组合式API` - `useMapChart` - `自动resize` - `图表类型` - `柱状图` - `折线图` - `饼图` - `雷达图` - `散点图` - `层级地图` --- ### [coder.md](./coder.md) - Vue 代码编写约定 **简介:** 定义 AI 生成 Vue 组件代码时必须遵循的严格规范,确保输出内容能被 `@vtj/parser` 无损解析为 DSL。包括强制使用 Composition API、响应式状态命名(`__state`、`__props`、`__emit`)、全局 API 映射表、模板指令使用规范、Import 导入约定,以及明确的禁止事项清单。 **核心主题:** parser 可解析的 Vue 代码规范、Composition API 强制要求 **标签:** - `代码规范` - `Composition API` - `script setup` - `parser解析` - `变量命名` - `全局API映射` - `模板约定` - `Import规范` - `DSL生成` - `禁止事项` - `__state命名` - `__props声明` - `__emit调用` - `生命周期钩子` - `computed计算` - `watch监听` - `指令使用` - `Slot插槽` - `动态class` - `PascalCase命名` --- ### [env.md](./env.md) - 环境变量指南 **简介:** 讲解 VTJ 平台中环境变量的配置和使用方式,支持开发(development)和生产(production)双环境值存储。介绍如何通过 `createEnv` 工具创建环境变量、`getEnv` 查询配置,以及在组件中通过 `__provider.env` 运行时访问环境变量,适用于 API 地址、功能开关、第三方 Key 等场景。 **核心主题:** 环境变量配置、双环境值存储、运行时访问 **标签:** - `环境变量` - `双环境配置` - `development` - `production` - `createEnv工具` - `运行时访问` - `EnvConfig` - `功能开关` - `API地址配置` - `全局只读配置` - `getEnv` - `removeEnv` - `nodeEnv切换` - `平铺对象` - `UPPER_SNAKE_CASE` - `__provider.env` - `环境值类型` - `同名不覆盖` - `自动选取` - `第三方Key配置` --- ### [globals.md](./globals.md) - 全局 API 使用指南 **简介:** 详细说明 `@vtj/renderer` 提供的全局变量及其在 Vue 组件中的使用方式。这些变量由框架自动注入,包括 `__store`(Pinia 状态)、`__request`(HTTP 请求)、`__libs`(第三方库集合)、`__apis`(接口集合)、`__access`(权限控制)等,涵盖权限判断、登录管理、动态请求、跨 UI 库调用等典型场景。 **核心主题:** renderer 提供的全局变量、自动注入机制 **标签:** - `全局API` - `自动注入` - `__store` - `__request` - `__libs` - `__apis` - `__access` - `权限控制` - `Pinia实例` - `HTTP请求` - `__pinia` - `第三方库集合` - `ElementPlus` - `AntDesignVue` - `VueUse` - `登录管理` - `权限判断` - `Token管理` - `请求封装` - `拦截器注册` --- ### [i18n.md](./i18n.md) - 国际化指南 **简介:** 介绍 VTJ 平台的国际化(i18n)配置和使用方法,基于 vue-i18n 的 Composition API 模式。包括如何通过 `createI18nMessage` 创建中英文对照词条、词条 Key 的命名规范(点号分层)、在模板和 script 中使用 `__i18n.t()` 进行翻译,以及插值参数、数字格式化、日期格式化等高级功能。 **核心主题:** 多语言配置、词条管理、翻译函数使用 **标签:** - `国际化` - `i18n` - `多语言` - `词条管理` - `vue-i18n` - `翻译函数` - `createI18nMessage` - `插值参数` - `Key命名规范` - `locale设置` - `getI18nMessage` - `removeI18nMessage` - `fallbackLocale` - `zh-CN` - `英文翻译` - `点号分层` - `模块页面元素` - `__i18n.t()` - `数字格式化` - `日期格式化` --- ### [icons.md](./icons.md) - 图标库使用指南 **简介:** 全面介绍 `@vtj/icons` 图标库的四种图标来源(SVG 组件、Iconfont 图标、Element Plus 图标、Assets 图标),以及全局注册和按需导入两种使用方式。详细说明 `XIcon` 组件的用法,包括 `icon` 和 `src` 属性的区别、size/color 控制、动态图标切换,并提供完整的图标分类列表。 **核心主题:** 图标组件、按需导入、XIcon 渲染 **标签:** - `图标库` - `XIcon组件` - `SVG图标` - `Iconfont` - `Element Plus图标` - `Assets图标` - `按需导入` - `全局注册` - `图标命名` - `动态图标` - `IconsPlugin` - `VtjIcon前缀` - `colors属性` - `size属性` - `color属性` - `src属性` - `CSS类实现` - `组件引用` - `图标分类` - `业务操作图标` --- ### [page.md](./page.md) - 页面管理指南 **简介:** 讲解 VTJ 中页面的三种类型(page、dir、layout)及其路由行为,页面树的创建、编辑、删除操作流程,以及路由体系和菜单生成规则。涵盖特殊属性如 KeepAlive 缓存、mask 内嵌母版、hidden 隐藏菜单、raw 源码模式,以及 UniApp 平台的专属字段(needLogin、style)。 **核心主题:** 页面类型、路由体系、菜单生成 **标签:** - `页面管理` - `路由体系` - `页面类型` - `目录节点` - `布局页面` - `createPage工具` - `菜单生成` - `RouterView` - `KeepAlive` - `源码模式` - `PageFile` - `getPages` - `updatePage` - `removePage` - `setHomepage` - `movePage` - `路由元信息` - `mask内嵌母版` - `hidden隐藏菜单` - `needLogin登录校验` --- ### [settings.md](./settings.md) - 应用设置指南 **简介:** 详细介绍 VTJ 应用级别的全局配置项,覆盖三大类:全局配置(CSS、Pinia Store、Access 权限控制、Enhance 增强)、请求配置(Axios 基础配置、请求拦截器、响应拦截器)、路由守卫(beforeEach 前置守卫、afterEach 后置守卫)。说明渲染引擎的严格初始化顺序及各配置项的依赖关系。 **核心主题:** 全局配置、请求配置、路由守卫 **标签:** - `应用设置` - `全局配置` - `Pinia Store` - `权限控制` - `Axios配置` - `请求拦截器` - `响应拦截器` - `路由守卫` - `beforeEach` - `初始化顺序` - `setGlobalCss` - `setGlobalStore` - `setGlobalAccess` - `setGlobalAxios` - `afterEach后置守卫` - `enhance增强` - `GlobalConfig` - `设计模式不生效` - `函数代码字符串` - `依赖关系` --- ### [tools.md](./tools.md) - 设计器工具方法说明 **简介:** 汇总 AI 在 VTJ 设计器中可调用的所有工具方法(Tools),包括页面管理(createPage、updatePage、removePage)、区块管理(createBlock、getBlocks)、API 管理(setApi、getApis)、全局配置(setGlobalCss、setGlobalStore 等)、环境变量、国际化、UniApp 配置等。提供标准的 JSON 调用格式和典型工作流程建议。 **核心主题:** 所有可调用的工具方法、调用格式、工作流程 **标签:** - `工具方法` - `action调用` - `页面管理工具` - `区块管理工具` - `API管理工具` - `全局配置工具` - `环境变量工具` - `国际化配置` - `UniApp配置` - `工作流程` - `getSkills` - `refresh刷新` - `getCurrentFile` - `getNodeSelected` - `active打开` - `movePage移动` - `parameters格式` - `JSON调用` - `技能文档` - `运行时检测` --- ### [ui.md](./ui.md) - UI 组件库使用指南 **简介:** 全面介绍 `@vtj/ui` 企业级 UI 组件库的核心组件和使用规范,包括 XGrid 数据表格(基于 VXE Table)、XForm 表单、XField 字段、XDialog 对话框、XActionBar 操作栏、XQueryForm 查询表单、XContainer 布局容器等。同时说明 Hooks 工具(useIcon、useLoader)、Adapter 适配器系统,以及完整的 CRUD 页面示例。 **核心主题:** 业务组件、Hooks、Adapter 适配器系统 **标签:** - `UI组件库` - `XGrid表格` - `XForm表单` - `XField字段` - `XDialog对话框` - `XActionBar` - `XQueryForm` - `Hooks工具` - `Adapter适配器` - `CRUD页面` - `VXE Table` - `列渲染器` - `单元格编辑` - `行拖拽排序` - `inline表单` - `sticky按钮` - `编辑器类型` - `级联刷新` - `useIcon` - `useLoader` --- ### [uni.md](./uni.md) - UniApp 全局配置指南 **简介:** 专门针对 UniApp 平台的全局配置文档,介绍如何通过 `setUniConfig` 工具配置 manifest.json(应用配置)、pages.json(页面路由配置)、全局 CSS,以及应用生命周期函数(onLaunch、onShow、onHide、onError 等)。说明配置在运行时的注入流程和仅 UniApp 平台生效的限制条件。 **核心主题:** UniApp 平台配置、manifest.json、pages.json、生命周期 **标签:** - `UniApp配置` - `manifestJson` - `pagesJson` - `应用生命周期` - `onLaunch` - `全局样式` - `tabBar配置` - `setUniConfig` - `平台专属` - `运行时注入` - `getUniConfig` - `onShow` - `onHide` - `onError` - `onPageNotFound` - `onThemeChange` - `onExit` - `window.__uniConfig` - `adoptedStyleSheets` - `easycom` --- ### [utils.md](./utils.md) - 工具库使用指南 **简介:** 介绍 `@vtj/utils` 通用工具库的完整功能模块,包括 HTTP 请求封装(request、createApi、useApi)、本地存储(storage 支持过期机制)、Cookie 操作、URL 解析与拼接、文件下载、日志模块、动态脚本加载、JSONP 跨域请求、客户端环境检测、requestAnimationFrame 封装等。提供典型工作流程示例,如数据获取与展示、文件上传与下载。 **核心主题:** HTTP 请求、本地存储、URL 处理、文件下载等通用工具 **标签:** - `工具库` - `HTTP请求` - `本地存储` - `storage` - `cookie操作` - `URL处理` - `文件下载` - `日志模块` - `动态脚本加载` - `JSONP请求` - `request封装` - `createApi` - `createApis` - `useApi钩子` - `缓存过期` - `localStorage` - `sessionStorage` - `url.stringify` - `downloadBlob` - `loadScript` --- ## 标签分类汇总 ### 按功能模块分类 **数据与接口:** - API管理、HTTP请求、setApi工具、路径参数、查询参数、Mock数据、接口调用、请求配置、数据源、CRUD接口、**request、**apis、权限控制 **组件与UI:** - 图表库、ECharts、XChart组件、XMapChart、UI组件库、XGrid表格、XForm表单、XField字段、XDialog对话框、XActionBar、XQueryForm、Hooks工具、Adapter适配器、图标库、XIcon组件 **配置与管理:** - 环境变量、双环境配置、应用设置、全局配置、Pinia Store、Axios配置、请求拦截器、响应拦截器、路由守卫、UniApp配置、manifestJson、pagesJson **国际化与本地化:** - 国际化、i18n、多语言、词条管理、vue-i18n、翻译函数 **页面与路由:** - 页面管理、路由体系、页面类型、目录节点、布局页面、RouterView、KeepAlive **代码规范:** - 代码规范、Composition API、script setup、parser解析、变量命名、全局API映射、模板约定 **工具与实用:** - 工具方法、本地存储、storage、cookie操作、URL处理、文件下载、日志模块、动态脚本加载、JSONP请求 **区块与复用:** - 区块管理、Schema区块、UrlSchema、Plugin插件、组件复用 --- ## 使用建议 ### AI 意图匹配查询示例 **场景 1:用户问"如何调用接口"** - 匹配标签:`API管理`、`HTTP请求`、`接口调用` - 推荐文档:[api.md](./api.md)、[globals.md](./globals.md)、[utils.md](./utils.md) **场景 2:用户问"如何使用表格组件"** - 匹配标签:`XGrid表格`、`UI组件库` - 推荐文档:[ui.md](./ui.md) **场景 3:用户问"如何配置多语言"** - 匹配标签:`国际化`、`词条管理` - 推荐文档:[i18n.md](./i18n.md) **场景 4:用户问"如何设置环境变量"** - 匹配标签:`环境变量`、`双环境配置` - 推荐文档:[env.md](./env.md) **场景 5:用户问"如何生成 Vue 代码"** - 匹配标签:`代码规范`、`Composition API`、`parser解析` - 推荐文档:[coder.md](./coder.md) **场景 6:用户问"如何使用图表"** - 匹配标签:`图表库`、`ECharts`、`XChart组件` - 推荐文档:[chart.md](./chart.md) **场景 7:用户问"如何配置路由守卫"** - 匹配标签:`路由守卫`、`beforeEach`、`应用设置` - 推荐文档:[settings.md](./settings.md) **场景 8:用户问"如何使用图标"** - 匹配标签:`图标库`、`XIcon组件` - 推荐文档:[icons.md](./icons.md) --- > **说明:** 每个文档的 20 个标签基于其核心内容、功能模块、使用场景、API方法、配置项等精准提取,可用于 AI 意图识别和文档推荐系统的匹配查询。 # VTJ 工具速查清单 > AI 意图 → 工具/文档 快速映射。按任务场景查找,直达对应工具或文档。 --- ## 一、页面管理 | 意图 | 工具方法 | 参考文档 | | ------------------- | ----------------------------------------------------- | -------------------- | | 查看页面树/菜单结构 | [`getMenus`](./tools.md#getmenus--获取页面菜单树) | [page.md](./page.md) | | 获取所有页面列表 | [`getPages`](./tools.md#getpages--获取所有页面) | [page.md](./page.md) | | 新建页面 | [`createPage`](./tools.md#createpage--创建页面) | [page.md](./page.md) | | 修改页面信息 | [`updatePage`](./tools.md#updatepage--更新页面信息) | [page.md](./page.md) | | 调整页面层级/父级 | [`movePage`](./tools.md#movepage--移动页面层级) | [page.md](./page.md) | | 删除页面 | [`removePage`](./tools.md#removepage--删除页面) | [page.md](./page.md) | | 设为首页 | [`setHomepage`](./tools.md#sethomepage--设置应用主页) | [page.md](./page.md) | ## 二、区块管理 | 意图 | 工具方法 | 参考文档 | | ------------ | ----------------------------------------------------- | ---------------------- | | 查看所有区块 | [`getBlocks`](./tools.md#getblocks--获取所有区块) | [block.md](./block.md) | | 创建区块 | [`createBlock`](./tools.md#createblock--创建区块) | [block.md](./block.md) | | 修改区块信息 | [`updateBlock`](./tools.md#updateblock--更新区块信息) | [block.md](./block.md) | | 删除区块 | [`removeBlock`](./tools.md#removeblock--删除区块) | [block.md](./block.md) | ## 三、API 接口管理 | 意图 | 工具方法 | 参考文档 | | -------------- | --------------------------------------------------- | ---------------------------------------------- | | 查看所有接口 | [`getApis`](./tools.md#getapis--获取接口列表) | [api.md](./api.md) | | 新建/更新接口 | [`setApi`](./tools.md#setapi--新增或更新接口) | [api.md](./api.md) | | 删除单个接口 | [`removeApi`](./tools.md#removeapi--删除接口) | [api.md](./api.md) | | 批量删除接口 | [`removeApis`](./tools.md#removeapis--批量删除接口) | [api.md](./api.md) | | 组件中调用接口 | → 用 `__apis.xxx()` | [api.md](./api.md)、[globals.md](./globals.md) | ## 四、文件与运行时操作 | 意图 | 工具方法 | | --------------------- | ----------------------------------------------------------------------------- | | 打开(激活)页面/区块 | [`active`](./tools.md#active--打开文件) | | 获取当前打开文件信息 | [`getCurrentFile`](./tools.md#getcurrentfile--获取当前文件信息) | | 获取当前文件 Vue 源码 | [`getCurrentFileContent`](./tools.md#getcurrentfilecontent--获取当前文件源码) | | 刷新运行时、检测错误 | [`refresh`](./tools.md#refresh--刷新运行时) | | 获取选中节点路径 | [`getNodeSelected`](./tools.md#getnodeselected--获取当前选中节点路径) | ## 五、全局配置 | 意图 | 工具方法 | 参考文档 | | ---------------------------- | --------------------------------------------------------------- | ---------------------------- | | 全局 CSS | `getGlobalCss` / `setGlobalCss` | [settings.md](./settings.md) | | Pinia Store(vue3 状态管理) | `getGlobalStore` / `setGlobalStore` | [settings.md](./settings.md) | | 权限控制配置 | `getGlobalAccess` / `setGlobalAccess` | [settings.md](./settings.md) | | Axios 请求基础配置 | `getGlobalAxios` / `setGlobalAxios` | [settings.md](./settings.md) | | 请求拦截器 | `getGlobalRequestInterceptor` / `setGlobalRequestInterceptor` | [settings.md](./settings.md) | | 响应拦截器 | `getGlobalResponseInterceptor` / `setGlobalResponseInterceptor` | [settings.md](./settings.md) | | 路由前置守卫 | `getGlobalBeforeEach` / `setGlobalBeforeEach` | [settings.md](./settings.md) | | 路由后置守卫 | `getGlobalAfterEach` / `setGlobalAfterEach` | [settings.md](./settings.md) | > 所有 set 类配置传入 **JS 函数代码字符串**,详见 [settings.md](./settings.md)。 ## 六、环境变量管理 | 意图 | 工具方法 | 参考文档 | | ---------------- | ----------------------------------------------- | ---------------------------------------------- | | 查看所有环境变量 | [`getEnv`](./env.md#getenv--获取所有环境变量) | [env.md](./env.md) | | 新增环境变量 | [`createEnv`](./env.md#createenv--新增环境变量) | [env.md](./env.md) | | 删除环境变量 | [`removeEnv`](./env.md#removeenv--删除环境变量) | [env.md](./env.md) | | 组件中访问 | → `__provider.env.变量名` | [env.md](./env.md)、[globals.md](./globals.md) | ## 七、国际化 i18n | 意图 | 工具方法 | 参考文档 | | -------------- | -------------------------------------------- | ------------------------------------------------ | | 查看所有词条 | `getI18nMessage` | [i18n.md](./i18n.md) | | 新增词条 | `createI18nMessage` | [i18n.md](./i18n.md) | | 删除词条 | `removeI18nMessage` | [i18n.md](./i18n.md) | | 组件中使用翻译 | → `__i18n.t('key')` / 模板 `{{ $t('key') }}` | [i18n.md](./i18n.md)、[globals.md](./globals.md) | ## 八、UniApp 专属 | 意图 | 工具方法/参数 | 参考文档 | | -------------------------- | --------------------------------------- | ------------------ | | 查看 UniApp 配置 | `getUniConfig(key)` | [uni.md](./uni.md) | | 配置 manifest.json | `setUniConfig("manifestJson", jsonStr)` | [uni.md](./uni.md) | | 配置 pages.json | `setUniConfig("pagesJson", jsonStr)` | [uni.md](./uni.md) | | 全局 CSS | `setUniConfig("css", cssStr)` | [uni.md](./uni.md) | | 生命周期:启动/显示/隐藏等 | `setUniConfig("onLaunch", fnStr)` 等 | [uni.md](./uni.md) | | 配置 tabBar | → 编辑 pagesJson 中的 tabBar 字段 | [uni.md](./uni.md) | ## 九、技能文档查询 | 意图 | 操作 | | ---------------------- | -------------------------------------- | | 查阅特定功能的详细用法 | `getSkills([技能ID])` — 技能 ID 见下表 | **可用技能 ID 与文档映射:** | 技能 ID | 文档 | 速查场景 | | ---------- | ---------------------------- | ----------------------------------------------------------------- | | `api` | [api.md](./api.md) | API 配置、路径参数、Mock 数据、接口调用规范 | | `block` | [block.md](./block.md) | 区块概念、来源类型、复用机制 | | `chart` | [chart.md](./chart.md) | XChart、XMapChart、ECharts 图表配置 | | `coder` | [coder.md](./coder.md) | **Vue Composition API 代码规范**(AI 生成代码前必读) | | `env` | [env.md](./env.md) | 环境变量双环境配置、UPPER_SNAKE_CASE 命名 | | `globals` | [globals.md](./globals.md) | 全局注入变量详解:`__store`、`__request`、`__apis`、`__access` 等 | | `i18n` | [i18n.md](./i18n.md) | 多语言词条管理、`__i18n.t()` 翻译、参数插值 | | `icons` | [icons.md](./icons.md) | 图标库 4 种来源、XIcon 组件、按需导入 | | `page` | [page.md](./page.md) | 页面类型(page/dir/layout)、路由体系、KeepAlive | | `settings` | [settings.md](./settings.md) | 全局配置(Store/Access/Axios/路由守卫)详细说明 | | `tools` | [tools.md](./tools.md) | 所有设计器工具方法完整文档 | | `ui` | [ui.md](./ui.md) | @vtj/ui 组件:XGrid、XForm、XField、XDialog、Hooks | | `uni` | [uni.md](./uni.md) | UniApp 平台配置(仅 UniApp 生效) | | `utils` | [utils.md](./utils.md) | @vtj/utils 工具库:HTTP 请求、storage、URL 处理等 | ## 十、编程库 / 全局 API 速查 | 模块 | 用途 | 组件中访问方式 | 参考文档 | | --------------- | -------------- | ----------------------------------------------------------------------------------------- | -------------------------- | | `@vtj/renderer` | 全局注入能力 | `__store`、`__request`、`__apis`、`__access`、`__libs`、`__pinia`、`__i18n`、`__provider` | [globals.md](./globals.md) | | `@vtj/ui` | 企业级 UI 组件 | ``, ``, ``, `` 等 | [ui.md](./ui.md) | | `@vtj/charts` | ECharts 图表 | ``, ``, `useChart()` | [chart.md](./chart.md) | | `@vtj/icons` | 图标系统 | `` | [icons.md](./icons.md) | | `@vtj/utils` | 通用工具函数 | `request()`, `storage`, `url`, `downloadBlob` 等 | [utils.md](./utils.md) | ## 十一、代码生成速查 | 场景 | 核心约束 | 参考文档 | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | **生成 Vue 页面/区块代码** | 强制 Composition API + `script setup`;状态命名 `__state`、props `__props`、emit `__emit`;用 `__apis.xxx()` 调接口;全局变量用 `__store`/`__request`/`__access` 等 | **[coder.md](./coder.md)**(必读) | | 使用 UI 组件 | 组件 PascalCase 引用;`@vtj/ui` 组件用 `` 等;图表用 ``;图标用 `` | [ui.md](./ui.md)、[chart.md](./chart.md)、[icons.md](./icons.md) | | 调用 API | `const { data } = await __apis.getUserList({ ...opts })` | [api.md](./api.md) | | 使用全局 Store | `const user = __store.state.user; __store.setUser(data)` | [settings.md](./settings.md)、[globals.md](./globals.md) | | 模板翻译 | `{{ $t('key') }}` — 注意:Composition 下 `$t` 仅在模板可用 | [i18n.md](./i18n.md) | ## 十二、典型工作流 ``` 1. 了解项目 → getMenus / getPages (了解页面结构) 2. 创建页面 → createPage(page, parentId?) (先父级再子级) 3. 创建区块 → createBlock(block) (跨页面复用的组件) 4. 注册接口 → setApi(apiSchema) (后端 API 对接) 5. 生成代码 → 遵循 coder.md 规范 + 调用 getSkills (AI 生成 Vue 源码) 6. 验证结果 → refresh (检测运行时错误) 7. 全局配置 → setGlobalStore / setGlobalAccess 等 (Store/权限/路由守卫) 8. i18n 配置 → createI18nMessage (多语言词条) 9. 环境变量 → createEnv (开发/生产双环境值) ``` --- ## 速查索引(按关键词) | 关键词 | 动作 | | ------------------------------------- | ---------------------------------------------------------- | | 创建页面/删除页面/移动页面 | → 见[页面管理](#一页面管理) | | 创建区块/删除区块 | → 见[区块管理](#二区块管理) | | 注册接口/调接口/\_\_apis | → 见[API 管理](#三-api-接口管理) + [api.md](./api.md) | | 获取源码/刷新/选中节点 | → 见[文件与运行时](#四文件与运行时操作) | | 全局CSS/Store/Pinia | → 见[全局配置](#五全局配置) + [settings.md](./settings.md) | | 权限/登录/access | → `setGlobalAccess` + [settings.md](./settings.md) | | Axios/baseURL/请求拦截 | → `setGlobalAxios` + [settings.md](./settings.md) | | 路由守卫/beforeEach | → `setGlobalBeforeEach` + [settings.md](./settings.md) | | 环境变量/env/\_\_provider | → 见[环境变量](#六环境变量管理) + [env.md](./env.md) | | i18n/多语言/翻译/$t | → 见[i18n](#七国际化-i18n) + [i18n.md](./i18n.md) | | UniApp/manifest/pages.json | → 见[UniApp](#八uniapp-专属) + [uni.md](./uni.md) | | 代码规范/Composition API/script setup | → [coder.md](./coder.md) | | 全局变量/**store/**request/\_\_libs | → [globals.md](./globals.md) | | XGrid 表格/XForm 表单/XDialog | → [ui.md](./ui.md) | | XChart 图表/useChart/ECharts | → [chart.md](./chart.md) | | XIcon 图标/SVG/Iconfont | → [icons.md](./icons.md) | | request/storage/工具函数 | → [utils.md](./utils.md) | | 生成 Vue 代码/parser 解析 | → [coder.md](./coder.md) | | 查看详细工具文档 | → [tools.md](./tools.md) | # VTJ 页面管理 — AI 配置与使用指南 > 本文档帮助 AI 理解页面的三种类型、路由体系、以及如何通过工具方法管理页面。 --- ## 一、页面数据流全貌 ``` 设计器页面树 项目数据 渲染引擎 pages/index.vue project.pages routes.ts + page.ts ├── 新增 → createPage() ──→ PageFile[] ──→ createStaticRoutes() → RouteRecordRaw[] ├── 编辑 → updatePage() │ ├── 删除 → removePage() ├──→ createMenus() → 侧边菜单 ├── 拖拽 → update() │ ├── 主页 → setHomepage() └──→ getHomepage() / getPage() └── 克隆 → clonePage() ``` **核心概念:** 页面是项目结构的基础单元,页面树即路由树。三种类型决定了路由行为和嵌套关系。 --- ## 二、页面类型 | 类型 | `dir` | `layout` | 说明 | | ----------------- | ------- | -------- | -------------------------------------------------------- | | **页面** (page) | `false` | `false` | 标准页面,拥有 DSL 及独立路由 | | **目录** (dir) | `true` | — | 纯容器节点,无 DSL 无路由,只用于组织子页面 | | **布局** (layout) | — | `true` | 布局壳页面,拥有 DSL 及路由,子页面嵌入其 `` | **类型决策:** - 需要嵌套路由时使用**目录**:用户看到的 URL 是子页面路径 - 需要共享外壳(侧边栏、顶栏等)时使用**布局**:子页面路由挂载在布局路由的 `children` 下 - UniApp 平台**不支持**目录和布局类型 --- ## 三、PageFile 完整字段 ```typescript interface PageFile extends BlockFile { dir?: boolean; // 是否目录 layout?: boolean; // 是否布局页面 icon?: string; // 菜单图标(ElementPlus 图标 或 @vtj/icons 名称) children?: PageFile[]; // 子页面(目录/布局的子级) mask?: boolean; // 内嵌母版,仅 Web 平台 hidden?: boolean; // 隐藏菜单,仅 Web 平台 raw?: boolean; // 源码模式(非低代码页面,不可在线编辑) pure?: boolean; // 纯净页面(默认 true) cache?: boolean; // 开启 KeepAlive 缓存,仅 Web 平台 meta?: Record; // 路由元信息(JSON 对象) needLogin?: boolean; // 需要登录,UniApp 专用 style?: Record; // 页面窗口表现,UniApp 专用 } // 继承自 BlockFile interface BlockFile { type: 'page' | 'block'; // 文件类型 id: string; // 唯一标识(自动生成) name: string; // 文件名(驼峰格式,如 Dashboard) title: string; // 页面标题(显示名) category?: string; // 分组 dsl?: BlockSchema; // 页面 DSL 内容(目录类型无此字段) } ``` --- ## 四、页面工具方法 ### 4.1 `getPages` — 获取全部页面 **参数:** 无 **返回:** 简化的页面列表,每项含 `id`、`name`、`title`、`layout`、`dir`、`icon` --- ### 4.2 `createPage` — 新建页面 **参数:** | 参数 | 类型 | 必填 | 说明 | | ------------- | ------- | ---- | --------------------------------- | | `page.name` | string | ✅ | 页面名称,驼峰格式,如 `UserList` | | `page.title` | string | ✅ | 页面标题,如 `用户列表` | | `page.icon` | string | ❌ | 图标名,如 `User`(ElementPlus) | | `page.dir` | boolean | ❌ | 是否目录(默认 false) | | `page.layout` | boolean | ❌ | 是否布局(默认 false) | | `parentId` | string | ❌ | 父页面 ID,用于嵌套 | **注意事项:** - 创建嵌套页面时,必须先创建父级(目录或布局),再以 `parentId` 创建子页面 - UniApp 平台强制 `dir = false`、`layout = false` - 创建非目录页面后自动激活该页面 - 返回 `{ id, name, title, layout, dir }` **示例:** ```json { "action": "createPage", "parameters": [ { "name": "Dashboard", "title": "仪表盘", "icon": "DataAnalysis" } ] } ``` 创建目录及子页面: ```json // 先创建目录 { "action": "createPage", "parameters": [{ "name": "System", "title": "系统管理", "dir": true }] } // 再创建子页面(需用返回的 parentId) { "action": "createPage", "parameters": [{ "name": "UserList", "title": "用户列表" }, "DIR_ID"] } ``` --- ### 4.3 `updatePage` — 编辑页面元信息 **参数:** | 参数 | 类型 | 必填 | 说明 | | ------------ | ------ | ---- | -------- | | `page.id` | string | ✅ | 页面 ID | | `page.name` | string | ✅ | 页面名称 | | `page.title` | string | ✅ | 页面标题 | | `page.icon` | string | ❌ | 图标名 | **限制:** 仅支持修改 `id`、`name`、`title`、`icon` 四个字段,不支持修改 `dir`/`layout` 等类型字段。 --- ### 4.4 `removePage` — 删除页面 **参数:** `id: string` — 页面 ID **限制:** 目录或布局类型的页面需先删除所有子级页面。 --- ### 4.5 `setHomepage` — 设置主页 **参数:** `id: string` — 页面 ID 主页即应用的根路由(`/`),访问应用时首先展示的页面。 --- ## 五、路由体系 ### 5.1 路由生成规则 | 页面类型 | 路由 path | 路由 name | 说明 | | -------- | ------------------------- | -------------- | ---------------------------------- | | 页面 | `/${pageRouteName}/${id}` | `id` | 标准页面路由 | | 目录 | 无路由 | — | 仅作为 children 的容器 | | 布局 | `${prefix}` | `layout_${id}` | 布局路由的 children 包含子页面路由 | | 主页 | `/` | `home_${id}` | 根路径路由 | **路由元信息合并:** ```typescript route.meta = { title, // 页面标题 ...routeMeta, // 全局路由元信息配置 ...page.meta, // 页面自定义 meta(JSON) __vtj__: id // 内部标识,用于 getPage(id) }; ``` ### 5.2 页面渲染流程 ``` URL 访问 /page/userList → vue-router 匹配 RouteRecordRaw → PageContainer.setup() → route.meta.__vtj__ 或 route.params.id 获取 id → provider.getPage(id) 获取 PageFile → provider.getRenderComponent(file.id) ├── 普通模式: getDsl(id) → createDslRenderer(dsl) └── 源码模式: modules[`${vtjRawDir}/${id}.vue`] → h(component, { ...query, key: sid }) 渲染 ``` **关键点:** - 路由 `params.id` 即页面的 `id` 字段 - 源码模式(`raw = true`)直接导入 `.vue` 文件,跳过 DSL 渲染 ### 5.3 菜单生成 菜单从 `project.pages` 树直接生成: - `layout` 类型:不生成菜单项,递归处理其 children - 非 `layout` 类型:生成菜单项,`url = ${menuPathPrefix}/${pageRouteName}/${id}` - `hidden = true` 的菜单项仍生成但标记为隐藏 - 菜单可配合 `access` 进行权限过滤 --- ## 六、特殊页面属性 ### 6.1 `mask`(内嵌母版) 仅 Web 平台有效。页面显示在父级布局的内部,而不是作为独立路由页面。 **与路由的关系:** mask 页面不影响路由结构,由前端框架的母版机制处理。 ### 6.2 `cache`(KeepAlive) 仅 Web 平台有效。开启后页面组件被 `` 缓存,切换时不销毁。 **代码影响:** 无,由框架自动处理。 ### 6.3 `hidden`(隐藏菜单) 仅 Web 平台有效,菜单中不显示该项,但路由仍然存在可访问。 ### 6.4 `raw`(源码模式) 页面使用原生 Vue 单文件组件,存储为 `.vue` 文件而非 DSL。**不可在设计器中在线编辑。** **代码影响:** 自己编写完整 `.vue` 文件,通过 `__provider` 等全局实例访问环境变量、API 等。 ### 6.5 `meta`(路由元信息) JSON 对象,合并到 `route.meta`,用于携带自定义路由数据: ```json { "roles": ["admin"], "keepAlive": true, "order": 1 } ``` 组件中通过 `useRoute().meta` 读取。 ### 6.6 UniApp 专属字段 | 字段 | 说明 | | ----------- | ------------------------------------------------------------------------------------------------------------ | | `needLogin` | 页面是否需要登录才能访问 | | `style` | 页面窗口表现配置,参考 [uni-app pages.json style](https://uniapp.dcloud.net.cn/collocation/pages.html#style) | --- ## 七、典型操作场景 ### 7.1 创建标准页面结构 ``` Dashboard (page) — 仪表盘主页 System (dir) — 系统管理目录 ├── UserList (page) — 用户列表 └── RoleManage (page) — 角色管理 ``` 操作顺序: 1. `createPage({ name: "Dashboard", title: "仪表盘", icon: "Odometer" })` 2. `createPage({ name: "System", title: "系统管理", dir: true, icon: "Setting" })` 3. `createPage({ name: "UserList", title: "用户列表" }, "System的ID")` 4. `createPage({ name: "RoleManage", title: "角色管理" }, "System的ID")` 5. `setHomepage("Dashboard的ID")` ### 7.2 创建布局套子页面 ``` AdminLayout (layout) — 管理布局(侧边栏+顶栏外壳) ├── Profile (page) — 个人中心 └── Settings (page) — 系统设置 ``` **前提:** AI 需要在 `AdminLayout` 的 DSL 中使用 `` 才能显示子页面。 --- ## 八、注意事项 1. **创建顺序:** 必须先创建父级(目录/布局),再创建子页面。子页面的 `parentId` 必须为已存在的目录或布局 ID 2. **删除顺序:** 删除目录/布局前,必须先删除所有子级页面,否则操作失败 3. **名称唯一:** 页面 `name` 在同级中不可重复 4. **名称自动格式化:** `name` 自动转为大驼峰(`UpperCamelCase`) 5. **UniApp 限制:** UniApp 平台不支持 `dir` 和 `layout` 类型,所有页面均为扁平 page 类型 6. **布局 + RouterView:** 布局页面的 DSL 中必须包含 `` 组件,否则子页面不会显示 7. **`updatePage` 限制:** 只能修改 `name`、`title`、`icon`,无法修改类型(dir/layout)等结构字段 8. **源码模式路径:** `raw = true` 的页面,Vue 文件路径为 `{vtjRawDir}/{id}.vue`,其中 `vtjRawDir` 默认为 `.vtj/vue` # VTJ 区块管理 — AI 配置与使用指南 > 本文档帮助 AI 理解区块(Block)的三种来源类型、在页面中的使用方式、以及如何通过工具方法管理区块。 --- ## 一、区块数据流全貌 ``` 设计器区块面板 项目数据 渲染引擎 → 代码生成 blocks/index.vue project.blocks loader.ts coder ├── 新增 Schema ──→ BlockFile ──→ getDsl(id) ──→ AsyncComponent ──→ import BlockName from './id.vue' ├── 新增 UrlSchema ──→ ──→ getDslByUrl(url) ──→ AsyncComponent ──→ provider.defineUrlSchemaComponent() ├── 新增 Plugin ──→ ──→ loadScriptUrl(scripts) ──→ AsyncComponent ──→ provider.definePluginComponent() ├── 编辑 → updateBlock() ├── 删除 → removeBlock() └── 克隆 → cloneBlock() 页面使用区块: DSL node.from = { type: 'Schema', id: 'blockId' } │ ▼ BlockLoader(id, name, from) → 加载并渲染区块 ``` **核心概念:** 区块是可复用的独立组件单元,有三种来源类型。在页面 DSL 中,通过 `node.from` 引用区块。区块可以独立编辑,也可以被拖拽到任意页面使用。 --- ## 二、区块三种来源类型 | 类型 | `fromType` | 说明 | 存储方式 | | -------------------- | ------------- | -------------------------------------------- | ------------ | | **设计** (Schema) | `'Schema'` | 在设计器中用低代码方式编辑的区块,有独立 DSL | 项目内置 DSL | | **引用** (UrlSchema) | `'UrlSchema'` | 引用远程 JSON 文件作为 DSL | 远程 URL | | **插件** (Plugin) | `'Plugin'` | 动态加载 JS/CSS 插件作为组件 | 远程资源 URL | **类型决策:** - 需要就地编辑的 → **Schema** - 多个项目共享同一组件 → **UrlSchema**(中央管理 JSON) - 需要动态加载第三方或自定义组件 → **Plugin**(上传 JS/CSS 文件) --- ## 三、BlockFile 完整字段 ```typescript interface BlockFile { type: 'block'; // 固定为 'block' id: string; // 唯一标识(自动生成) name: string; // 文件名,驼峰格式,如 UserCard title: string; // 显示名称,如 "用户卡片" category?: string; // 分组,如 "数据展示"、"表单" fromType?: 'Schema' | 'UrlSchema' | 'Plugin'; // 来源类型,默认 'Schema' urls?: string; // 资源文件路径(Plugin/UrlSchema 使用,多个用逗号分隔) library?: string; // 插件库名(Plugin 类型使用) dsl?: BlockSchema; // 区块 DSL 内容(Schema 类型使用) preset?: boolean; // 是否为预设区块(不可编辑删除) market?: MarketInstallInfo; // 物料市场安装信息 } ``` --- ## 四、区块工具方法 ### 4.1 `getBlocks` — 获取全部区块 **参数:** 无 **返回:** 简化的区块列表,每项含 `id`、`name`、`title`、`category` --- ### 4.2 `createBlock` — 新建区块 **参数:** | 参数 | 类型 | 必填 | 说明 | | ---------------- | ------ | ---- | ------------------------------------- | | `block.name` | string | ✅ | 区块名称,驼峰格式,如 `UserCard` | | `block.title` | string | ✅ | 区块标题,如 `用户卡片` | | `block.category` | string | ❌ | 分组名称,如 `数据展示`。可为新分组名 | **创建后自动激活** 该区块进入编辑模式。 **示例:** ```json { "action": "createBlock", "parameters": [ { "name": "UserCard", "title": "用户卡片", "category": "数据展示" } ] } ``` --- ### 4.3 `updateBlock` — 编辑区块元信息 **参数:** | 参数 | 类型 | 必填 | 说明 | | ---------------- | ------ | ---- | -------- | | `block.id` | string | ✅ | 区块 ID | | `block.name` | string | ❌ | 区块名称 | | `block.title` | string | ❌ | 区块标题 | | `block.category` | string | ❌ | 分组名称 | --- ### 4.4 `removeBlock` — 删除区块 **参数:** `id: string` — 区块 ID --- ## 五、区块在页面中的使用 ### 5.1 使用方式 区块被拖拽到页面后,在 DSL 中表现为一个带有 `from` 引用的节点: ```json { "name": "UserCard", "from": { "type": "Schema", "id": "abc123def456" }, "props": { "title": "团队成员" } } ``` 三种 `from` 格式: | 类型 | `from` 格式 | 加载方式 | | --------- | ----------------------------------------------------- | --------------------------- | | Schema | `{ type: 'Schema', id: 'blockId' }` | 按 id 获取 DSL → 创建渲染器 | | UrlSchema | `{ type: 'UrlSchema', url: 'https://...' }` | 按 URL 获取 JSON DSL | | Plugin | `{ type: 'Plugin', urls: [...], library: 'libName' }` | 动态加载 JS/CSS 文件 | ### 5.2 页面保存为区块 将某个页面保存为区块,供其他页面复用: ``` pages/index.vue → 右键 "保存到区块" → project.saveToBlock(page) ``` --- ## 六、代码生成规则 ### 6.1 Schema 区块 生成独立 `.vue` 文件 + `import` 语句: ```javascript // 生成在 script setup 顶部 import UserCard from './abc123def456.vue'; ``` ### 6.2 UrlSchema 区块 生成异步组件定义: ```javascript const UserCard = __provider.defineUrlSchemaComponent( 'https://example.com/block.json' ); ``` ### 6.3 Plugin 区块 生成插件组件定义: ```javascript const UserCard = __provider.definePluginComponent({ type: 'Plugin', urls: ['https://example.com/plugin.js', 'https://example.com/plugin.css'], library: 'UserCard' }); ``` ### 6.4 模板中的使用 三种类型的区块在模板中使用方式相同: ```html ``` --- ## 七、区块 vs 页面 | 维度 | 区块 (Block) | 页面 (Page) | | -------- | --------------------------- | ------------------------------- | | 用途 | 可复用组件单元 | 独立路由页面 | | 路由 | 无独立路由 | 有独立路由 | | 复用 | 可被多个页面引用 | 作为路由终点 | | 类型 | Schema / UrlSchema / Plugin | page / dir / layout | | 文件类型 | `type: 'block'` | `type: 'page'` | | 编辑 | 独立编辑区 | 独立编辑区 | | 嵌套 | 通过 `from` 引用 | 通过 children + RouterView 嵌套 | **典型关系:** - 页面内部可以嵌入多个区块(通过拖拽) - 一个区块可以被多个页面同时引用 - 页面可以保存为区块供其他地方复用 - 区块也可以引用其他区块(通过 `from.type = 'Schema'`) --- ## 八、注意事项 1. **Schema 区块可编辑:** 只有 `fromType: 'Schema'` 的区块可以在设计器中打开编辑,UrlSchema 和 Plugin 类型不能在线编辑 2. **预设区块不可删改:** `preset: true` 的区块只能使用,不能编辑和删除 3. **名称自动格式化:** `name` 自动转为大驼峰(`UpperCamelCase`) 4. **名称不可重复:** 区块和页面共享同一个命名空间,`name` 全局不可重复 5. **资源文件格式限制:** - UrlSchema 的 `urls` 只接受一个 `.json` 文件 - Plugin 的 `urls` 可接受多个 `.js`、`.css`、`.json` 文件 6. **Plugin 必须指定 library:** `fromType: 'Plugin'` 时必须填写 `library` 字段,用于查找插件组件 7. **Schema 区块缓存:** 运行时按 `blockId + instanceId` 缓存组件实例,相同区块多实例共享 DSL 但各自独立渲染 8. **双向复用:** 页面可以保存为区块,区块也可以通过拖拽加入页面,两者可互相转换 # VTJ API 管理 — AI 配置指南 > 本文档帮助 AI 理解如何通过工具方法管理项目 API,以及在组件中调用 API 发送请求。 --- ## 一、数据流全貌 ``` 设计器 API 管理面板 项目数据 渲染引擎 apis/index.vue ──setApi()────▶ project.apis ──createSchemaApis()──▶ provider.apis apis/form.vue (增/删/改) (ApiSchema[]) (register by id+name) (callable functions) │ 组件中调用: __apis['apiName'](data, opts) ``` **关键流程:** 1. **创建阶段:** 通过 `setApi` 工具将 API 配置存入 `project.apis` 2. **初始化阶段:** 应用启动时 `Provider.load()` → `createSchemaApis(apis, meta, adapter)` 将每条 API 编译为可调用的函数 3. **注册方式:** 每条 API 同时以 `id` 和 `name` 作为键注册到 `provider.apis`,组件中通过 `__apis['name']` 调用 4. **调用阶段:** `__apis['apiName'](data, opts)` → 底层调用 `request.send(config)` 发送请求 --- ## 二、API 工具方法 ### `setApi` — 新增或更新 API 新增一条 API 配置。若 `name` 已存在则更新,否则新增。 **参数:** | 参数 | 类型 | 必填 | 说明 | | ------------------ | ------- | ---- | --------------------------------------------------------------------------- | | `api.name` | string | ✅ | 接口名称,camelCase,如 `getUserList` | | `api.url` | string | ✅ | 请求 URL,支持路径参数如 `/api/user/:id` | | `api.label` | string | ❌ | 接口描述说明 | | `api.method` | string | ❌ | 请求方法:`get` / `post` / `put` / `delete` / `patch` / `jsonp`,默认 `get` | | `api.category` | string | ❌ | 分组名称,用于 UI 分类展示 | | `api.settings` | object | ❌ | 请求配置(下表) | | `api.headers` | string | ❌ | 请求头,JS 表达式字符串,如 `"({'Content-Type': 'application/json'})"` | | `api.mock` | boolean | ❌ | 是否开启模拟数据,默认 `false` | | `api.mockTemplate` | string | ❌ | 模拟数据模板函数(JS 函数字符串),签名 `(req) => template` | | `api.jsonpOptions` | object | ❌ | JSONP 配置(仅 method 为 `jsonp` 时有效) | **`api.settings` 子字段:** | 字段 | 类型 | 默认值 | 说明 | | ---------------- | ------- | ------- | --------------------------------------------------------------------- | | `type` | string | `form` | 发送数据类型:`form`(表单)/ `json`(JSON)/ `data`(文件/FormData) | | `loading` | boolean | `true` | 请求时是否显示全局 loading | | `failMessage` | boolean | `true` | 请求失败时是否弹出错误提示 | | `validSuccess` | boolean | `false` | 是否校验响应成功 | | `originResponse` | boolean | `true` | 是否返回原始 Axios 响应对象 | | `injectHeaders` | boolean | `false` | 是否注入自定义请求头 | | `proxy` | boolean | `false` | 是否开启请求代理 | **`api.jsonpOptions` 子字段(仅 method 为 `jsonp`):** | 字段 | 类型 | 说明 | | ----------------------- | ------- | ---------------- | | `jsonpCallback` | string | 回调函数名 | | `jsonpCallbackFunction` | string | 回调函数 | | `timeout` | number | 超时时间(毫秒) | | `crossorigin` | boolean | 是否跨域 | **示例(简单配置):** ```json { "action": "setApi", "parameters": [ { "name": "getUserList", "label": "获取用户列表", "url": "/api/users", "method": "get", "category": "用户管理" } ] } ``` **示例(完整配置):** ```json { "action": "setApi", "parameters": [ { "name": "getUserList", "label": "获取用户列表", "url": "/api/users", "method": "get", "category": "用户管理", "settings": { "type": "json", "loading": true, "failMessage": true, "validSuccess": false, "originResponse": true, "injectHeaders": false, "proxy": false }, "headers": { "type": "JSExpression", "value": "({'Content-Type': 'application/json'})" }, "mock": false, "mockTemplate": { "type": "JSFunction", "value": "(req) => {\n return {\n code: 0,\n message: 'ok',\n data: {\n 'list|10': [{\n id: '@guid',\n name: '@cname',\n 'age|18-60': 1\n }]\n }\n };\n}" } } ] } ``` --- ### `getApis` — 获取所有 API 获取当前项目中已配置的全部 API 列表。 **参数:** 无 **返回:** `ApiSchema[]` 数组,每项包含 `id`、`name`、`url`、`method`、`label`、`category` 等字段 --- ### `removeApi` — 删除单个 API 通过名称或 ID 删除一条 API。 **参数:** - `name: string` — API 名称或 ID --- ### `removeApis` — 批量删除 API 批量删除多条 API。 **参数:** - `apis: string[]` — API 名称或 ID 数组 --- ## 三、API 完整配置(ApiSchema) 设计器表单分为 4 个 Tab:**基础信息**、**请求配置**、**模拟数据**、**接口测试**。以下是 `ApiSchema` 的完整字段: ### 3.1 基础信息(必填) | 字段 | 类型 | 必填 | 说明 | | ---------- | ------ | -------- | --------------------------------------------------------------- | | `id` | string | 自动生成 | 唯一标识(UUID),系统自动分配 | | `name` | string | ✅ | 接口名称,camelCase,如 `getUserList`,该名称也是组件中调用的键 | | `label` | string | ✅ | 接口描述说明 | | `url` | string | ✅ | 请求 URL,支持路径参数占位符如 `/api/users/:id` | | `method` | string | ✅ | 请求方法:`get` / `post` / `put` / `delete` / `patch` / `jsonp` | | `category` | string | ❌ | 分组名称,用于 UI 分类展示 | ### 3.2 请求配置(settings + headers) | 字段 | 类型 | 默认值 | 说明 | | ------------------------- | ------------ | ------- | --------------------------------------------------------------------- | | `settings.type` | string | `form` | 发送数据类型:`form`(表单)、`json`(JSON)、`data`(文件/FormData) | | `settings.loading` | boolean | `true` | 请求时是否显示全局 loading 动画 | | `settings.failMessage` | boolean | `true` | 请求失败时是否弹出错误提示 | | `settings.validSuccess` | boolean | `true` | 是否校验响应是否成功(调用全局 validate 函数) | | `settings.originResponse` | boolean | `false` | 是否返回原始 Axios 响应对象(而非 data 部分) | | `settings.injectHeaders` | boolean | `false` | 是否注入请求拦截器中自定义的请求头 | | `settings.proxy` | boolean | `false` | 是否开启请求代理 | | `headers` | JSExpression | `({})` | 请求头配置,值为 JS 表达式字符串 | **headers 示例:** ```javascript // headers.value 的内容是一个 JS 表达式 ({ 'Content-Type': 'application/json', 'X-Custom-Header': 'value' }); ``` ### 3.3 模拟数据(mock) | 字段 | 类型 | 默认值 | 说明 | | -------------- | ---------- | ------- | ---------------- | | `mock` | boolean | `false` | 是否开启模拟数据 | | `mockTemplate` | JSFunction | — | 模拟数据模板函数 | **mockTemplate 函数签名:** `(req) => template` `req` 参数提供的信息: | 属性 | 说明 | | ------------ | ------------ | | `req.url` | 请求 URL | | `req.type` | 请求方法类型 | | `req.data` | 请求体数据 | | `req.params` | URL 路径参数 | | `req.query` | URL 查询参数 | 函数返回的数据会被 Mock.js 处理生成随机模拟数据: ```javascript (req) => { return { code: 0, message: 'ok', data: { id: '@guid', name: '@cname', 'age|18-60': 1 } }; }; ``` > 模板使用 Mock.js 语法规则,参考:https://vtj.pro/help/mock.html ### 3.4 jsonp 专用配置 当 `method` 为 `jsonp` 时,额外提供以下字段: | 字段 | 类型 | 说明 | | ------------------------------------ | ------- | ---------------- | | `jsonpOptions.jsonpCallback` | string | 回调函数名 | | `jsonpOptions.jsonpCallbackFunction` | string | 回调函数 | | `jsonpOptions.timeout` | number | 超时时间(毫秒) | | `jsonpOptions.crossorigin` | boolean | 是否跨域 | ### 3.5 常见问题 #### 返回数据异常或 `undefined` 如果调用 API 后发现返回数据不符合预期(如为 `undefined`、缺少字段或结构不对),请检查以下两处 `originResponse` 配置是否一致: 1. **应用设置中的全局请求配置**(`setGlobalAxios`) 2. **单个 API 的请求配置**(`setApi` 的 `settings.originResponse`) **原理说明:** - 当 `originResponse: false`(默认)时,VTJ 自动提取并返回 `res.data.data`,即后端响应体中的业务数据 - 当 `originResponse: true` 时,返回完整的 Axios 响应对象,需通过 `res.data` 或 `res.data.data` 手动取值 - 单个 API 的 `settings.originResponse` 会覆盖全局配置 **典型错误场景:** ```javascript // 错误示例 1:全局 originResponse: true,但代码按业务数据处理 const res = await __apis['getUserList'](); this.list = res.data.data.list; // ❌ res 已经是原始响应对象,res.data 才是后端响应体 // 正确写法 const res = await __apis['getUserList'](); this.list = res.data.data.list; // ✅ 若全局 originResponse: true,需 res.data.data // 或者改为 this.list = res.list; // ✅ 若全局 originResponse: false ``` ```javascript // 错误示例 2:全局 originResponse: false,但代码按原始响应对象处理 const res = await __apis['getUserList'](); console.log(res.status); // ❌ res 是业务数据,没有 status 属性 // 正确写法:临时开启 originResponse const res = await __apis['getUserList']( {}, { settings: { originResponse: true } } ); console.log(res.status); // ✅ 200 ``` **排查步骤:** 1. 确认应用设置中 `setGlobalAxios` 的 `settings.originResponse` 值 2. 确认该 API 在 `setApi` 中是否单独设置了 `settings.originResponse` 3. 确保组件中处理响应数据的方式与当前生效的 `originResponse` 值匹配 #### 请求成功但进入 `catch` 或弹出错误提示 如果接口实际已返回 200 且数据正常,但代码进入了 `catch` 分支,或页面弹出了错误提示,请检查 `validSuccess` 配置: 1. **应用设置中的全局请求配置**(`setGlobalAxios` 的 `settings.validSuccess`) 2. **单个 API 的请求配置**(`setApi` 的 `settings.validSuccess`) 3. **全局请求配置中的 `validate` 函数**是否与后端响应结构匹配 **原理说明:** - 当 `validSuccess: false`(默认)时,VTJ 不校验后端业务响应码,只要 HTTP 状态码为 2xx 即视为成功 - 当 `validSuccess: true` 时,VTJ 会调用 `validate` 函数对响应体进行业务成功校验;若 `validate` 返回 `false`,请求会被视为失败,Promise 被 `reject` 并弹出错误提示 - 全局默认 `validate` 函数逻辑为:`res.data?.code === 0 || !!res.data?.success`,即要求后端响应体中包含 `code: 0` 或 `success: true` - 单个 API 的 `settings.validSuccess` 会覆盖全局配置 **典型错误场景:** ```javascript // 错误示例 1:后端返回结构不匹配默认 validate // 后端响应:{ status: 'ok', data: [...] } const res = await __apis['getUserList'](); // ❌ 若 validSuccess: true,默认 validate 找不到 code/success,判定失败,进入 catch // 解决方案:自定义 validate 函数匹配后端结构 { "action": "setGlobalAxios", "parameters": [ "(app) => {\n return {\n settings: {\n validSuccess: true,\n validate: (res) => {\n return res.data?.status === 'ok';\n }\n }\n };\n}" ] } ``` ```javascript // 错误示例 2:未处理 validSuccess 导致的 reject // 全局 validSuccess: true,但代码未加 try/catch const res = await __apis['getUserList'](); // ❌ 校验失败时会抛出异常,导致后续代码不执行 // 正确写法 try { const res = await __apis['getUserList'](); this.list = res; } catch (e) { // 校验失败或请求异常时进入此处 console.error('请求失败', e); } ``` ```javascript // 错误示例 3:某个 API 不需要校验但全局 validSuccess: true // 该 API 后端返回无固定 code/success 结构 const res = await __apis['getRawData'](); // ❌ 被全局 validate 误判为失败 // 解决方案:该 API 单独关闭 validSuccess { "action": "setApi", "parameters": [ { "name": "getRawData", "url": "/api/raw", "settings": { "validSuccess": false } } ] } ``` **排查步骤:** 1. 确认应用设置中 `setGlobalAxios` 的 `settings.validSuccess` 值 2. 确认全局 `validate` 函数逻辑是否与后端实际响应结构匹配(如 `code`、`success`、`status` 等字段) 3. 确认该 API 在 `setApi` 中是否单独设置了 `settings.validSuccess` 4. 若 `validSuccess: true`,确保调用处已处理 `reject` 场景(`try/catch` 或 `.catch()`) --- ## 四、组件中调用 API ### 4.1 基本调用 API 在运行时通过 `__apis` 全局变量访问,键名为 API 的 `name` 或 `id`: ```javascript // 无参数 GET 请求 const res = await __apis['getUserList'](); // POST 请求,带请求体 const res = await __apis['createUser']({ name: '张三', age: 28 }); ``` **调用签名:** ``` (data?, opts?) => Promise ``` - `data` — 请求体数据(GET/JSONP 时通常为空) - `opts` — 额外配置,可覆盖 API 的默认 settings,也可传递路径参数(`opts.params`)和查询参数(`opts.query`) ### 4.2 路径参数(URL 中的 `:id` 占位符) 如果 API 的 URL 包含路径参数(如 `/api/users/:id`),通过第二个参数 `opts.params` 传入: ```javascript // URL: /api/users/:id const user = await __apis['getUserById']( {}, // 无请求体 { params: { id: 'abc123' } } // 路径参数 ); // URL: /api/orders/:orderId/items/:itemId const item = await __apis['getOrderItem']( {}, { params: { orderId: '100', itemId: '5' } } ); ``` ### 4.3 查询参数 查询参数(即 `?key=value`)通过 `opts.query` 传入: ```javascript // 最终请求: /api/users?page=1&size=20&keyword=张三 const res = await __apis['getUserList']( {}, { query: { page: 1, size: 20, keyword: '张三' } } ); ``` > **区分:** `opts.params` 用于替换 URL 中的路径占位符(如 `/api/users/:id`),`opts.query` 用于拼接 URL 查询字符串(`?key=value`)。两者不可混用。 ### 4.4 覆盖请求配置 `opts` 参数支持临时覆盖 API 的 settings: ```javascript // 本次请求不显示 loading,不显示错误提示 const res = await __apis['getUserList']( {}, { settings: { loading: false, failMessage: false } } ); // 自定义请求头 const res = await __apis['getUserList']( {}, { settings: { injectHeaders: true }, headers: { 'X-Device': 'mobile' } } ); ``` ### 4.5 响应数据提取与 `originResponse` VTJ 的请求底层基于 Axios,后端接口通常返回如下格式的响应体: ```json { "code": 0, "msg": "ok", "data": { ... } } ``` **默认行为(`originResponse: false`):** 请求成功后,VTJ 自动提取 `res.data.data`,即只返回响应体中 `data` 字段的值,省去手动 `.data.data` 的取值步骤: ```javascript // 默认 originResponse: false const res = await __apis['getUserList'](); // res 直接是 { list: [...], total: 100 },而非完整的响应包装 ``` **开启 `originResponse: true`:** 返回完整的 Axios 响应对象(`AxiosResponse`),包含以下属性: | 属性 | 说明 | | ------------- | ------------------------------- | | `res.data` | 响应体(即后端返回的完整 JSON) | | `res.status` | HTTP 状态码(如 200) | | `res.headers` | 响应头对象 | | `res.config` | 请求配置对象 | 适用场景: - 需要读取 HTTP 响应头(如分页总数 `X-Total-Count`、下载文件的 `Content-Disposition`) - 需要判断 HTTP 状态码做差异化处理 - 需要访问后端响应体的顶层字段(如 `code`、`msg`),而不仅是 `data` 部分 **设置方式:** 1. **在 API 配置中全局设置:** ```json { "action": "setApi", "parameters": [ { "name": "getFileList", "url": "/api/files", "method": "get", "settings": { "originResponse": true } } ] } ``` 2. **在调用时临时覆盖:** ```javascript // 临时获取原始响应对象 const res = await __apis['getUserList']( {}, { settings: { originResponse: true } } ); console.log(res.status); // 200 console.log(res.headers); // { 'x-total-count': '50', ... } console.log(res.data); // { code: 0, msg: 'ok', data: { list: [...] } } ``` **示例:读取分页响应头** ```javascript const __state = reactive({ list: [], total: 0, async fetchPage(page = 1) { // 后端通过响应头返回总数 const res = await __apis['getUserList']( {}, { query: { page, size: 20 }, settings: { originResponse: true } } ); this.list = res.data.data || []; // res.data 是响应体,res.data.data 是业务数据 this.total = Number(res.headers['x-total-count']) || 0; } }); ``` **示例:读取下载文件响应** ```javascript const __state = reactive({ async downloadFile(id) { const res = await __apis['downloadFile']( {}, { params: { id }, settings: { originResponse: true } } ); // 从响应头获取文件名 const disposition = res.headers['content-disposition']; const filename = disposition?.match(/filename=(.+)/)?.[1] || 'unknown.bin'; // res.data 为文件二进制内容(需配合 responseType: 'blob') return { content: res.data, filename }; } }); ``` > **注意:** 开启 `originResponse` 后,返回值从业务数据变为 Axios 响应对象,取值路径需相应调整。默认返回 `res.data.data`,开启后需手动访问 `res.data.data` 或 `res.data`(取决于后端响应结构)。 ### 4.6 JSONP 请求 JSONP 类型 API 的调用签名特殊: ```javascript (query?) => Promise ``` ```javascript // 设置 API: method = 'jsonp', url = 'https://api.example.com/data' const res = await __apis['getExternalData']({ userId: '123', callback: 'jsonpCallback' }); ``` ### 4.7 Vue SFC 中使用 在 ` ``` --- ## 五、典型使用场景 ### 5.1 API 基础地址 ```json { "action": "createEnv", "parameters": [ { "name": "API_BASE_URL", "development": "http://localhost:3000/api", "production": "https://api.myapp.com" } ] } ``` 组件中使用环境变量拼接 API URL: ```javascript // 注意:API 的 url 字段可直接使用相对路径 /api/users, // 实际请求地址由全局 axios 的 baseURL 决定。 // 环境变量更适用于非请求场景的地址引用。 const uploadUrl = `${__provider.env.API_BASE_URL}/upload`; ``` ### 5.2 功能开关 ```json { "action": "createEnv", "parameters": [ { "name": "ENABLE_DEBUG_PANEL", "development": "true", "production": "false" } ] } ``` 组件中: ```html ``` ### 5.3 第三方 Key / 配置 ```json { "action": "createEnv", "parameters": [ { "name": "MAP_KEY", "development": "dev-abc123", "production": "prod-xyz789" } ] } ``` --- ## 六、注意事项 1. **值类型为字符串:** `EnvConfig` 的 `development` 和 `production` 字段类型均为 `string`,布尔值需使用 `'true'` / `'false'` 字符串 2. **同名不覆盖:** `createEnv` 不检查同名变量是否已存在,直接追加。如需更新,建议先 `removeEnv` 再 `createEnv` 3. **运行时自动选取:** `initEnv()` 根据 `provider.nodeEnv`(`development` 或 `production`)自动选择对应值,无需手动判断环境 4. **变量名约定:** 推荐使用大写字母 + 下划线命名(`UPPER_SNAKE_CASE`),如 `BASE_URL`、`APP_TITLE` 5. **脚本层访问:** 环境变量通过 `__provider.env` 实例属性访问,不是 `$provider.env` 或 `this.$provider.env` 6. **不在 `__state` 中存储:** 环境变量是全局只读配置,不要将 `__provider.env` 的值复制到 `__state` 中,直接在需要的地方读取即可 7. **不需要手动 import:** `__provider` 由框架在组件模板中通过 `useProvider()` 自动声明,组件内直接使用 # @vtj/renderer 全局 API 使用指南 > 本文档描述 `@vtj/renderer` 提供的全局变量在 Vue 组件中的使用方式,供 AI 大模型生成代码时参考。 --- ## 重要约定 这些全局变量由 `@vtj/renderer` 提供,AI 生成代码时可选择以下任一方式使用: - **直接使用变量名**(推荐):在方法体内直接使用 `__store`、`__apis` 等变量,无需手动声明或导入,框架会在生成的 ` ``` # VTJ 国际化(i18n)— AI 配置与使用指南 > 本文档帮助 AI 理解如何通过工具方法配置国际化词条,以及在组件中实现多语言文本。 --- ## 一、数据流全貌 ``` 设计器 i18n 面板 项目数据 渲染引擎 i18n/index.vue ──setI18n()──▶ project.i18n ──initI18n()──▶ VueI18n 插件注册 (表格编辑) (I18nConfig) (消息格式转换) (app.use) │ [ { key, 'zh-CN', en } ] → { 'zh-CN': { key: value }, en: { key: value } } ``` **关键流程:** 1. **词条存储:** 设计器以扁平数组形式存储 `[{ key, 'zh-CN', en }]` 2. **渲染器转换:** `initI18n()` 将扁平数组转为 locale 分组的嵌套对象 `{ 'zh-CN': { key: value }, en: { key: value } }` 3. **插件注册:** 通过 `VueI18n.createI18n()` 创建 vue-i18n 实例,以 Composable API 模式(`legacy: false`)注册到 Vue 应用 4. **全局可用:** 组件中通过 `__i18n` 访问翻译功能,模板和 script 均使用 `__i18n.t('key')` --- ## 二、I18n 工具方法 ### `getI18nMessage` — 获取所有词条 获取当前项目已配置的全部中英对照词条。 **参数:** 无 **返回:** `I18nMessage[]` 数组,每项包含 `key`、`zh-CN`、`en` --- ### `createI18nMessage` — 新增词条 新增一条中英文对照词条。`key` 必须唯一,重复的 `key` 会覆盖。 **参数:** | 参数 | 类型 | 必填 | 说明 | | --------------- | ------ | ---- | -------------------------------------------------------------------- | | `message.key` | string | ✅ | 词条标识,推荐点号分层命名,如 `common.confirm`、`user.profile.name` | | `message.zh-CN` | string | ✅ | 简体中文内容 | | `message.en` | string | ✅ | 英文内容 | **示例:** ```json { "action": "createI18nMessage", "parameters": [ { "key": "common.submit", "zh-CN": "提交", "en": "Submit" } ] } ``` **批量创建词条:** 需要多次调用此工具,每次传入一条。 --- ### `removeI18nMessage` — 删除词条 通过 `key` 删除指定词条。 **参数:** - `key: string` — 词条标识 **示例:** ```json { "action": "removeI18nMessage", "parameters": ["common.submit"] } ``` --- ## 三、语言设置(locale / fallbackLocale) 国际化有两个全局设置: | 设置项 | 键名 | 可选值 | 说明 | | -------- | ---------------- | -------------- | ---------------------- | | 默认语言 | `locale` | `zh-CN` / `en` | 应用启动时使用的语言 | | 回退语言 | `fallbackLocale` | `zh-CN` / `en` | 找不到翻译时的兜底语言 | > ⚠️ **暂无对应工具方法。** 当前 `locale` 和 `fallbackLocale` 只能通过设计器 i18n 面板的「设置」按钮手动配置,无对应的 AI 工具调用。如未配置,默认均为 `zh-CN`。 --- ## 四、组件中使用国际化 ### 4.1 模板中使用(推荐方式) > VTJ 使用 vue-i18n Composition API 模式(`legacy: false`),模板中必须使用 `__i18n.t()`,不支持 Options API 的 `$t()`。 ```html ``` ### 4.2 script 中使用 在 ` ``` --- ## 五、词条 Key 命名规范 推荐使用点号分层的命名方式,按「模块.页面.元素」的结构组织: | 规范 | 示例 Key | 中文值 | 说明 | | -------- | --------------------- | ---------------- | -------------------- | | 通用类 | `common.submit` | 提交 | 跨页面复用的通用文案 | | | `common.cancel` | 取消 | | | | `common.confirm` | 确认 | | | | `common.delete` | 删除 | | | | `common.back` | 返回 | | | 表格类 | `table.empty` | 暂无数据 | 表格空状态 | | | `table.search` | 查询 | | | | `table.reset` | 重置 | | | 业务页面 | `user.list.title` | 用户列表 | 特定页面的标题 | | | `user.list.create` | 新增用户 | | | | `user.profile.name` | 姓名 | 用户详情字段 | | | `order.detail.status` | 状态 | 订单状态标签 | | 表单校验 | `validation.required` | 此项必填 | 表单校验提示 | | | `validation.email` | 邮箱格式不正确 | | | 操作提示 | `tips.deleteConfirm` | 确定删除该项? | 操作前的确认提示 | | | `tips.saveSuccess` | 保存成功 | | | | `tips.saveFailed` | 保存失败,请重试 | | --- ## 六、典型工作流程 ### 6.1 新建项目时的 i18n 配置流程 ``` 1. 分析页面中的静态文案,整理成词条清单 2. 逐条调用 createI18nMessage 创建词条 3. 在 Vue 模板中使用 __i18n.t('key') 替代硬编码文本 ``` ### 6.2 新增页面时 ``` 1. 查看现有词条:getI18nMessage 2. 复用已有词条(如 common.*) 3. 创建新词条:createI18nMessage 4. 在生成的 Vue 代码中使用 __i18n.t('key') ``` --- ## 七、带插值参数的翻译 词条中可以包含 `{name}` 占位符,调用时传入参数: ```json { "action": "createI18nMessage", "parameters": [ { "key": "user.welcome", "zh-CN": "欢迎回来,{name}!", "en": "Welcome back, {name}!" } ] } ``` 模板中使用: ```html {{ __i18n.t('user.welcome', { name: __state.userName }) }} ``` Script 中使用: ```javascript const msg = __i18n.t('user.welcome', { name: __state.userName }); ``` --- ## 八、注意事项 1. **key 必须唯一:** 重复的 key 会导致词条覆盖,创建前可通过 `getI18nMessage` 确认 2. **`zh-CN` 和 `en` 均必须填写:** 每条词条的中英文内容均不可为空 3. **统一使用 `__i18n.t()`:** VTJ 使用 Composition API 模式(`legacy: false`),模板和 script 中均使用 `__i18n.t('key')`,不支持 Options API 的 `$t()` 写法 4. **不需要手动 import:** `__i18n` 是由 `vue-i18n` 的 `useI18n()` 提供的全局变量,框架已自动注入,组件中无需手动导入 5. **设置后需 `refresh` 生效:** 通过工具新增词条后,需要调用 `refresh` 刷新运行时才能看到效果 6. **locale/fallbackLocale 无工具:** 默认语言和回退语言需通过设计器面板手动配置 # @vtj/icons 图标库 — AI 使用指南 > 本文档帮助 AI 理解 `@vtj/icons` 图标库的构成、导入方式和在 Vue 组件中的使用规范。 --- ## 一、图标库构成 `@vtj/icons` 包含四类图标来源: | 来源 | 说明 | 组件类型 | | ---------------------------------------------------- | -------------------------------------- | ---------------------------- | | **SVG 组件**(`./components`) | 内置 SVG 图标,Vue 组件形式 | Vue 组件,支持 `colors` 属性 | | **Iconfont 图标**(`./icons`) | 自定义 CSS 图标字体,`VtjIconXxx` 命名 | Vue 组件(CSS 类实现) | | **Element Plus 图标**(re-export from `@vtj/icons`) | 全量 re-exported Element Plus 图标 | Vue 组件 | | **Assets 图标**(`./assets`) | SVG 资源文件导入,`IconXxx` 命名 | SVG 字符串/路径资源 | 所有图标均可作为 Vue 组件使用。全局注册后可在模板中直接使用标签名;按需导入时需配合 `XIcon` 组件(来自 `@vtj/ui`)使用。 --- ## 二、安装与注册 ### 2.1 安装依赖 ```json { "dependencies": { "@vtj/icons": "workspace:~" } } ``` ### 2.2 全局注册(推荐) ```typescript import { createApp } from 'vue'; import { IconsPlugin } from '@vtj/icons'; import '@vtj/icons/dist/style.css'; const app = createApp(App); app.use(IconsPlugin); // 注册所有图标为全局组件 ``` 或使用独立 `install` 方法: ```typescript import { install } from '@vtj/icons/install'; import '@vtj/icons/dist/style.css'; install(app); ``` ### 2.3 按需导入 按需导入时,图标需通过 `XIcon` 组件渲染。`XIcon` 的 `icon` 属性接收图标组件引用,通过 `:icon="IconName"` 传递: ```vue ``` --- ## 三、SVG 组件图标 ### 3.1 图标列表 以下图标位于 `@vtj/icons` 的 SVG 组件目录,直接按名称导入: | 组件名 | 说明 | | ---------------- | ---------- | | `Fullscreen` | 全屏 | | `ExitFullscreen` | 退出全屏 | | `Fixed` | 固定 | | `UnFixed` | 取消固定 | | `Visible` | 可见 | | `Invisible` | 不可见 | | `Maximize` | 最大化 | | `Minimize` | 最小化 | | `Popup` | 弹出 | | `LineHeight` | 行高 | | `Rows` | 行布局 | | `Skin` | 皮肤 | | `QrCodeLogin` | 二维码登录 | | `RawClose` | 原始关闭 | | `RawLock` | 原始锁定 | | `RawUnLock` | 原始解锁 | | `UserLogin` | 用户登录 | ### 3.2 用法 SVG 组件支持 `colors` 属性传递颜色数组,按 path 顺序着色。按需导入时需通过 `XIcon` 渲染: ```vue ``` > **全局注册后**也可直接使用标签名:``、``。 --- ## 四、Iconfont 图标 ### 4.1 命名规则 所有 iconfont 图标以 `VtjIcon` 为前缀,驼峰命名。相互对应 CSS class 以 `vtj-icon-` 为前缀,短横线命名: | 组件名 | CSS Class | | ------------------- | ---------------------- | | `VtjIconSetting` | `vtj-icon-setting` | | `VtjIconArrowRight` | `vtj-icon-arrow-right` | | `VtjIconAi` | `vtj-icon-ai` | | `VtjIconUser` | `vtj-icon-user` | | `VtjIconSave` | `vtj-icon-save` | ### 4.2 完整图标列表 #### 通用操作类 | 组件名 | 说明 | | ------------------ | -------- | | `VtjIconAdd` | 添加 | | `VtjIconRemove` | 移除 | | `VtjIconDelete` | 删除 | | `VtjIconEdit` | 编辑 | | `VtjIconCopy` | 复制 | | `VtjIconSave` | 保存 | | `VtjIconSearch` | 搜索 | | `VtjIconRefresh` | 刷新 | | `VtjIconClose` | 关闭 | | `VtjIconCheck` | 勾选 | | `VtjIconHelp` | 帮助 | | `VtjIconInfo` | 信息 | | `VtjIconMore` | 更多 | | `VtjIconShare` | 分享 | | `VtjIconLock` | 锁定 | | `VtjIconUnlock` | 解锁 | | `VtjIconExport` | 导出 | | `VtjIconImport` | 导入 | | `VtjIconUpload` | 上传 | | `VtjIconDownload` | 下载 | | `VtjIconPreview` | 预览 | | `VtjIconPublish` | 发布 | | `VtjIconSwitch` | 切换 | | `VtjIconFixed` | 固定 | | `VtjIconUnfixed` | 取消固定 | | `VtjIconVisible` | 可见 | | `VtjIconInvisible` | 不可见 | #### 方向箭头类 | 组件名 | 说明 | | ------------------- | ------ | | `VtjIconArrowRight` | 箭头右 | | `VtjIconArrowLeft` | 箭头左 | | `VtjIconArrowDown` | 箭头下 | | `VtjIconArrowUp` | 箭头上 | | `VtjIconGreater` | 大于号 | | `VtjIconSmaller` | 小于号 | | `VtjIconBack` | 返回 | | `VtjIconExpand` | 展开 | | `VtjIconCollapsed` | 收起 | | `VtjIconRedo` | 重做 | | `VtjIconUndo` | 撤销 | #### 导航与布局类 | 组件名 | 说明 | | -------------------- | -------- | | `VtjIconHome` | 首页 | | `VtjIconMenu` | 菜单 | | `VtjIconCategory` | 分类 | | `VtjIconProject` | 项目 | | `VtjIconTemplate` | 模板 | | `VtjIconComponents` | 组件 | | `VtjIconBlock` | 区块 | | `VtjIconPageSetting` | 页面设置 | | `VtjIconLayers` | 图层 | | `VtjIconOutline` | 大纲 | | `VtjIconDeps` | 依赖 | | `VtjIconData` | 数据 | | `VtjIconFile` | 文件 | | `VtjIconFolder` | 文件夹 | | `VtjIconDocument` | 文档 | | `VtjIconHistory` | 历史 | | `VtjIconNotice` | 通知 | | `VtjIconFav` | 收藏 | #### 设备与窗口类 | 组件名 | 说明 | | ----------------------- | ---------- | | `VtjIconPc` | PC 设备 | | `VtjIconPhone` | 手机设备 | | `VtjIconPad` | 平板设备 | | `VtjIconUniapp` | UniApp | | `VtjIconFullscreen` | 全屏 | | `VtjIconExitFullscreen` | 退出全屏 | | `VtjIconWindowMax` | 窗口最大化 | | `VtjIconWindowMin` | 窗口最小化 | | `VtjIconWindowClose` | 窗口关闭 | | `VtjIconWindowNormal` | 窗口还原 | | `VtjIconWindowDown` | 窗口下移 | | `VtjIconWindowUp` | 窗口上移 | #### AI 与工具类 | 组件名 | 说明 | | ------------------- | ---------- | | `VtjIconAi` | AI | | `VtjIconNewChat` | 新建对话 | | `VtjIconChatRecord` | 对话记录 | | `VtjIconEnv` | 环境变量 | | `VtjIconConfig` | 配置 | | `VtjIconLang` | 语言 | | `VtjIconGlobal` | 全局 | | `VtjIconApi` | API | | `VtjIconOpenapi` | OpenAPI | | `VtjIconSwagger` | Swagger | | `VtjIconDevTools` | 开发者工具 | | `VtjIconDiff` | 差异对比 | | `VtjIconMaster` | 主控 | | `VtjIconConsole` | 控制台 | | `VtjIconTeam` | 团队 | | `VtjIconBug` | Bug | | `VtjIconVars` | 变量 | | `VtjIconJs` | JS | | `VtjIconDatabase` | 数据库 | #### 面板定位类 | 组件名 | 说明 | | -------------------- | -------- | | `VtjIconTopPanel` | 顶部面板 | | `VtjIconBottomPanel` | 底部面板 | | `VtjIconLeftPanel` | 左侧面板 | | `VtjIconRightPanel` | 右侧面板 | #### 业务操作类(Np 前缀) | 组件名 | 说明 | | -------------------- | -------- | | `VtjIconNpAdd` | 新增 | | `VtjIconNpAddRow` | 新增行 | | `VtjIconNpRemove` | 移除 | | `VtjIconNpRemoveRow` | 移除行 | | `VtjIconNpDelete` | 删除 | | `VtjIconNpEdit` | 编辑 | | `VtjIconNpSave` | 保存 | | `VtjIconNpCancel` | 取消 | | `VtjIconNpConfirm` | 确认 | | `VtjIconNpSubmit` | 提交 | | `VtjIconNpReset` | 重置 | | `VtjIconNpSearch` | 搜索 | | `VtjIconNpSelect` | 选择 | | `VtjIconNpExport` | 导出 | | `VtjIconNpImport` | 导入 | | `VtjIconNpList` | 列表 | | `VtjIconNpPrint` | 打印 | | `VtjIconNpShare` | 分享 | | `VtjIconNpFile` | 文件 | | `VtjIconNpRefresh` | 刷新 | | `VtjIconNpReturn` | 返回 | | `VtjIconNpReturnAll` | 全部返回 | | `VtjIconNpExit` | 退出 | | `VtjIconNpClose` | 关闭 | | `VtjIconNpExtend` | 扩展 | ### 4.3 用法 按需导入时通过 `XIcon` 渲染 Iconfont 图标: ```vue ``` > **全局注册后**也可直接使用标签名:``。 Iconfont 图标本质是 `` 元素,可通过 CSS 控制大小和颜色: ```css .vtj-icon-setting { font-size: 18px; color: var(--el-text-color-primary); } ``` ```css .vtj-icon-setting { font-size: 18px; color: var(--el-text-color-primary); } ``` --- ## 五、Element Plus 图标 `@vtj/icons` 全量 re-export Element Plus 的所有图标,直接按 Element Plus 官方名称导入使用。 按需导入时通过 `XIcon` 渲染: ```vue ``` 全量图标列表参见 [Element Plus Icons 文档](https://element-plus.org/zh-CN/component/icon.html)。 --- ## 六、Assets 图标 Assets 图标是 SVG 资源导入,以 `Icon` 为前缀命名。它们本质是 SVG 文件路径,适用于非组件场景(如设计器面板预览图、占位图等)。 ```typescript import { IconButton, IconTable, IconForm, IconInput, IconImage, IconMenu, IconPage, IconSetting } from '@vtj/icons'; ``` Assets 图标数量约 300+,涵盖以下类别: - **组件类:** `IconButton`、`IconInput`、`IconTable`、`IconForm`、`IconSelect`、`IconRadio`、`IconCheckbox`、`IconDatepick`、`IconTabs`、`IconTag`、`IconCarousel`、`IconSwiper` 等 - **布局类:** `IconRow`、`IconCol`、`IconGrid`、`IconDisplayFlex`、`IconDisplayBlock`、`IconHr`、`IconDivider`(对应 `IconLine`)等 - **样式类:** `IconBorderAll`、`IconMargin`、`IconPadding`、`IconBackgroundColor`、`IconBackgroundImage`、`IconTextAlignCenter`、`IconFontStyleItalic` 等 - **光标类:** `IconCursorPointer`、`IconCursorMove`、`IconCursorGrab`、`IconCursorText`、`IconCursorZoomIn` 等 - **状态类:** `IconEmpty`、`IconEmptyData`、`IconEmptyAction`、`IconLoading`、`IconSuccess`(对应 `IconFlowSuccess`)、`IconError`、`IconWarning`、`IconAlert` 等 - **操作类:** `IconAdd`、`IconDelete`、`IconEdit`、`IconCopy`、`IconSave`、`IconSearch`、`IconRefresh`、`IconPreview`、`IconReturn`、`IconClose`、`IconClear` 等 - **Flow 类:** `IconFlowAdd`、`IconFlowDelete`、`IconFlowEdit`、`IconFlowCheckmark`、`IconFlowCross`、`IconFlowSuccess`、`IconFlowFailure` 等 - **插件类:** `IconPluginIconData`、`IconPluginIconJs`、`IconPluginIconPage`、`IconPluginIconTree`、`IconPluginIconRobot` 等 - **其他:** `IconPage`、`IconHome`、`IconUserLocked`、`IconLocation`、`IconLanguage`、`IconTinyLogo` 等 --- ## 七、模板中使用规范 ### 7.1 全局注册后使用(推荐) 全局注册后,所有图标均为全局组件,模板中直接使用标签名: ```html ``` ### 7.2 按需导入使用(推荐) 按需导入时,通过 `XIcon` 组件渲染图标,并可自由控制大小和颜色: ```vue ``` ### 7.3 动态图标 ```vue ``` > 注意:动态切换时,`XIcon` 的 `:icon="variable"` 中 `variable` 应始终持有图标的 Vue 组件引用(即 `import` 后的变量名),而不是字符串。 ### 7.4 Assets 图标通过 `src` 属性使用 Assets 图标本质是 SVG 文件路径,通过 `XIcon` 的 `src` 属性渲染: ```vue ``` --- ## 八、VTJ Composition API 完整示例 以下示例展示按需导入模式,使用 `XIcon` 渲染各类图标: ```vue ``` > 全局注册后则无需 `import { XIcon }` 和图标组件,直接在模板中使用标签名即可。 --- ## 九、注意事项 1. **全局注册后可直接使用:** 使用 `IconsPlugin` 或 `install` 全局注册后,所有图标在模板中直接使用标签名,无需手动 import 2. **按需导入需配合 XIcon:** 未全局注册时,需从 `@vtj/ui` 导入 `XIcon`,通过 `:icon="IconName"` 传递图标组件引用 3. **`icon` 属性传递组件引用:** `XIcon` 的 `:icon` 接收 Vue 组件对象(即 `import` 后的变量名),并非字符串路径 4. **Assets 图标用 `src` 属性:** Assets 图标(`IconXxx`)通过 `XIcon` 的 `:src="IconName"` 属性渲染,不是 `:icon` 5. **XIcon 支持 `size` 和 `color`:** `:size` 可传数字或 `'small'`/`'default'`/`'large'`/`'inherit'`,`color` 传 CSS 色值字符串 6. **Iconfont 图标默认颜色:** `VtjIconXxx` 通过 `XIcon` 渲染时,`color` 属性控制颜色;全局注册直接使用时通过 CSS `color` 控制 7. **SVG 组件 `colors` 属性:** SVG 组件支持 `colors` 数组按 path 顺序着色,但需通过 `` 或全局注册后直接标签使用 8. **样式文件:** 需要导入 `@vtj/icons/dist/style.css` 以确保 iconfont 字体和 SVG 组件样式生效 9. **无需耗时搜索图标名称:** 上述列表已覆盖所有图标,直接从列表中选取即可 # VTJ 应用设置 — AI 配置指南 > 本文档帮助 AI 理解如何通过工具方法配置应用级别的全局设置。 > 设计器的"应用设置"面板提供 9 个配置项,覆盖 3 大类:全局配置、请求配置、路由守卫。 > 这些配置最终存储在 `project.globals` 中,由渲染引擎在初始化时按顺序执行。 --- ## 一、数据流全貌 ``` 设计器面板 项目数据 渲染引擎 globals/index.vue ──setGloblas()──▶ project.globals ──initRuntimeGlobals()──▶ 运行时生效 (UI) (GlobalConfig) (globals.ts) ``` **关键流程:** 1. 通过工具方法设置 → 存入 `project.globals`(`GlobalConfig` 类型) 2. 应用启动时 `Provider.install()` → 调用 `initGlobals()` → 调用 `initRuntimeGlobals()` 3. 渲染引擎按**固定顺序**初始化各项配置 > **注意:** 设计模式(Design Mode)下 `initGlobals` 不会被调用,仅在预览/运行时生效。 --- ## 二、配置项与工具方法对照表 | 设计器面板项 | 配置键名 | 设置工具 | 查询工具 | 值类型 | | --------------------------- | ------------ | ------------------------------ | ------------------------------ | ---------- | | 应用全局「CSS」 | `css` | `setGlobalCss` | `getGlobalCss` | CSS 字符串 | | 应用状态「Pinia」 | `store` | `setGlobalStore` | `getGlobalStore` | JS 函数 | | 权限控制「Access」 | `access` | `setGlobalAccess` | `getGlobalAccess` | JS 函数 | | 应用增强「JS」 | `enhance` | ⚠️ 暂无工具 | ⚠️ 暂无工具 | JS 函数 | | 请求配置「IRequestOptions」 | `axios` | `setGlobalAxios` | `getGlobalAxios` | JS 函数 | | 请求拦截器 | `request` | `setGlobalRequestInterceptor` | `getGlobalRequestInterceptor` | JS 函数 | | 响应拦截器 | `response` | `setGlobalResponseInterceptor` | `getGlobalResponseInterceptor` | JS 函数 | | 前置守卫「beforeEach」 | `beforeEach` | `setGlobalBeforeEach` | `getGlobalBeforeEach` | JS 函数 | | 后置守卫「afterEach」 | `afterEach` | `setGlobalAfterEach` | `getGlobalAfterEach` | JS 函数 | > ⚠️ **`enhance`(应用增强 JS)** 目前没有对应的工具方法,暂无法通过 AI 工具配置。 --- ## 三、渲染引擎初始化顺序 `initRuntimeGlobals()` 严格按以下顺序执行,**顺序不可更改**,配置时需注意依赖关系: ``` 1. CSS(全局样式) ── adoptedStyleSheets 注入 │ 2. Store(Pinia 状态) ── 创建 Pinia 实例,注册 $store │ 3. Axios + 拦截器 ── 先设基础配置,再设请求拦截器,最后设响应拦截器 │ 4. Access(权限控制) ── 创建 Access 实例,连接 router/request │ 5. 路由守卫 ── 先 beforeEach,后 afterEach │ 6. Enhance(应用增强) ── 最后执行,可访问全部已初始化的 libs 和 app ``` **含义:** - `store` 中的状态可在 `access`、路由守卫、拦截器中通过 `app.config.globalProperties.$store` 访问 - `access` 实例挂载后,路由守卫可通过 `app.config.globalProperties.$access` 访问 - `enhance` 最后执行,可访问所有已初始化的资源(store、access、router 等) --- ## 四、各配置项详细说明 ### 4.1 应用全局 CSS — `css` **对应工具:** `setGlobalCss` / `getGlobalCss` 直接传入 CSS 代码字符串,会在应用启动时注入为全局样式表。 **示例:** ```json { "action": "setGlobalCss", "parameters": [ "body { margin: 0; padding: 0; font-family: 'Helvetica Neue', sans-serif; }\n.page-container { min-height: 100vh; }" ] } ``` **设计器默认值:** 空字符串(不注入额外 CSS) --- ### 4.2 应用状态 Pinia — `store` **对应工具:** `setGlobalStore` / `getGlobalStore` 定义应用的全局 Pinia Store,函数必须返回一个标准 Pinia Store 配置对象。 **函数签名:** `(app) => ({ state, getters, actions })` | 参数 | 说明 | | ----- | ---------------------------------------------------------------- | | `app` | Vue 应用实例,可用于获取全局属性如 `app.config.globalProperties` | **设计器默认模板:** ```javascript (app) => { return { state: () => { return { // 定义状态 }; }, getters: { // 计算属性 }, actions: { // 方法 } }; }; ``` **完整示例:** ```json { "action": "setGlobalStore", "parameters": [ "(app) => {\n return {\n state: () => ({\n user: null,\n token: '',\n permissions: []\n }),\n getters: {\n isLogined: (state) => !!state.token,\n userName: (state) => state.user?.name || '游客'\n },\n actions: {\n login(data) {\n this.token = data.token\n this.user = data.user\n this.permissions = data.permissions || []\n },\n logout() {\n this.token = ''\n this.user = null\n this.permissions = []\n },\n hasPermission(code) {\n return this.permissions.includes(code)\n }\n }\n }\n}" ] } ``` **运行时访问:** 组件中通过 `__store.xxx` 访问: ```javascript const user = __store.user; __store.login({ token: 'xxx', user: { name: '张三' } }); ``` --- ### 4.3 权限控制 Access — `access` **对应工具:** `setGlobalAccess` / `getGlobalAccess` 配置应用的权限控制插件,函数返回 `AccessOptions` 配置对象。 **函数签名:** `(app) => AccessOptions` **设计器默认模板:** ```javascript (app) => { return { // session: false, // authKey: 'Authorization', // storageKey: 'ACCESS_STORAGE', // auth: '/#/login', // whiteList: (to) => true, // redirectParam: 'r', // unauthorizedCode: 401, // unauthorizedMessage: '登录已经失效,请重新登录!', // noPermissionMessage: '无权限访问该页面', // statusKey: 'code' }; }; ``` **`AccessOptions` 配置项说明:** | 配置项 | 类型 | 默认值 | 说明 | | --------------------- | -------- | -------------- | ------------------------------------------------------------------ | | `session` | boolean | false | 是否开启 session 存储(关闭浏览器即失效),false 使用 localStorage | | `authKey` | string | Authorization | 请求头和 cookie 中 token 的键名 | | `storageKey` | string | ACCESS_STORAGE | 本地缓存的键名 | | `auth` | string | /#/login | 登录页面的 hash 路径 | | `whiteList` | function | (to) => false | 路由白名单,返回 true 跳过权限校验,接收 to 路由对象 | | `redirectParam` | string | r | 登录后重定向的参数名 | | `unauthorizedCode` | number | 401 | 未登录时后端返回的状态码 | | `unauthorizedMessage` | string | 登录已失效... | 未登录时的提示消息 | | `noPermissionMessage` | string | 无权限... | 无权限时的提示消息 | | `statusKey` | string | code | 响应数据中状态码的字段名 | **运行时访问:** 组件中通过 `__access` 访问: ```javascript // 检查是否已登录 __access.isLogined(); // 检查是否拥有指定权限 __access.can('user:edit'); // 检查是否至少有一个权限 __access.some(['user:edit', 'user:view']); // 获取当前 token __access.getToken(); // 获取登录用户数据 __access.getData(); // 登录 __access.login({ token: 'xxx', user: { name: '张三' }, permissions: ['user:view'] }); // 登出 __access.logout(); ``` --- ### 4.4 应用增强 JS — `enhance` ⚠️ **尚无对应工具方法。** 该配置允许在应用初始化的最后阶段注入自定义增强逻辑,函数接收 `app`(Vue 应用实例)和 `libs`(所有注册的第三方库集合)。 **设计器默认模板:** ```javascript (app) => { // 在此添加增强代码 }; ``` **执行时机:** 在所有其他全局配置(CSS、Store、Axios、Access、路由守卫)初始化完成后执行。 --- ### 4.5 请求配置 IRequestOptions — `axios` **对应工具:** `setGlobalAxios` / `getGlobalAxios` UI 标签中也称 `getGlobalAxios`,设置时使用 `setGlobalAxios`。 配置 Axios 请求工具的基础选项(baseURL、超时、响应校验等)。 **函数签名:** `(app) => IRequestOptions` **设计器默认模板:** ```javascript (app) => { return { // baseURL: '/', // timeout: 60000, // settings: { // type: 'form', // validSuccess: false, // originResponse: true, // loading: true, // failMessage: true, // validate: (res) => { // return res.data?.code === 0 || !!res.data?.success; // } // } }; }; ``` **`IRequestOptions` 常见配置项:** | 配置项 | 类型 | 说明 | | ------------------------- | -------- | ---------------------------------------------------------------- | | `baseURL` | string | 请求的基础 URL 前缀 | | `timeout` | number | 请求超时时间(毫秒) | | `settings.type` | string | 请求数据类型:`form`(表单)、`json`(JSON)、`data`(FormData) | | `settings.validSuccess` | boolean | 是否校验响应是否成功 | | `settings.originResponse` | boolean | 是否返回原始 Axios 响应对象 | | `settings.loading` | boolean | 请求时是否显示全局 loading | | `settings.failMessage` | boolean | 请求失败时是否显示错误提示 | | `settings.validate` | function | 自定义响应成功校验函数,接收 `res` 返回 boolean | **完整示例:** ```json { "action": "setGlobalAxios", "parameters": [ "(app) => {\n return {\n baseURL: 'https://api.example.com',\n timeout: 30000,\n settings: {\n type: 'json',\n validSuccess: true,\n originResponse: false,\n loading: true,\n failMessage: true,\n validate: (res) => {\n return res.data?.code === 0\n }\n }\n }\n}" ] } ``` --- ### 4.6 请求拦截器 — `request` **对应工具:** `setGlobalRequestInterceptor` / `getGlobalRequestInterceptor` 在每次请求发送前执行,常用于注入 token、设置请求头等。 **函数签名:** `(config, app) => config` | 参数 | 说明 | | -------- | ------------------ | | `config` | Axios 请求配置对象 | | `app` | Vue 应用实例 | **必须返回**请求配置对象 `config`。 **设计器默认模板:** ```javascript (config, app) => { return config; }; ``` **典型示例(自动注入 token):** ```javascript (config, app) => { const access = app.config.globalProperties.$access; if (access?.getToken()) { config.headers['Authorization'] = `Bearer ${access.getToken()}`; } return config; }; ``` --- ### 4.7 响应拦截器 — `response` **对应工具:** `setGlobalResponseInterceptor` / `getGlobalResponseInterceptor` 在每次请求收到响应后执行,常用于统一处理响应数据、错误处理等。 **函数签名:** `(res, app) => res` | 参数 | 说明 | | ----- | ------------------ | | `res` | Axios 原始响应对象 | | `app` | Vue 应用实例 | **必须返回**响应对象 `res`。 **设计器默认模板:** ```javascript (res, app) => { return res; }; ``` **典型示例(统一错误处理):** ```javascript (res, app) => { if (res.data?.code === 401) { const access = app.config.globalProperties.$access; if (access) { access.logout(); } } return res; }; ``` --- ### 4.8 前置路由守卫 beforeEach — `beforeEach` **对应工具:** `setGlobalBeforeEach` / `getGlobalBeforeEach` 在路由跳转前执行,常用于权限校验、登录拦截等。 **函数签名:** `(to, from, next, app) => void` | 参数 | 说明 | | ------ | ----------------------------------------------- | | `to` | 即将进入的目标路由对象 | | `from` | 当前正要离开的路由对象 | | `next` | 执行跳转的函数(与 vue-router beforeEach 一致) | | `app` | Vue 应用实例 | **设计器默认模板:** ```javascript (to, from, next, app) => { next(); }; ``` **典型示例(登录校验):** ```javascript (to, from, next, app) => { const access = app.config.globalProperties.$access; const isPublic = access?.options?.whiteList?.(to); if (!isPublic && !access?.isLogined()) { next('/login'); } else { next(); } }; ``` --- ### 4.9 后置路由守卫 afterEach — `afterEach` **对应工具:** `setGlobalAfterEach` / `getGlobalAfterEach` 在路由跳转完成后执行,常用于页面标题更新、埋点上报等。 **函数签名:** `(to, from, failure, app) => void` | 参数 | 说明 | | --------- | ---------------------------------- | | `to` | 进入的目标路由对象 | | `from` | 离开的路由对象 | | `failure` | 导航失败信息,成功时为 `undefined` | | `app` | Vue 应用实例 | **设计器默认模板:** ```javascript (to, from, failure, app) => {}; ``` **典型示例(埋点上报):** ```javascript (to, from, failure, app) => { if (!failure) { // 页面浏览埋点 console.log('Page view:', to.path); } }; ``` --- ## 五、配置建议与注意事项 ### 5.1 典型配置流程 当 AI 需要配置应用级别功能时,建议按以下顺序调用工具: ``` 1. setGlobalCss → 设置全局样式 2. setGlobalStore → 定义全局 Pinia 状态 3. setGlobalAxios → 配置请求基础选项 4. setGlobalRequestInterceptor → 设置请求拦截(如注入 token) 5. setGlobalResponseInterceptor → 设置响应拦截(如统一错误处理) 6. setGlobalAccess → 配置权限控制插件 7. setGlobalBeforeEach → 设置前置路由守卫(登录校验等) 8. setGlobalAfterEach → 设置后置路由守卫(埋点等) ``` 这个顺序与渲染引擎内部初始化顺序一致,可以保证依赖关系正确。 ### 5.2 重要约定 1. **值类型:** `css` 为普通字符串,其余 7 项(store、access、enhance、axios、request、response、beforeEach、afterEach)均为 **JS 函数代码字符串**,不是 JSON 对象 2. **工具参数格式:** 所有 set 类工具的配置内容均作为**单个字符串参数**传入(即 `parameters` 数组的第一个元素),不要在字符串外额外包裹对象 3. **`enhance` 暂无工具:** 如需初始化后执行自定义逻辑,目前只能通过设计器面板手动编辑,无对应 AI 工具方法 4. **运行时不直接调用:** 工具方法只负责**存储配置**到项目中,配置的实际生效发生在应用启动时,不影响当前打开的预览窗口(可调用 `refresh` 刷新查看效果) 5. **设计模式不生效:** 设计器内编辑页面时,全局配置不会立即在页面渲染中生效(`initGlobals` 仅在非设计模式下执行) 6. **函数内可访问全局属性:** - `app.config.globalProperties.$store` — Pinia store 实例 - `app.config.globalProperties.$access` — 权限控制实例 - `app.config.globalProperties.$router` — 路由实例 - `app.config.globalProperties.$provider` — Provider 实例 ### 5.3 查询已有配置 在修改配置前,建议先调用对应的 `get` 工具查看已有内容,避免覆盖: ``` getGlobalCss → 查看当前全局 CSS getGlobalStore → 查看当前 Pinia store 代码 getGlobalAccess → 查看当前权限配置 getGlobalAxios → 查看当前请求基础配置 getGlobalRequestInterceptor → 查看当前请求拦截器 getGlobalResponseInterceptor → 查看当前响应拦截器 getGlobalBeforeEach → 查看当前前置路由守卫 getGlobalAfterEach → 查看当前后置路由守卫 ``` # VTJ 设计器工具方法说明 > 本文档描述 AI 可调用的所有工具方法(Tools),每个工具均通过 `action` + `parameters` 的 JSON 格式调用。 --- ## 调用格式 ```json { "action": "工具名称", "parameters": [参数1, 参数2, ...] } ``` --- ## 一、技能与辅助 ### `getSkills` — 获取技能文档 获取指定 ID 的技能文档内容,用于查阅特定功能的详细用法说明。 **参数:** - `...ids: string[]` — 一个或多个技能 ID **示例:** ```json { "action": "getSkills", "parameters": ["pinia", "axios"] } ``` --- ## 二、页面管理 ### `getMenus` — 获取页面菜单树 获取当前项目的页面菜单树结构(含层级关系)。 **参数:** 无 **返回:** 树形结构数组,每项包含 `id`、`name`、`title`、`layout`、`dir`、`icon`、`children` --- ### `getPages` — 获取所有页面 获取当前项目的全部页面列表(扁平结构)。 **参数:** 无 **返回:** 数组,每项包含 `id`、`name`、`title`、`layout`、`dir`、`icon` --- ### `createPage` — 创建页面 在当前项目中新建页面。有层级关系时,需先创建父级(目录或布局页面),再创建子页面。 **参数:** | 参数 | 类型 | 必填 | 说明 | | ------------- | ------- | ---- | ----------------------------------------------------------------------------- | | `page` | object | ✅ | 页面对象 | | `page.name` | string | ✅ | 页面名称,PascalCase,如 `UserList` | | `page.title` | string | ✅ | 页面标题,如 `用户列表` | | `page.icon` | string | ❌ | 图标名称,可选 ElementPlus 图标或 `@vtj/icons` 图标 | | `page.dir` | boolean | ❌ | 是否目录,目录可包含子目录或子页面 | | `page.layout` | boolean | ❌ | 是否布局页面,布局页面的子级为子页面(需配合 RouterView 使用),UniApp 不支持 | | `parentId` | string | ❌ | 父页面 ID,不传则创建在根目录 | **示例:** ```json { "action": "createPage", "parameters": [ { "name": "Dashboard", "title": "仪表盘", "icon": "DataAnalysis" }, "2gqoc7vp" ] } ``` **注意:** - UniApp 平台不支持 `dir` 和 `layout` 类型,会自动忽略 - 创建成功后会自动打开(激活)该页面(目录类型除外) --- ### `updatePage` — 更新页面信息 修改已有页面的元信息(名称、标题、图标等)。 **参数:** | 参数 | 类型 | 必填 | 说明 | | ------------ | ------ | ---- | -------- | | `page.id` | string | ✅ | 页面 ID | | `page.name` | string | ✅ | 页面名称 | | `page.title` | string | ✅ | 页面标题 | | `page.icon` | string | ❌ | 图标名称 | --- ### `movePage` — 移动页面层级 将页面移动到指定父级下(改变层级关系)。 **参数:** | 参数 | 类型 | 必填 | 说明 | | ---------- | ------ | ---- | ------------------------------------- | | `id` | string | ✅ | 要移动的页面 ID | | `parentId` | string | ❌ | 目标父页面 ID,传 `null` 则移到根目录 | --- ### `removePage` — 删除页面 删除指定页面或目录。 **注意:** 删除目录或布局类型页面前,需先删除其所有子页面。 **参数:** - `id: string` — 页面文件 ID --- ### `setHomepage` — 设置应用主页 将指定页面设为应用首页。 **参数:** - `id: string` — 页面 ID --- ## 三、区块组件管理 ### `getBlocks` — 获取所有区块 获取当前项目的全部区块组件列表。 **参数:** 无 **返回:** 数组,每项包含 `id`、`name`、`title`、`category` --- ### `createBlock` — 创建区块 在当前项目中新建区块组件,创建后自动打开(激活)。 **参数:** | 参数 | 类型 | 必填 | 说明 | | ---------------- | ------ | ---- | ----------------------------------- | | `block.name` | string | ✅ | 区块名称,PascalCase,如 `UserCard` | | `block.title` | string | ✅ | 区块标题 | | `block.category` | string | ❌ | 区块分类/分组名称 | --- ### `updateBlock` — 更新区块信息 修改已有区块的元信息。 **参数:** | 参数 | 类型 | 必填 | 说明 | | ---------------- | ------ | ---- | -------- | | `block.id` | string | ✅ | 区块 ID | | `block.name` | string | ❌ | 区块名称 | | `block.title` | string | ❌ | 区块标题 | | `block.category` | string | ❌ | 分类 | --- ### `removeBlock` — 删除区块 删除指定区块文件。 **参数:** - `id: string` — 区块文件 ID --- ## 四、文件操作 ### `active` — 打开文件 在设计器中打开(激活)指定的页面或区块。 **参数:** - `id: string` — 文件(页面或区块)ID --- ### `getCurrentFile` — 获取当前文件信息 获取当前设计器中打开的文件元信息(名称、标题、ID)。 **参数:** 无 **返回:** `{ id, name, title }`,无打开文件时抛出错误 --- ### `getCurrentFileContent` — 获取当前文件源码 获取当前打开文件的 Vue 组件源码内容。 **参数:** 无 **返回:** Vue 组件源码字符串 --- ### `refresh` — 刷新运行时 刷新当前页面/区块的运行时渲染,并检测是否存在运行时错误。 **参数:** 无 **返回:** - `true` — 无运行时错误 - 错误信息字符串 — 检测到运行时报错,需修复代码 **用途:** 代码生成完毕后调用,确认是否有运行时错误。 --- ### `getNodeSelected` — 获取当前选中节点路径 获取当前页面中选中元素的节点路径,路径最后一项为选中元素名称。 **参数:** 无 **返回:** 路径字符串,如 `ElTable[0]>ElTableColumn[2]`,无选中时返回 `null` --- ## 五、接口 API 管理 ### `getApis` — 获取接口列表 获取当前项目中已配置的所有接口。 **参数:** 无 **返回:** `ApiSchema[]` 数组 --- ### `setApi` — 新增或更新接口 新增或更新一个接口配置。若接口名称已存在则更新,不存在则新增。 **参数:** | 参数 | 类型 | 必填 | 说明 | | ------------ | ------ | ---- | -------------------------------------------------------------------------------- | | `api.name` | string | ✅ | 接口名称,camelCase,如 `getUserList` | | `api.label` | string | ❌ | 接口描述说明 | | `api.url` | string | ✅ | 请求 URL,支持路径参数如 `/api/user/:id` | | `api.method` | string | ❌ | 请求方法:`get` \| `post` \| `put` \| `delete` \| `patch` \| `jsonp`,默认 `get` | **示例:** ```json { "action": "setApi", "parameters": [ { "name": "getUserList", "label": "获取用户列表", "url": "/api/users", "method": "get" } ] } ``` --- ### `removeApi` — 删除接口 删除指定接口。 **参数:** - `name: string` — 接口名称或 ID --- ### `removeApis` — 批量删除接口 批量删除多个接口。 **参数:** - `apis: string[]` — 接口名称或 ID 数组 --- ## 六、全局配置 ### `getGlobalCss` / `setGlobalCss` — 全局 CSS 获取或设置应用的全局 CSS 样式代码。 **`setGlobalCss` 参数:** - `css: string` — CSS 代码字符串 --- ### `getGlobalStore` / `setGlobalStore` — 全局 Pinia Store 获取或设置应用的全局 Pinia 状态。 **`setGlobalStore` 参数:** - `store: string` — JS 函数代码字符串 函数接收 `app`(Vue 应用实例),返回标准 Pinia Store 配置对象: ```javascript (app) => { return { state: () => ({ user: null, token: '' }), getters: { isLogined: (state) => !!state.token }, actions: { setUser(user) { this.user = user; }, logout() { this.user = null; this.token = ''; } } }; }; ``` 组件中通过 `__store.xxx` 访问(如 `__store.state.user`、`__store.setUser(data)`)。 --- ### `getGlobalAccess` / `setGlobalAccess` — 权限控制配置 获取或设置权限控制插件配置。 **`setGlobalAccess` 参数:** - `access: string` — JS 函数代码字符串 函数接收 `app`,返回 `AccessOptions` 配置对象: ```javascript (app) => { return { session: false, // 是否开启 session(关闭浏览器失效) authKey: 'Authorization', // 请求头和 cookie 中 token 的键名 storageKey: 'ACCESS_STORAGE', // 本地缓存键名 auth: '/#/login', // 登录页路径 whiteList: (to) => false, // 路由白名单,返回 true 则跳过权限校验 redirectParam: 'r', // 重定向参数名 unauthorizedCode: 401, // 未登录响应状态码 unauthorizedMessage: '登录已经失效,请重新登录!', noPermissionMessage: '无权限访问该页面', statusKey: 'code' // 响应数据中状态码的 key }; }; ``` 组件中通过 `__access` 访问(如 `__access.isLogined()`、`__access.can('user:edit')`)。 --- ### `getGlobalAxios` / `setGlobalAxios` — Axios 基础配置 获取或设置全局 Axios 请求工具的基础配置(baseURL、超时、响应校验等)。 **`setGlobalAxios` 参数:** - `axios: string` — JS 函数代码字符串 函数接收 `app`,返回 `IRequestOptions` 配置对象: ```javascript (app) => { return { baseURL: '/', timeout: 60000, settings: { type: 'json', // 请求数据类型:form | json | data validSuccess: true, // 是否校验响应成功 originResponse: false, // 是否返回原始 Axios 响应 loading: true, // 是否显示 loading failMessage: true, // 是否显示错误提示 validate: (res) => { return res.data?.code === 0 || !!res.data?.success; } } }; }; ``` --- ### `getGlobalRequestInterceptor` / `setGlobalRequestInterceptor` — 请求拦截器 获取或设置全局 Axios 请求拦截器,用于在发请求前修改请求配置(如注入 token)。 **`setGlobalRequestInterceptor` 参数:** - `request: string` — JS 函数代码字符串 函数接收两个参数: - `config` — 请求配置对象 - `app` — Vue 应用实例 函数**必须返回** `config`: ```javascript (config, app) => { const token = app.config.globalProperties.$access?.getToken(); if (token) { config.headers['Authorization'] = `Bearer ${token}`; } return config; }; ``` --- ### `getGlobalResponseInterceptor` / `setGlobalResponseInterceptor` — 响应拦截器 获取或设置全局 Axios 响应拦截器,用于统一处理响应数据。 **`setGlobalResponseInterceptor` 参数:** - `response: string` — JS 函数代码字符串 函数接收两个参数: - `res` — Axios 原始响应对象 - `app` — Vue 应用实例 函数**必须返回** `res`: ```javascript (res, app) => { // 可在此处做统一的数据转换 return res; }; ``` --- ### `getGlobalBeforeEach` / `setGlobalBeforeEach` — 前置路由守卫 获取或设置全局前置路由守卫(`router.beforeEach`)。 **`setGlobalBeforeEach` 参数:** - `value: string` — JS 函数代码字符串 函数接收 4 个参数: - `to` — 即将进入的目标路由 - `from` — 当前正要离开的路由 - `next` — 执行跳转的函数 - `app` — Vue 应用实例 ```javascript (to, from, next, app) => { // 示例:登录校验 const access = app.config.globalProperties.$access; if (!access.isLogined() && to.path !== '/login') { next('/login'); } else { next(); } }; ``` --- ### `getGlobalAfterEach` / `setGlobalAfterEach` — 后置路由守卫 获取或设置全局后置路由守卫(`router.afterEach`)。 **`setGlobalAfterEach` 参数:** - `value: string` — JS 函数代码字符串 函数接收 4 个参数: - `to` — 即将进入的目标路由 - `from` — 当前正要离开的路由 - `failure` — 导航失败信息(无失败则为 `undefined`) - `app` — Vue 应用实例 ```javascript (to, from, failure, app) => { if (!failure) { // 路由跳转成功后的操作,如记录埋点 console.log('navigated to', to.path); } }; ``` --- ## 七、环境变量管理 ### `getEnv` — 获取环境变量列表 获取项目中配置的所有环境变量。 **参数:** 无 **返回:** `EnvConfig[]` 数组,每项包含 `name`、`development`、`production` **组件中访问环境变量:** `__provider.env.变量名` --- ### `createEnv` — 新增环境变量 新增一个环境变量,区分开发/生产两套值。 **参数:** | 参数 | 类型 | 必填 | 说明 | | -------------------- | ------ | ---- | --------------------- | | `config.name` | string | ✅ | 变量名,如 `BASE_URL` | | `config.development` | string | ✅ | 开发环境的值 | | `config.production` | string | ✅ | 生产环境的值 | **示例:** ```json { "action": "createEnv", "parameters": [ { "name": "BASE_URL", "development": "http://dev.api.com", "production": "https://api.com" } ] } ``` --- ### `removeEnv` — 删除环境变量 删除指定名称的环境变量。 **参数:** - `name: string` — 环境变量名称 --- ## 八、国际化(i18n)管理 ### `getI18nMessage` — 获取词条列表 获取 vue-i18n 的所有中英文对照词条。 **参数:** 无 **返回:** `I18nMessage[]` 数组,每项包含 `key`、`zh-CN`、`en` **组件中使用词条:** `__i18n.t('key')` 或模板中 `{{ $t('key') }}` --- ### `createI18nMessage` — 新增词条 新增一条中英文对照词条。 **参数:** | 参数 | 类型 | 必填 | 说明 | | --------------- | ------ | ---- | ----------------------------- | | `message.key` | string | ✅ | 词条标识,如 `common.confirm` | | `message.zh-CN` | string | ✅ | 中文内容 | | `message.en` | string | ✅ | 英文内容 | --- ### `removeI18nMessage` — 删除词条 删除指定 key 的词条。 **参数:** - `key: string` — 词条标识 key --- ## 九、UniApp 专属配置 > 以下工具仅适用于 UniApp 平台项目。 ### `getUniConfig` / `setUniConfig` — UniApp 全局配置 获取或设置 UniApp 全局配置,包括 pages.json、manifest.json、全局 CSS、App.vue 生命周期等。 **参数:** | 参数 | 类型 | 必填 | 说明 | | ------- | ------ | --------- | -------------------------- | | `key` | string | ✅ | 配置类型名称(见下方枚举) | | `value` | string | ✅(set) | 配置内容(见下方规则) | **`key` 枚举值:** | key | 说明 | | ---------------------- | ----------------------- | | `manifestJson` | manifest.json 应用配置 | | `pagesJson` | pages.json 页面路由配置 | | `css` | App.vue 中的全局 CSS | | `onLaunch` | App 启动时 | | `onShow` | App 显示时 | | `onHide` | App 隐藏时 | | `onError` | App 报错时 | | `onPageNotFound` | 页面不存在时 | | `onUnhandledRejection` | 未处理 Promise 拒绝时 | | `onThemeChange` | 主题变化时 | | `onUniNViewMessage` | nvue 发送消息时 | | `onExit` | App 退出时 | **`value` 格式规则:** 1. `key` 为 `manifestJson` 或 `pagesJson` 时,`value` 为 **JSON 字符串** 2. `key` 为 `css` 时,`value` 为 **CSS 代码字符串** 3. `key` 为生命周期名称时,`value` 为 **JS 函数代码块**: ```javascript () => { // 生命周期逻辑 }; ``` 4. `value` 为 `null` 时,表示清除该配置 **示例(设置 pages.json):** ```json { "action": "setUniConfig", "parameters": [ "pagesJson", "{\"pages\":[{\"path\":\"pages/index/index\",\"style\":{\"navigationBarTitleText\":\"首页\"}}],\"globalStyle\":{\"navigationBarTextStyle\":\"black\",\"navigationBarTitleText\":\"uni-app\",\"navigationBarBackgroundColor\":\"#F8F8F8\",\"backgroundColor\":\"#F8F8F8\"}}" ] } ``` **示例(设置 onLaunch 生命周期):** ```json { "action": "setUniConfig", "parameters": ["onLaunch", "() => { console.log('App launched') }"] } ``` --- ## 十、工具调用建议 ### 典型工作流程 1. **了解项目结构:** 先调用 `getMenus` 或 `getPages` 了解页面结构 2. **创建页面:** 用 `createPage` 创建,层级页面先建父级 3. **生成内容:** 结合 Vue 代码规范生成页面源码 4. **验证结果:** 调用 `refresh` 检测是否有运行时错误 5. **配置接口:** 用 `setApi` 注册后端接口 6. **全局配置:** 按需配置 store、access、axios 等全局选项 ### 注意事项 - 调用 `createPage`/`createBlock` 后,目标文件会自动激活打开 - `refresh` 会等待渲染完成(约 1 秒),建议生成完整代码后再调用 - UniApp 平台不支持 `dir`(目录)和 `layout`(布局)类型页面 - 函数类型配置(store、access、axios、拦截器、路由守卫)均传入 **JS 函数代码字符串**,不是 JSON - `setGlobalStore` 的函数必须返回 Pinia store 配置对象,可用 `getSkills` 查询 pinia 用法 # @vtj/ui 组件库 — AI 使用指南 > 本文档帮助 AI 理解 `@vtj/ui` 组件库的构成、导入方式和在 Vue 组件中的使用规范。 --- ## 一、组件库概览 `@vtj/ui` 是 VTJ 平台的企业级 UI 组件库,基于 Vue 3 + TypeScript 构建,底层依赖 Element Plus 和 VXE Table。提供以下核心模块: | 模块 | 功能说明 | 导入方式 | | ------------ | -------------------------------------------- | ----------------------------------------------------- | | **组件** | 30+ 业务组件(Grid、Form、Dialog、Field 等) | `import { XGrid, XForm } from '@vtj/ui'` | | **Hooks** | 可复用的 Composition API 钩子 | `import { useIcon, useLoader } from '@vtj/ui'` | | **指令** | 拖拽、缩放等自定义指令 | `import { vDraggable, vResizable } from '@vtj/ui'` | | **Adapter** | 适配器系统(上传、字段编辑器、VXE 配置等) | `import { useAdapter, AdapterPlugin } from '@vtj/ui'` | | **工具方法** | 通用工具函数 | `import { parseSize } from '@vtj/ui/utils'` | | **常量** | 全局常量定义 | `import { ... } from '@vtj/ui/constants'` | ### 1.1 技术栈依赖 ```json { "dependencies": { "@vtj/icons": "latest", "@vtj/utils": "latest", "@vueuse/core": "~14.1.0", "element-plus": "~2.13.0", "sortablejs": "~1.15.6", "vxe-table": "~4.6.17", "vxe-table-plugin-menus": "~4.0.3" } } ``` ### 1.2 组件命名规范 - 所有组件均以 `X` 前缀命名,如 `XGrid`、`XForm`、`XDialog` - 组件类型定义以 `Props`、`Emits`、`Instance` 结尾,如 `GridProps`、`GridEmits`、`GridInstance` --- ## 二、安装与注册 ### 2.1 安装依赖 ```json { "dependencies": { "@vtj/ui": "latest" } } ``` ### 2.2 全局注册 ```typescript import { createApp } from 'vue'; import { AdapterPlugin } from '@vtj/ui'; import '@vtj/ui/dist/style.css'; const app = createApp(App); // 注册适配器插件(会自动注册 Element Plus 的消息组件) app.use(AdapterPlugin, { uploader: async (file: File) => { // 自定义上传逻辑 return { url: '...', name: file.name }; }, fieldEditors: { // 自定义字段编辑器 } }); ``` --- ## 三、核心组件使用 ### 3.1 XGrid 数据表格 `XGrid` 是基于 VXE Table 封装的高级数据表格组件,支持数据加载、排序、过滤、行/列拖拽排序、单元格编辑等功能。 #### 基本用法 ```vue ``` #### 列渲染器 ```vue ``` #### 高级特性 ```vue ``` --- ### 3.2 XForm 表单 `XForm` 是基于 Element Plus Form 封装的表单组件,支持 inline 模式、自动提交/重置、sticky 底部按钮等特性。 #### 基本用法 ```vue ``` #### Inline 模式 ```vue ``` --- ### 3.3 XField 字段组件 `XField` 是统一的表单字段组件,支持多种编辑器类型、动态选项加载、级联刷新、可见性控制等。 #### 内置编辑器 | 编辑器类型 | 说明 | 适用场景 | | ---------- | ---------- | ------------ | | `text` | 文本输入框 | 单行文本 | | `textarea` | 多行文本框 | 多行文本 | | `number` | 数字输入框 | 数值输入 | | `select` | 下拉选择 | 单选/多选 | | `radio` | 单选框 | 少量选项单选 | | `checkbox` | 复选框 | 少量选项多选 | | `date` | 日期选择 | 日期/时间 | | `switch` | 开关 | 布尔值 | | `password` | 密码输入框 | 密码输入 | #### 基本用法 ```vue ``` --- ### 3.4 XDialog 对话框 `XDialog` 是增强型对话框组件,支持拖拽、缩放、最大化/最小化、多实例管理等。 #### 基本用法 ```vue ``` #### 使用 Dialog Hooks ```vue ``` --- ### 3.5 XActionBar 操作栏 `XActionBar` 用于统一的操作按钮区域,支持按钮、文本、图标模式,下拉菜单等。 ```vue ``` --- ### 3.6 XQueryForm 查询表单 `XQueryForm` 是专门用于数据查询的表单组件,支持折叠展开、自动布局等。 ```vue ``` --- ### 3.7 XContainer 布局容器 `XContainer` 是基于 Flex 布局的容器组件,提供丰富的布局控制属性。 ```vue ``` --- ### 3.8 其他常用组件 #### XAction 操作按钮 ```vue ``` #### XIcon 图标组件 ```vue ``` #### XTabs 标签页 ```vue ``` #### XAttachment 附件上传 ```vue ``` #### XHeader 页头 ```vue ``` #### XMask 遮罩布局 ```vue ``` --- ## 四、Hooks 工具 ### 4.1 useIcon 图标钩子 ```typescript import { useIcon } from '@vtj/ui'; const { IconComponent } = useIcon('Add'); ``` ### 4.2 useLoader 加载器钩子 ```typescript import { useLoader } from '@vtj/ui'; const { data, loading, error, reload } = useLoader(async () => { return await request({ url: '/api/data' }); }); ``` ### 4.3 useDisabled 禁用状态钩子 ```typescript import { useDisabled } from '@vtj/ui'; const disabled = useDisabled(props.disabled, actionItem); ``` ### 4.4 useDefer 延迟渲染钩子 ```typescript import { useDefer } from '@vtj/ui'; const defer = useDefer(100); // 延迟 100ms ``` --- ## 五、Adapter 适配器系统 ### 5.1 使用适配器 ```vue ``` ### 5.2 配置适配器 ```typescript import { AdapterPlugin } from '@vtj/ui'; app.use(AdapterPlugin, { // 自定义上传 uploader: async (file) => { const formData = new FormData(); formData.append('file', file); const res = await request({ url: '/api/upload', method: 'post', data: formData }); return { url: res.url, name: file.name }; }, // 自定义字段编辑器 fieldEditors: { customEditor: { component: CustomEditorComponent, defaultValue: '' } }, // VXE Table 配置 vxeConfig: { // ... }, // Grid 自定义配置持久化 getCustom: async (id) => { return await request({ url: `/api/grid-config/${id}` }); }, saveCustom: async (info) => { await request({ url: '/api/grid-config', method: 'post', data: info }); } }); ``` --- ## 六、VTJ 代码规范 ### 6.1 Composition API 强制规范 所有组件必须使用 ` ``` ### 6.2 组件导入规范 从 `@vtj/ui` 按需导入组件,不要全局导入: ```vue ``` ### 6.3 变量命名规范 - 使用 `ref` 或 `reactive` 声明响应式变量 - 变量名使用 camelCase - 组件 ref 使用 `xxRef` 命名 ```vue ``` ### 6.4 类型定义规范 使用 TypeScript 类型定义: ```vue ``` ### 6.5 事件处理规范 事件处理函数使用 `on` 前缀: ```vue ``` --- ## 七、完整示例 ### 7.1 标准 CRUD 页面 ```vue ``` --- ## 八、常见问题 ### 8.1 如何自定义 Grid 列渲染? 使用 `slots` 配置: ```vue ``` ### 8.2 如何在 Field 中使用自定义编辑器? 通过 Adapter 注册: ```typescript app.use(AdapterPlugin, { fieldEditors: { customEditor: { component: CustomEditor, defaultValue: '' } } }); ``` ```vue ``` ### 8.3 Dialog 如何获取内部组件实例? 通过 `componentInstance` 属性: ```vue ``` --- ## 九、总结 `@vtj/ui` 提供了一套完整的企业级业务组件库,核心特点: 1. **组件前缀统一**:所有组件以 `X` 开头,避免命名冲突 2. **基于成熟生态**:底层使用 Element Plus 和 VXE Table 3. **TypeScript 友好**:完整的类型定义支持 4. **适配器模式**:灵活的扩展机制 5. **Composition API**:全面支持 Vue 3 组合式 API 在编写代码时,请遵循 VTJ 代码规范,使用 Composition API 模式,按需导入组件,合理使用 Hooks 和 Adapter 系统。 # @vtj/charts 图表库 — AI 使用指南 > 本文档帮助 AI 理解 `@vtj/charts` 图表库的构成、组件属性和在 Vue 组件中的使用规范。 --- ## 一、库概述 `@vtj/charts` 是基于 ECharts 5.x 封装的 Vue 3 图表组件库,提供开箱即用的图表组件和组合式 API。 | 内容 | 说明 | | ---------- | --------------------------------------------- | | 基础依赖 | `echarts` `~5.6.0` | | 核心组件 | `XChart`(通用图表)、`XMapChart`(地图图表) | | 组合式 API | `useChart`、`useMapChart` | | 自动特性 | 响应式 option、自动 resize、事件代理 | --- ## 二、安装与注册 ### 2.1 安装依赖 ```json { "dependencies": { "@vtj/charts": "latest" } } ``` ### 2.2 全局注册(推荐) ```typescript import { createApp } from 'vue'; import Charts from '@vtj/charts'; const app = createApp(App); app.use(Charts); // 注册 XChart、XMapChart 为全局组件 ``` 全局注册后,模板中可直接使用 `` 和 `` 标签。 ### 2.3 按需导入 ```vue ``` --- ## 三、XChart 通用图表组件 ### 3.1 Props | 属性 | 类型 | 默认值 | 说明 | | -------- | --------------- | ----------- | -------------------------- | | `width` | `string` | `'100%'` | 图表容器宽度 | | `height` | `string` | `'400px'` | 图表容器高度 | | `option` | `EChartsOption` | `undefined` | ECharts 配置项,响应式更新 | ### 3.2 Exposed 属性 通过模板 ref 可访问以下属性: | 名称 | 类型 | 说明 | | ----------- | ---------------------------- | --------------------- | | `elRef` | `HTMLElement` | 图表容器 DOM 引用 | | `option` | `EChartsOption` | 当前 option | | `instance` | `Ref` | ECharts 实例引用 | | `getEChart` | `() => ECharts \| undefined` | 获取 ECharts 实例方法 | ### 3.3 事件 组件接收 ECharts 事件监听器,通过 Vue 的 `v-on` 或属性传递,支持以下格式: - **kebab-case 事件名:** `:on-click="handler"`、`:on-dblclick="handler"` - 引擎自动转换 kebab-case 事件名为 camelCase 后注册到 ECharts 实例 ### 3.4 基础用法 ```vue ``` ### 3.5 动态更新 Option `option` 是响应式属性,变更后图表自动更新: ```vue ``` ### 3.6 通过 ref 访问 ECharts 实例 ```vue ``` --- ## 四、XMapChart 地图图表组件 ### 4.1 Props | 属性 | 类型 | 默认值 | 说明 | | --------- | ------------------ | ----------------------------------------------------------------- | ------------------------------------ | | `geoJson` | `string \| object` | `'https://unpkg.com/vtj-geojson@0.1.3/geo/100000/100000.geoJson'` | GeoJSON 数据或 URL,默认中国省级地图 | | `name` | `string` | `'china'` | 地图注册名称 | 其余 ECharts option 通过 `v-bind="$attrs"` 透传,需在 option 中配置地图相关的 series 或 geo。 ### 4.2 Emits | 事件名 | 参数 | 说明 | | ------- | --------- | ---------------------- | | `ready` | `geoJSON` | 地图数据加载完成后触发 | ### 4.3 Exposed 属性 | 名称 | 类型 | 说明 | | ------------- | ----------------------------------- | ------------------------ | | `chartRef` | `XChart 实例` | 内部 XChart 组件引用 | | `instance` | `ComputedRef` | 计算属性,ECharts 实例 | | `option` | `Ref` | 当前 option | | `getEChart` | `() => ECharts \| undefined` | 获取 ECharts 实例方法 | | `getChartRef` | `() => XChart 实例` | 获取内部 XChart 组件引用 | | `geoJSON` | `ShallowRef` | 已加载的 GeoJSON 数据 | ### 4.4 基础用法 提供 `geoJson` 数据源后,组件自动注册地图并通过 `v-bind="$attrs"` 透传的 option 渲染: ```vue ``` ### 4.5 使用自定义 GeoJSON ```vue ``` ### 4.6 使用 geo 组件而非 series-map 若配置 `option.geo` 而非 `series-map`,组件会自动将 `option.geo.map` 设为当前 `name`: ```vue ``` --- ## 五、组合式 API ### 5.1 useChart 用于在非组件场景下创建 ECharts 图表实例: ```typescript import { ref, onMounted } from 'vue'; import { useChart } from '@vtj/charts'; import type { ChartOption } from '@vtj/charts'; // 模板中:
const chartContainer = ref(); const chartOption = ref({ xAxis: { type: 'category', data: ['A', 'B', 'C'] }, yAxis: { type: 'value' }, series: [{ type: 'line', data: [10, 20, 15] }] }); const { instance, getEChart } = useChart(chartContainer, chartOption, {}); onMounted(() => { console.log('ECharts 实例:', getEChart()); }); ``` **参数说明:** | 参数 | 类型 | 说明 | | -------- | --------------------------------- | ---------------------------------- | | `el` | `MaybeRef` | 图表容器元素引用 | | `option` | `Ref` | ECharts option 响应式引用 | | `attrs` | `Record` | 事件监听器(如 `{ onClick: fn }`) | **返回值:** | 名称 | 类型 | 说明 | | ----------- | ---------------------------- | ----------------------- | | `instance` | `Ref` | ECharts 实例 | | `getEChart` | `() => ECharts \| undefined` | 获取 ECharts 实例的方法 | **自动能力:** - `onMounted` 时初始化 ECharts 实例并注册事件和 option - `option` 变化时自动 `setOption` - `useResizeObserver` 自动 resize(防抖 150ms) - `onUnmounted` 时自动 dispose 实例 ### 5.2 useMapChart 用于自定义地图场景: ```typescript import { ref } from 'vue'; import { useMapChart } from '@vtj/charts'; const mapName = ref('china'); const geoJson = ref('https://unpkg.com/vtj-geojson@0.1.3/geo/100000/100000.geoJson'); const { chartRef, geoJSON, option } = useMapChart(mapName, geoJson, { option: { series: [{ type: 'map', map: 'china', data: [...] }] } }); ``` **参数说明:** | 参数 | 类型 | 说明 | | --------- | --------------------- | ------------------------ | | `name` | `Ref` | 地图注册名称 | | `geoJson` | `Ref` | GeoJSON 数据或 URL | | `attrs` | `Record` | 透传属性(含 option 等) | **返回值:** | 名称 | 类型 | 说明 | | ---------- | ------------------ | --------------------- | | `chartRef` | `Ref` | 内部 XChart 组件引用 | | `geoJSON` | `ShallowRef` | 已加载的 GeoJSON 数据 | | `option` | `Ref` | 合并后的 option | **自动能力:** - name / geoJson 变化时自动重新加载和注册地图 - 加载过程中自动显示 / 隐藏 ECharts loading 状态 - 自动将 option 中的 series-map 和 geo.map 设为当前 name --- ## 六、VTJ Composition API 完整示例 ### 6.1 通用图表 - 柱状图 + 折线图混合 ```vue ``` ### 6.2 饼图 ```vue ``` ### 6.3 地图图表 ```vue ``` ### 6.4 异步数据加载 ```vue ``` --- ## 七、图表类型快速参考 以下列出 ECharts 支持的常用图表配置模式,可直接在 `option.series` 中使用: ### 7.1 折线图 ```typescript { type: 'line', data: [10, 20, 15], smooth: true, areaStyle: {} } ``` ### 7.2 柱状图 ```typescript { type: 'bar', data: [10, 20, 15], barWidth: '40%' } ``` ### 7.3 饼图 ```typescript { type: 'pie', data: [{ value: 100, name: 'A' }], radius: '50%' } ``` ### 7.4 散点图 ```typescript { type: 'scatter', data: [[10, 20], [15, 25], [20, 15]] } ``` ### 7.5 雷达图 ```typescript { type: 'radar', data: [{ value: [80, 90, 70, 85], name: '预算分配' }] } // 需配合 radar 组件: // radar: { indicator: [{ name: '销售额', max: 100 }, ...] } ``` ### 7.6 地图 ```typescript { type: 'map', map: 'china', data: [{ name: '广东省', value: 800 }] } ``` --- ## 八、注意事项 1. **option 必须为响应式:** 推荐使用 `ref` 包裹 option 对象,使其变更时自动触发图表更新 2. **option 深度监听:** 引擎内部对 option 进行了 `{ deep: true }` 的 watch,修改深层属性也会触发更新 3. **高度设默认值:** `XChart` 默认高度 `400px`,务必根据需要显式设置 `height` 4. **地图需 GeoJSON:** `XMapChart` 内置默认中国省级地图 GeoJSON URL,使用其他地图需提供自定义 GeoJSON 5. **事件名 kebab-case:** 事件属性以 `:on-` 开头、kebab-case 命名,如 `:on-click="handler"`、`:on-dblclick="handler"` 6. **自动 resize:** 组件内部已集成 `ResizeObserver`,容器尺寸变化时图表自动 resize 7. **生命周期管理:** 组件卸载时自动 dispose ECharts 实例,无需手动清理 8. **类型导入:** 需要 ECharts 类型时可从 `@vtj/charts` 导入 `ChartOption` 和 `EChartsInstance` 9. **无需直接操作 echarts 实例:** 大多数场景通过 `:option` 响应式更新即可,避免直接调用 `setOption` 10. **无需耗时搜索 ECharts 配置:** ECharts 的 option 配置语法遵循官方的 ECharts Option 规范,上述示例覆盖了最常用的图表类型和模式 --- ## 九、VTJ 设计器 Composition API 规范示例 > 以下示例展示在 VTJ 设计器中使用 Composition API(` ``` ### 9.2 GeoJSON 地图层级路径说明 `XMapChart` 的 `geo-json` 属性支持按行政区划编码逐级获取 GeoJSON 数据,当更换 `geo-json` 路径时需同步更新 `name` 属性: | 层级 | 示例 GeoJSON URL | `name` 值 | 说明 | | -------- | ------------------------------------------------------------------------- | ---------- | ---------------- | | 全国 | `https://unpkg.com/vtj-geojson@0.1.3/geo/100000.geoJson` | `'100000'` | 中国全国地图 | | 省级 | `https://unpkg.com/vtj-geojson@0.1.3/geo/100000/440000.geoJson` | `'440000'` | 广东省地图 | | 市级 | `https://unpkg.com/vtj-geojson@0.1.3/geo/100000/440000/440100.geoJson` | `'440100'` | 广州市地图 | | 省级含子 | `https://unpkg.com/vtj-geojson@0.1.3/geo/100000/100000.geoJson`(默认值) | `'china'` | 中国省级区划地图 | ```vue ``` > **注意:** 以上示例中的 `state` 和 `provider` 为 VTJ 设计器组件的标准模板代码,请保留。echarts 原始对象按需导入使用。 # VTJ Vue 代码编写约定 > 本文档描述 AI 大模型生成 Vue 组件代码时必须遵循的约定,确保输出内容能被 `@vtj/parser` 无损解析为 DSL。 --- ## 一、基础结构约定 ### 1.1 强制使用 ` ``` ### 1.2 SFC 文件结构顺序 ```vue ``` --- ## 二、` ``` # VTJ UniApp 全局配置 — AI 配置指南 > 本文档帮助 AI 理解 UniApp 平台的全局配置项,以及如何通过工具方法进行配置。 --- ## 一、配置数据流 ``` 设计器 UniApp 配置面板 项目数据 渲染引擎 uni-config/index.vue project.uniConfig uni/setup/app.ts ├── manifest.json ──┐ ┌── manifestJson ──→ injectUniConfig() → window.__uniConfig ├── pages.json ─────┤ setUni │── pagesJson ──→ injectUniRoutes() → window.__uniRoutes ├── CSS ────────────┤ Config │── css ──→ injectUniCSS() → adoptedStyleSheets └── 生命周期 ───────┘ └── onXxx ──→ createUniAppComponent() → App 组件方法 仅 UniApp 平台有效: 项目 platform === 'uniapp' 时,配置才会在运行时生效 ``` --- ## 二、UniConfig 完整字段 ```typescript interface UniConfig { manifestJson?: Record; // manifest.json 应用配置(JSON 对象) pagesJson?: Record; // pages.json 页面配置(JSON 对象) css?: string; // 全局 CSS 样式字符串 // ---- 应用生命周期函数 ---- onLaunch?: JSFunction; // 初始化完成时触发(全局只触发一次) onShow?: JSFunction; // 启动或从后台进入前台时触发 onHide?: JSFunction; // 从前台进入后台时触发 onError?: JSFunction; // 报错时触发 onPageNotFound?: JSFunction; // 页面不存在监听 onUnhandledRejection?: JSFunction; // 未处理的 Promise 拒绝监听(2.8.1+) onUniNViewMessage?: JSFunction; // nvue 页面数据通信监听 onThemeChange?: JSFunction; // 系统主题变化监听 onLastPageBackPress?: JSFunction; // 最后一个页面按 Android back 键 onExit?: JSFunction; // 应用退出监听 } ``` --- ## 三、配置工具方法 ### 3.1 `setUniConfig` — 设置 UniApp 配置 **参数:** | 参数 | 类型 | 必填 | 说明 | | ------- | ------ | ---- | ---------------------------------------- | | `key` | string | ✅ | 配置类型名,必须从枚举值中取(详见下方) | | `value` | string | ✅ | 配置内容,格式取决于 key | **`key` 可选枚举值(共 13 项):** | key | value 格式 | 说明 | | ---------------------- | ----------------- | ---------------------- | | `manifestJson` | JSON 字符串 | manifest.json 应用配置 | | `pagesJson` | JSON 字符串 | pages.json 页面配置 | | `css` | CSS 代码字符串 | 全局样式 | | `onLaunch` | JS 函数代码字符串 | 应用初始化完成 | | `onShow` | JS 函数代码字符串 | 应用进入前台 | | `onHide` | JS 函数代码字符串 | 应用进入后台 | | `onError` | JS 函数代码字符串 | 应用报错 | | `onPageNotFound` | JS 函数代码字符串 | 页面不存在 | | `onUnhandledRejection` | JS 函数代码字符串 | 未处理 Promise 拒绝 | | `onThemeChange` | JS 函数代码字符串 | 主题变化 | | `onUniNViewMessage` | JS 函数代码字符串 | nvue 数据通信 | | `onExit` | JS 函数代码字符串 | 应用退出 | **value 格式规则:** - `manifestJson` / `pagesJson`:JSON 字符串,如 `'{"appid":"xxx","name":"MyApp"}'` - `css`:CSS 代码字符串,如 `'body { background: #f5f5f5; }'` - 生命周期:JS 函数代码块,默认模板 `() => { }` - 传 `null`:清除该配置项 **示例:** ```json // 配置 manifest.json { "action": "setUniConfig", "parameters": [ "manifestJson", "{\"appid\":\"__UNI__123456\",\"name\":\"我的应用\",\"versionName\":\"1.0.0\"}" ] } // 配置 pages.json(含 tabBar) { "action": "setUniConfig", "parameters": [ "pagesJson", "{\"globalStyle\":{\"navigationBarTitleText\":\"首页\"},\"tabBar\":{\"list\":[{\"pagePath\":\"/\",\"text\":\"首页\"}]}}" ] } // 配置全局 CSS { "action": "setUniConfig", "parameters": [ "css", "body { margin: 0; padding: 0; font-family: sans-serif; }" ] } // 配置 onLaunch 生命周期 { "action": "setUniConfig", "parameters": [ "onLaunch", "() => {\n console.log('App 启动', uni.getLaunchOptionsSync())\n}" ] } ``` ### 3.2 `getUniConfig` — 获取 UniApp 配置 **参数:** `key: string` — 配置类型名(枚举值同 `setUniConfig`) **返回:** - `manifestJson` / `pagesJson`:格式化的 JSON 字符串 - `css`:CSS 字符串 - 生命周期:函数代码字符串 --- ## 四、配置详解 ### 4.1 `manifestJson` — 应用配置 对应 uni-app 的 `manifest.json`。运行时被解析后注入到 `window.__uniConfig`。 **关键字段参考:** | 字段 | 说明 | | ---------------- | --------------------------------------- | | `appid` | 应用 ID | | `name` | 应用名称 | | `versionName` | 版本名称 | | `versionCode` | 版本号 | | `h5.router` | H5 路由配置(mode、base) | | `h5.async` | 异步组件配置(loading、error、timeout) | | `networkTimeout` | 网络超时配置 | | `h5` | 其他 H5 平台相关配置 | ### 4.2 `pagesJson` — 页面配置 对应 uni-app 的 `pages.json`。影响全局样式、tabBar、easycom 等。 **关键字段参考:** | 字段 | 说明 | | ------------- | ----------------------------------------- | | `globalStyle` | 全局页面样式(navigationBarTitleText 等) | | `tabBar` | 底部 tabBar 配置(list、color 等) | | `easycom` | 自动导入组件配置 | **注意:** `pagesJson` 中的 `pages` 字段**不需要手动配置**,VTJ 会根据 `project.pages` 自动生成路由。 ### 4.3 `css` — 全局样式 注入为全局 CSS(通过 adoptedStyleSheets),影响所有页面。适用于定义全局字体、重置样式、CSS 变量等。 ### 4.4 应用生命周期 对应 uni-app 的 `App.vue` 组件方法。配置的函数将在应用级别的对应生命周期触发。 | 生命周期 | 触发时机 | 参数说明 | | ---------------------- | ---------------------- | ------------------- | | `onLaunch` | 初始化完成(全局一次) | launchOptions | | `onShow` | 启动 / 后台进入前台 | launchOptions | | `onHide` | 前台进入后台 | 无 | | `onError` | 报错时 | error | | `onPageNotFound` | 页面路由不存在 | { path, query } | | `onUnhandledRejection` | 未处理 Promise 拒绝 | { reason, promise } | | `onThemeChange` | 系统主题变化 | { theme } | | `onUniNViewMessage` | nvue 数据通讯 | data | | `onExit` | 应用退出 | 无 | **生命周期函数示例:** ```javascript // onShow — 监听应用进入前台 () => { const options = uni.getLaunchOptionsSync(); console.log('App Show', options); // 检查登录状态 // const token = uni.getStorageSync('token') // if (!token) uni.reLaunch({ url: '/pages/login' }) }; // onError — 全局错误捕获 () => { console.error('应用错误:', arguments); // 上报错误到监控平台 }; ``` --- ## 五、运行时处理流程 ``` setupUniApp(opts) ├── injectUniFeatures(opts, window) → 注入 UniApp 特性 ├── injectUniConfig(opts, window) → 解析 manifest.json → window.__uniConfig ├── injectUniGlobal(UniH5, window) → 注入 UniApp 全局 API ├── injectUniRoutes(Vue, UniH5, ...) → 根据 pages + pagesJson 生成路由 ├── injectUniCSS(appid, css, window) → 注入全局 CSS ├── Vue.createApp(setupApp(App)) → 创建 App 实例 ├── app.use(install, UniH5) → 安装 UniApp 插件 └── app.use(plugin) → 安装 H5 插件 ``` --- ## 六、注意事项 1. **仅 UniApp 平台有效:** 只有 `project.platform === 'uniapp'` 时,这些配置才会被加载和执行 2. **`pagesJson` 不配置 pages 字段:** VTJ 根据项目页面树自动生成路由,`pagesJson` 中只需配置 `globalStyle`、`tabBar` 等全局项 3. **manifestJson 影响运行时行为:** 如 `h5.router.mode` 决定路由模式(hash/history),`networkTimeout` 决定请求超时 4. **生命周期函数格式:** 必须是箭头函数或普通函数代码字符串,框架通过 `new Function()` 动态解析 5. **配置为 null 即清除:** 传 `value: null` 可清除对应配置项 6. **CSS 为全局注入:** 通过 adoptedStyleSheets 注入,不要在其中定义页面特定的样式 7. **manifestJson / pagesJson 需完整 JSON:** 每次设置会覆盖对应字段的全部内容,如需部分修改,应先 `getUniConfig` 读取再合并设置 8. **tabBar 来自 pagesJson:** tabBar 配置在 `pagesJson.tabBar` 中,各页面的 `style` 会与路由合并 # VTJ 工具库(@vtj/utils)— AI 使用指南 > 本文档帮助 AI 理解如何使用 `@vtj/utils` 工具库中的各类工具方法,在组件中实现网络请求、数据存储、URL 处理、文件下载等常见功能。 --- ## 一、工具库概览 `@vtj/utils` 是 VTJ 平台的通用工具库,提供以下核心功能模块: | 模块 | 功能 | 导入方式 | | -------------- | ------------------------------------------------ | ---------------------------------------------------------------------- | | **request** | HTTP 请求封装(基于 axios) | `import { request, createApi, createApis, useApi } from '@vtj/utils'` | | **storage** | 本地存储(localStorage/sessionStorage/内存缓存) | `import { storage } from '@vtj/utils'` | | **cookie** | Cookie 操作 | `import { cookie } from '@vtj/utils'` | | **url** | URL 解析与拼接 | `import { url } from '@vtj/utils'` | | **download** | 文件下载 | `import { downloadUrl, downloadBlob, downloadJson } from '@vtj/utils'` | | **logger** | 日志打印 | `import { logger } from '@vtj/utils'` | | **loadScript** | 动态加载外部脚本 | `import { loadScript } from '@vtj/utils'` | | **jsonp** | JSONP 跨域请求 | `import { jsonp } from '@vtj/utils'` | | **client** | 客户端环境检测 | `import { getClientInfo } from '@vtj/utils'` | | **raf** | requestAnimationFrame 封装 | `import { rAF, cAF } from '@vtj/utils'` | | **util** | 通用工具函数 | `import { isClient, fileToBase64, formDataToJson } from '@vtj/utils'` | --- ## 二、HTTP 请求模块(request) ### 2.1 核心 API | 方法 | 说明 | 返回值 | | -------------------------------- | ------------------------------ | ---------------------------------- | | `request(config)` | 发送 HTTP 请求 | `Promise` | | `createApi(url \| config, req?)` | 创建单个 API 函数 | `(data?, opts?) => Promise` | | `createApis(map, req?)` | 批量创建 API 函数 | `Record` | | `useApi(loader, transform?)` | Composition API 风格的请求钩子 | `{ data, error, loading, reload }` | ### 2.2 request 实例方法 ```javascript request.send(config) // 发送请求 request.cancel(id?) // 取消请求(不传 id 取消全部) request.setConfig(options) // 修改全局配置 request.useRequest(fn) // 请求拦截器 request.useResponse(fn) // 响应拦截器 ``` ### 2.3 请求配置(IRequestConfig) ```javascript { url: string, // 请求地址 method: string, // 请求方法:get/post/put/patch/delete settings: { type: 'form' | 'json' | 'data', // 数据格式(默认 form) loading: boolean, // 是否显示 loading showLoading: () => void, // 自定义显示 loading hideLoading: () => void, // 自定义隐藏 loading failMessage: boolean, // 是否显示失败提示 showError: (msg, e) => void, // 自定义错误提示 originResponse: boolean, // 返回原始 axios 响应 headers: object | function, // 自定义请求头 injectHeaders: boolean, // 是否注入自定义请求头 proxy: boolean, // 是否开启代理 proxyPath: string // 代理服务路径 }, query: object // URL path 参数对象(用于路径参数替换) } ``` ### 2.4 使用示例 #### 方式一:直接使用 request ```javascript import { request } from '@vtj/utils'; // GET 请求 const res = await request({ url: '/api/users', method: 'get', settings: { type: 'json', loading: true } }); // POST 请求(form 格式) const res = await request({ url: '/api/users', method: 'post', data: { name: '张三', age: 25 } }); // POST 请求(JSON 格式) const res = await request({ url: '/api/users', method: 'post', settings: { type: 'json' }, data: { name: '张三', age: 25 } }); // 带路径参数(query 用于替换 URL 中的 :id) const res = await request({ url: '/api/users/:id', method: 'get', query: { id: 123 } }); // 实际请求:/api/users/123 ``` #### 方式二:使用 createApi(推荐) ```javascript import { createApi } from '@vtj/utils'; // 创建 API 函数 const getUserList = createApi('/api/users'); const getUserById = createApi('/api/users/:id'); const createUser = createApi({ url: '/api/users', method: 'post', settings: { type: 'json' } }); // 调用 API const list = await getUserList(); const user = await getUserById(null, { query: { id: 123 } }); const newUser = await createUser({ name: '张三' }); ``` #### 方式三:使用 createApis 批量创建 ```javascript import { createApis } from '@vtj/utils'; const __apis = createApis({ getUserList: '/api/users', getUserById: '/api/users/:id', createUser: { url: '/api/users', method: 'post', settings: { type: 'json' } }, updateUser: { url: '/api/users/:id', method: 'put', settings: { type: 'json' } }, deleteUser: { url: '/api/users/:id', method: 'delete' } }); // 在组件中使用 onMounted(async () => { const res = await __apis.getUserList(); __state.userList = res.data || []; }); // 带路径参数调用 await __apis.getUserById(null, { query: { id: 123 } }); // 带请求体调用 await __apis.createUser({ name: '张三', age: 25 }); ``` #### 方式四:使用 useApi 钩子 ```javascript import { useApi, createApi } from '@vtj/utils'; const getUserList = createApi('/api/users'); // 自动加载数据 const { data, error, loading, reload } = useApi(getUserList()); // 带数据转换 const { data } = useApi(getUserList(), (res) => res.data?.list || []); ``` ### 2.5 params 与 query 的职责区分 > ⚠️ **重要规范:** 在 VTJ 的请求体系中,`params` 和 `query` 有明确的语义区分: | 参数类型 | 用途 | 位置 | 示例 | | ---------- | ------------------------------------ | ------------ | ----------------------------------- | | **query** | URL **路径参数**(Path Parameters) | URL 路径中 | `/api/users/:id` → `/api/users/123` | | **params** | URL **查询参数**(Query Parameters) | URL `?` 后面 | `/api/users?page=1&size=10` | **正确使用方式:** ```javascript // ✅ query 用于路径参数替换 await request({ url: '/api/users/:id', query: { id: 123 } }); // 实际请求:GET /api/users/123 // ✅ data 中的字段会自动成为查询参数(GET 请求) await request({ url: '/api/users', method: 'get', data: { page: 1, size: 10 } }); // 实际请求:GET /api/users?page=1&size=10 // ✅ POST 请求中 query 用于路径参数,data 用于请求体 await request({ url: '/api/users/:id', method: 'post', query: { id: 123 }, data: { name: '张三' } }); // 实际请求:POST /api/users/123 // 请求体:{ name: '张三' } ``` ### 2.6 路径参数传参规范 当 API 地址包含路径参数(如 `:id`)时,必须通过 `query` 字段传入: ```javascript // API 定义 const __apis = createApis({ getUser: '/api/users/:id', updateUser: { url: '/api/users/:id', method: 'put', settings: { type: 'json' } } }); // 正确调用方式 await __apis.getUser(null, { query: { id: 123 } }); await __apis.updateUser({ name: '张三' }, { query: { id: 123 } }); ``` **原理说明:** `request` 内部使用 `pathToRegexpCompile` 将 URL 中的 `:paramName` 替换为 `query` 对象中对应的值。 --- ## 三、本地存储模块(storage) ### 3.1 核心 API ```javascript import { storage } from '@vtj/utils'; storage.save(key, value, opts?) // 保存数据 storage.get(key, opts?) // 读取数据 storage.remove(key, opts?) // 删除数据 storage.clear(opts?) // 清空存储 storage.config(opts?) // 修改默认配置 ``` ### 3.2 存储类型(type) | 类型 | 说明 | 过期支持 | 环境 | | --------- | -------------- | -------- | -------- | | `local` | localStorage | ✅ 支持 | 浏览器 | | `session` | sessionStorage | ✅ 支持 | 浏览器 | | `cache` | 内存缓存 | ✅ 支持 | 所有环境 | ### 3.3 配置选项 ```javascript { type: 'cache' | 'local' | 'session', // 存储类型(默认 cache) expired: number, // 过期时间(毫秒),0 为永不过期 prefix: string // key 前缀(默认 '__VTJ_') } ``` ### 3.4 使用示例 ```javascript import { storage } from '@vtj/utils'; // 保存数据(永不过期) storage.save('userToken', 'abc123'); // 保存数据(1 小时后过期) storage.save('userToken', 'abc123', { type: 'local', expired: 60 * 60 * 1000 }); // 读取数据 const token = storage.get('userToken'); // 读取数据(指定存储类型) const token = storage.get('userToken', { type: 'local' }); // 删除数据 storage.remove('userToken'); // 清空所有缓存 storage.clear(); // 修改默认配置 storage.config({ type: 'local', prefix: 'MY_APP_' }); ``` ### 3.5 在 Composition API 中使用 ```javascript import { reactive, onMounted } from 'vue'; import { storage } from '@vtj/utils'; const __state = reactive({ user: null, token: '' }); onMounted(() => { // 从本地存储读取用户信息 __state.token = storage.get('userToken') || ''; __state.user = storage.get('userInfo', { type: 'local' }); }); function login(user) { __state.user = user; __state.token = user.token; // 保存到本地存储 storage.save('userToken', user.token, { type: 'local', expired: 7 * 24 * 60 * 60 * 1000 // 7 天 }); storage.save('userInfo', user, { type: 'local', expired: 7 * 24 * 60 * 60 * 1000 }); } function logout() { storage.remove('userToken', { type: 'local' }); storage.remove('userInfo', { type: 'local' }); __state.user = null; __state.token = ''; } ``` --- ## 四、Cookie 操作模块(cookie) ### 4.1 核心 API ```javascript import { cookie } from '@vtj/utils'; cookie.set(name, value, opts?) // 设置 Cookie cookie.get(name) // 读取 Cookie cookie.remove(name, opts?) // 删除 Cookie ``` ### 4.2 配置选项 ```javascript { expires: number, // 过期天数 path: string, // 路径(默认 '/') domain: string, // 域名 secure: boolean, // 仅 HTTPS sameSite: string // SameSite 策略 } ``` ### 4.3 使用示例 ```javascript import { cookie } from '@vtj/utils'; // 设置 Cookie(会话级别) cookie.set('userId', '12345'); // 设置 Cookie(7 天过期) cookie.set('userId', '12345', { expires: 7 }); // 设置 Cookie(指定路径和域名) cookie.set('userId', '12345', { expires: 7, path: '/', domain: '.example.com' }); // 读取 Cookie const userId = cookie.get('userId'); // 删除 Cookie cookie.remove('userId'); ``` --- ## 五、URL 处理模块(url) ### 5.1 核心 API ```javascript import { url } from '@vtj/utils'; url.stringify(query) // 对象转查询字符串 url.parse(str?) // 查询字符串转对象 url.append(url, query) // 在 URL 后追加参数 url.getHost(url) // 获取 URL 的 host url.getCurrentHost(includePath) // 获取当前页面 host ``` ### 5.2 使用示例 ```javascript import { url } from '@vtj/utils'; // 对象转查询字符串 const str = url.stringify({ page: 1, size: 10 }); // 结果:'page=1&size=10' // 查询字符串转对象 const obj = url.parse('page=1&size=10'); // 结果:{ page: '1', size: '10' } // 获取当前 URL 参数 const params = url.parse(); // 结果:从 location.search 解析参数 // 在 URL 后追加参数 const newUrl = url.append('/api/users', { page: 2 }); // 结果:'/api/users?page=2' // 追加参数到已有参数的 URL const newUrl = url.append('/api/users?sort=asc', { page: 2 }); // 结果:'/api/users?sort=asc&page=2' // 获取 URL 的 host const host = url.getHost('https://example.com/api/users'); // 结果:'https://example.com' // 获取当前页面 host const host = url.getCurrentHost(false); // 结果:'https://example.com' const hostWithPath = url.getCurrentHost(true); // 结果:'https://example.com/path/to/page' ``` --- ## 六、文件下载模块(download) ### 6.1 核心 API ```javascript import { downloadUrl, downloadBlob, downloadJson, downloadRemoteFile } from '@vtj/utils'; downloadUrl(url, filename?) // 下载指定 URL 的文件 downloadBlob(data, filename?, type?) // 下载 Blob 数据 downloadJson(data, filename?) // 下载 JSON 数据 downloadRemoteFile(url, filename?, type?)// 下载远程文件 ``` ### 6.2 使用示例 ```javascript import { downloadUrl, downloadBlob, downloadJson, downloadRemoteFile } from '@vtj/utils'; // 下载 URL 文件 downloadUrl('https://example.com/file.pdf', 'report.pdf'); // 下载 JSON 数据 const data = { name: '张三', age: 25 }; downloadJson(data, 'user.json'); // 下载 Blob 数据(CSV 文件) const csvContent = 'name,age\n张三,25'; downloadBlob(csvContent, 'users.csv', 'text/csv'); // 下载远程文件 await downloadRemoteFile( 'https://example.com/image.png', 'avatar.png', 'image/png' ); ``` ### 6.3 在组件中使用 ```javascript import { reactive } from 'vue'; import { downloadJson, createApi } from '@vtj/utils'; const exportData = createApi('/api/users/export'); const __state = reactive({ async exportUsers() { const res = await exportData(); downloadJson(res.data, 'users.json'); } }); ``` --- ## 七、日志模块(logger) ### 7.1 核心 API ```javascript import { logger, getLogger } from '@vtj/utils'; logger.debug(...args); // 调试日志 logger.log(...args); // 普通日志 logger.info(...args); // 信息日志 logger.warn(...args); // 警告日志 logger.error(...args); // 错误日志 ``` ### 7.2 日志级别 | 级别 | 值 | 说明 | | -------- | --- | -------- | | debug | -1 | 调试信息 | | log/info | 0 | 普通信息 | | warn | 1 | 警告信息 | | error | 2 | 错误信息 | ### 7.3 使用示例 ```javascript import { logger, getLogger } from '@vtj/utils'; // 使用默认 logger(bizName: 'VTJ') logger.info('页面加载完成'); logger.warn('用户未登录'); logger.error('请求失败', error); // 创建自定义 logger const myLogger = getLogger({ level: 'debug', bizName: 'MyApp' }); myLogger.debug('调试信息'); myLogger.info('[MyApp] 业务日志'); // 日志输出格式:[bizName] message // 例如:[VTJ] 页面加载完成 ``` ### 7.4 动态控制日志级别 通过 URL 参数控制日志输出: ``` https://example.com?__logConf__=debug https://example.com?__logConf__=warn:MyApp ``` 格式:`__logConf__=logLevel[:bizName]` --- ## 八、动态脚本加载(loadScript) ### 8.1 核心 API ```javascript import { loadScript } from '@vtj/utils'; loadScript(src, options?) // 动态加载外部 JS 脚本 ``` ### 8.2 配置选项 ```javascript { async: boolean, // 是否异步加载(默认 true) attrs: object, // 自定义属性 charset: string, // 字符集(默认 'utf-8') text: string, // 追加的脚本内容 type: string, // 脚本类型(默认 'text/javascript') library: string // window 上的全局变量名 } ``` ### 8.3 使用示例 ```javascript import { loadScript } from '@vtj/utils'; // 加载外部脚本 await loadScript('https://cdn.example.com/chart.js'); // 加载并获取全局变量 const Chart = await loadScript('https://cdn.example.com/chart.js', { library: 'Chart' }); // 加载带自定义属性 await loadScript('https://cdn.example.com/sdk.js', { async: true, attrs: { 'data-app-id': '12345' } }); ``` --- ## 九、JSONP 跨域请求(jsonp) ### 9.1 核心 API ```javascript import { jsonp } from '@vtj/utils'; jsonp(url, options?) // 发送 JSONP 请求 ``` ### 9.2 配置选项 ```javascript { query: object, // 查询参数 timeout: number, // 超时时间(毫秒) jsonpCallback: string, // 回调函数名 jsonpCallbackFunction: string // 回调函数名 } ``` ### 9.3 使用示例 ```javascript import { jsonp } from '@vtj/utils'; // 基础 JSONP 请求 const data = await jsonp('https://api.example.com/data'); // 带查询参数 const data = await jsonp('https://api.example.com/data', { query: { page: 1, size: 10 } }); // 带模板字符串的 URL const data = await jsonp('https://api.example.com/users/${id}', { query: { id: 123 } }); ``` --- ## 十、客户端环境检测(client) ### 10.1 核心 API ```javascript import { getClientInfo } from '@vtj/utils'; getClientInfo(); // 获取客户端环境信息 ``` ### 10.2 返回值 ```javascript { os: string, // 操作系统:Windows/Mac OS/iOS/Android/Linux osVersion: string, // 系统版本 browser: string, // 浏览器:Chrome/Safari/Firefox/Edge/Opera/IE browserVersion: string, // 浏览器版本 isMobile: boolean // 是否为移动设备 } ``` ### 10.3 使用示例 ```javascript import { getClientInfo } from '@vtj/utils'; const info = getClientInfo(); if (info.isMobile) { console.log('移动设备:', info.os, info.browser); } else { console.log('桌面设备:', info.os, info.browser); } ``` --- ## 十一、requestAnimationFrame 封装(raf) ### 11.1 核心 API ```javascript import { rAF, cAF } from '@vtj/utils'; rAF(fn); // 请求动画帧(兼容 SSR) cAF(handle); // 取消动画帧 ``` ### 11.2 使用示例 ```javascript import { rAF, cAF } from '@vtj/utils'; let handle; function animate() { // 动画逻辑 handle = rAF(animate); } // 开始动画 handle = rAF(animate); // 停止动画 cAF(handle); ``` --- ## 十二、通用工具函数(util) ### 12.1 核心 API ```javascript import { isClient, fileToBase64, formDataToJson, dataURLtoBlob, blobToFile } from '@vtj/utils'; isClient; // 是否为浏览器环境 fileToBase64(file); // File 转 Base64 formDataToJson(data); // FormData 转 JSON dataURLtoBlob(dataurl); // Base64 转 Blob blobToFile(blob, fileName); // Blob 转 File ``` ### 12.2 使用示例 ```javascript import { isClient, fileToBase64, formDataToJson } from '@vtj/utils'; // 环境检测 if (isClient) { // 浏览器环境代码 console.log(window.location.href); } // File 转 Base64 const base64 = await fileToBase64(file); // FormData 转 JSON const json = formDataToJson(formData); ``` --- ## 十三、典型工作流程 ### 13.1 数据获取与展示 ```javascript import { reactive, onMounted } from 'vue'; import { createApis, storage } from '@vtj/utils'; const __apis = createApis({ getUserList: '/api/users', getUserById: '/api/users/:id' }); const __state = reactive({ users: [], loading: false }); onMounted(async () => { // 尝试从缓存读取 const cached = storage.get('userList', { type: 'local' }); if (cached) { __state.users = cached; return; } // 从服务器获取 __state.loading = true; try { const res = await __apis.getUserList(); __state.users = res.data || []; // 缓存 5 分钟 storage.save('userList', __state.users, { type: 'local', expired: 5 * 60 * 1000 }); } finally { __state.loading = false; } }); ``` ### 13.2 文件上传与下载 ```javascript import { reactive } from 'vue'; import { createApi, downloadBlob, fileToBase64 } from '@vtj/utils'; const uploadFile = createApi({ url: '/api/upload', method: 'post', settings: { type: 'data' } // multipart/form-data }); const __state = reactive({ async handleUpload(file) { // File 转 Base64 const base64 = await fileToBase64(file); // 上传文件 const formData = new FormData(); formData.append('file', file); const res = await uploadFile(formData); return res.data; }, async handleExport() { const res = await __apis.exportData(); downloadBlob(res.data, 'export.xlsx', 'application/vnd.ms-excel'); } }); ``` ### 13.3 动态加载第三方库 ```javascript import { reactive, onMounted } from 'vue'; import { loadScript } from '@vtj/utils'; const __state = reactive({ chartLoaded: false }); onMounted(async () => { try { const Chart = await loadScript('https://cdn.example.com/chart.js', { library: 'Chart' }); if (Chart) { __state.chartLoaded = true; // 使用 Chart 库 } } catch (error) { logger.error('加载图表库失败', error); } }); ``` --- ## 十四、注意事项 1. **request 默认返回 `res.data.data`:** 除非设置 `originResponse: true` 才会返回完整的 axios 响应对象 2. **query 与 params 语义区分:** `query` 用于路径参数替换,请求体数据使用 `data` 字段 3. **storage 支持过期机制:** 过期时间单位为毫秒,0 表示永不过期 4. **isClient 用于 SSR 兼容:** 在非浏览器环境中访问 `window` 前先判断 `isClient` 5. **logger 支持动态级别控制:** 通过 URL 参数 `__logConf__` 可以动态调整日志输出 6. **loadScript 返回 Promise:** 加载成功返回 window 上的全局变量(如果指定了 `library`) 7. **download 方法需要浏览器环境:** 依赖 `document.createElement`,SSR 环境下不可用 8. **cookie 基于 js-cookie:** 完整 API 参考 [js-cookie 文档](https://github.com/js-cookie/js-cookie) --- ## 十五、从 @vtj/base 继承的工具 `@vtj/utils` 还从 `@vtj/base` 导出了以下常用工具: ```javascript import { merge, // 深度合并对象 omit, // 排除对象属性 debounce, // 防抖函数 throttle, // 节流函数 uuid, // 生成唯一 ID pathToRegexpCompile, // 路径参数编译 isUrl, // 判断是否为 URL template // 模板字符串编译 } from '@vtj/utils'; ``` 这些工具在 request、storage、url 等模块内部广泛使用,也可以在业务代码中直接使用。