# create-page-common **Repository Path**: als2014/create-page-common ## Basic Information - **Project Name**: create-page-common - **Description**: 基于swagger文档生成通用页面,例如:列表、详情、表单;弹窗;本项目使用vue编写,目前也只能生成vue2 + element-ui的页面;vue3 及其它语音版本,后续迭代;构造器基本是一样的,只要适配模板即可; - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: http://lianglei.site - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2023-12-14 - **Last Updated**: 2023-12-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 基于 swagger 的 VUE 代码生成器 根据 Swagger 文档定义,自动生成视图页面、API、路由、mock等。新页面可热更新直接运行。根据目标项目根目录(工作空间)中的 ESLint 环境配置信息,对文件进行 --fix 修复,保障文件代码格式与目标项目统一。 > 建议运行在 nodejs v14.21.3 与 npm 6.14.18 版本及邻近版本上;其它版本编译过程中可能会有异常; 建议使用nvm等node版本管理工具; > 高版本nodejs 建议使用 npm i -f 命令安装项目;经测试 nodejs 16.17.1 与 18.16.1 是可以兼容的; > 如果你的项目与本项目工作在不同node环境中,且本项目无法在当前版本下启动,建议使用nvm等工具切换到 v14.21.3,运行本项目,创建完所需页面后,再切换到你的node版本,运行你的项目;后续有时间可能考虑使用 electron 隔离node版本; ## 主要功能 * 支持 Swagger 文件数据及目标项目数据离线缓存,无需重复初始化项目; * 支持按需自动注入、注册自定义组件; * API文件支持按需增量更新,自动按需引入依赖函数,no never-used; * 路由文件支持新增一级路由,自动合并二级路由(依据swagger tag 分组);并自动备份至本项目 /bak 目录下; * 采用 art-template 字符串模板引擎,简单易用,并使用自定义规则解决与 Vue、ES5 模板语法冲突问题; * 支持自动匹配列名与列描述信息,并根据字段类型尝试自动匹配input-form-item * 支持自定义模板与模板数据(内置多种常用数据及格式);支持配置默认模板; * 支持配置同名文件存在时,自动覆盖或跳过,默认页面文件自动覆盖,路由及 API 自动跳过; * 支持配置自动生成的页面、目录、API 的文件名后缀连接符,例如:列表页默认为 filename-[list].vue,并且默认过滤文件名中的 (^query|list$)(可选,强迫症患者福音) * 支持配置列表字段默认对齐方式,默认数值型居中,其它类型居左; * 支持配置表单元素在各类型模板中是否可用【boolean | 正则:'list|form'】 * 支持字典数据; * 支持设置不参与用户交互的参数列表,例如:每页条数,当前页码等; * 支持自动识别匹配复合组件,例如双日历组件 data[Time]Range,同时支持手动配置,并高亮显示匹配关系;(Tips:需组件支持) ## 使用步骤 1. 启动本项目 ``` # npm install npm run local ``` > 建议在 cmd命令行中运行; 2. 初始化项目 填写swagger或catalog项目地址(格式如下图)、和本地目标项目根路径;初始化项目,成功后返回项目及接口信息,检查信息是否有误! ![初始化项目](./src/assets/readme-imgs/img-01.png) 3. 生成列表页 选择需要生成的页面对应的接口API,按需修改下方配置项目后,点击【生成】按钮,批量生成相关页面;如果目标项目服务已启动,此时可直接访问新页面; ![初始化项目](./src/assets/readme-imgs/img-02.png) > Tips: 列表API下拉框中只展示包含list的API; > 拖动检索条件、列表项区域中的图标( ),可改变字段显示顺序; > 列表项 -> 气泡:对应 show-overflow-tooltip ,暂不支持 table-header 使用气泡; > 列表项 -> 显示:设置是否在列表中显示该字段; ## 配置 > 注意:修改配置文件后,必须重启本项目; ``` { // 分页参数,例如每页条数,当前页码等非用户输入的参数 pageListParams: [ 'pageSize', 'currentPage' ], makeFile: { // 生成文件的配置 isMakeView: true, // 是否生成视图文件 isMakeApi: true, // 是否生成api文件 isMakeRouter: true, // 是否生成路由文件 isMakeMock: false // 是否生成mock数据文件 }, author: 'lianglei', // 作者 reWrite: { // 存在重名文件是否直接覆盖, true:覆盖; false:跳过; key值需与 template 中的key值一致,未设置的文件默认为true; listPage: true, // 列表页 infoPage: true, // 详情页 formPage: true // 表单页 }, listPage: { // 列表页 表格列对齐方式 colAlignDefault: 'left', // 默认居左对齐 colAlignInt: 'center' // 数字型默认居中对齐 }, // 项目文件结构路径配置 projectPath: { apisFilePath: 'src/apis', // api文件目录 httpFile: '@/apis/request.js', // 网络请求库,例如 axios;必须 export 导出 (post get del put)方法 routerFile: 'src/router/index.js', // 路由文件 routerMatchMark: '@/views/' // 路由文件中路由匹配标记, 可匹配路由文件中 component: () => import('@/views/icons/index'), 的 @/views/部分, }, // 生成文件的配置, 其中base开头的为基础模板配置,不可修改属性名称 template: { listPage: { // 列表页 savePath: 'src/views', // 生成的位置目录 相对于项目根目录的路径, 例如: src/views suffix: '-list', dirSuffix: '-page', // 视图目录后缀连接词, 例如 /user-page template: 'page/list-page.art' // 模板名称 相对于 /art-template 目录 }, infoPage: { // 详情页 savePath: 'src/views', // 生成的位置目录 相对于项目根目录的路径, 例如: src/views suffix: '-info', dirSuffix: '-page', // 视图目录后缀连接词, 例如 /user-page template: 'page/info-page.art' // 模板名称 相对于 /art-template 目录 }, infoDialog: { // 详情页弹窗 dialog savePath: 'src/components', // 生成的位置目录 相对于项目根目录的路径, 例如: src/views suffix: '-info-dialog', dirSuffix: '', // 视图目录后缀连接词, 例如 /user-page template: 'dialog/base-info.art' // 模板名称 相对于 /art-template 目录 }, formPage: { // 表单页 savePath: 'src/views', // 生成的位置目录 相对于项目根目录的路径, 例如: src/views suffix: '-form', dirSuffix: '-page', // 视图目录后缀连接词, 例如 /user-page template: 'page/form-page.art' // 模板名称 相对于 /art-template 目录 }, routerFile: { // 路由文件;名称不可修改; 暂不支持外部多路由文件,只支持单路由文件,也不支持路由的命名视图、动态加载等 template: 'base/base-router.art' // 模板名称 相对于 /art-template 目录 }, baseMockData: { // mock数据 baseMockData 名称不可修改 savePath: 'mock/json', // 生成的位置目录 相对于项目根目录 /mock/json/data templateLayout: 'base/base-mock-layout.art', // 模板名称 相对于 /art-template 目录 template: 'base/base-mock-item.art' // 模板名称 相对于 /art-template 目录 } }, // mock数据配置 mockCig: { // 模式数据类型映射 columnTypeMap: { /** * 同正则匹配字段名称,从而返回猜测类型的数据,预设的数据在/mock/json/data/example-data.js 文件中 makeDemoMockData * 匹配不到的所有模拟字段均返回 makeDemoMockData.randomStr 即1-5位随机字符 * 同一类型均有数量限制,限制为makeDemoMockData中key的后缀最大值:超过数量上限后返回随机数; * 例如: name1:XX; name2:xx; 则name类型最多可用3次,可用增加次数,例如name3\name4,但后缀必须是同前缀分组下的连续的整数; * 这里的key对应 /mock/json/data/example-data.js 文件中 makeDemoMockData 对象的key 的前缀 * 属性值只支持 正则表达式 或 false * 生成器中使用了 Object.assign 对配置信息进行合并,所以可随意扩展,如果想禁用预设字段的映射,将对应key值设置为false,例如: name:false * 注意后续版本中可能会移除预设的映射规则 */ integer: /integer/, name: /(title|name$)/i, city: /(^city|city$)/i, province: /(^province|province$)/i, email: /email/i, uid: /(code|id)/i, datetime: /(^datetime|datetime$)/i, date: /(^date|date$)/i, phone: /(^(phone|mobile)|(phone|mobile)$)/i } }, formItemCig: { dataTimeRangeRegExp: '^(start|end|begin)|(start|end|begin)$', // 不区分大小写 isStartRegExp: '^(start|begin)|(start|begin)$' // 不区分大小写 }, /** * 路由前缀连接词 * 可为空,如果设置则必须首字母大写,否则可能导致路由缓存不生效; * 用于构造 路由中的 name,及页面中 export default.name * 最终格式为: [lever2]xxxx ,例如:PageUserList, 其中page 为lever2路由前缀连接词,UserList为API名称 * 详见 /mock/json/createPage.js */ routerSuffix: { lever1: 'Menu', lever2: 'Page' }, /** * 表单元素类型 * disabled : 在构造模板中,不可使用(暂不支持)的元素 * [undefined] : 不禁用, 默认值; * [boolean] true : 全部禁用; * [string] 只有完全匹配的才禁用,例如:'list|form' 则表示为 list 或 form 禁用; * path : 可选,自定义组件的路径 例如:'@/components/cusDatePicker/index.vue' * valid : 必须,表单验证配置 * -- trigger: 必须,触发方式 'blur' 、'change' 等 * -- type: 可选,数据类型 'string'(默认)、'date'、'array' 等 * dataSource : 可选,数据源配置,例如:下拉选择框的选项 * -- dataType: 必须,数据格式,默认array,可选:array、object * -- default: 可选,数据源默认值,例如:下拉选择框的默认值 [{value: null, label: '全部'}] ; 如果没有对组件进行配置,则使用默认值 */ formItemOpts: [ { value: 'input', label: '单行文本框', valid: { trigger: 'blur' } }, { value: 'textarea', label: '多行文本框', disabled: 'list', valid: { trigger: 'blur' } }, { value: 'select', label: '下拉选择框', valid: { trigger: 'change' }, dataSource: { dataType: 'array', default: [{ value: null, label: '全部' }] } }, { value: 'radioGroup', label: '单选框组', disabled: 'list', valid: { trigger: 'change' }, dataSource: { dataType: 'array', default: [{ value: '-1', label: '选项一' }, { value: '-2', label: '选项二' }] } }, { value: 'radio', // 暂不支持,因为基本没有单独使用单选框的场景 label: '单选框', disabled: true, valid: { trigger: 'change' } }, { value: 'checkboxGroup', label: '多选框组', valid: { trigger: 'change', type: 'array' }, dataSource: { dataType: 'array', default: [{ value: '-1', label: '选项一' }, { value: '-2', label: '选项二' }] } }, { value: 'checkbox', label: '多选框', valid: { trigger: 'change' } }, { value: 'timePicker', label: '时间选择器', disabled: true, valid: { trigger: 'change', type: 'date' } }, { value: 'datePicker', label: '日期选择器', valid: { trigger: 'change', type: 'date' } }, { value: 'cusDatePicker', label: '日期选择器(双)', path: '@/components/cusDatePicker/index.vue', valid: { trigger: 'change', type: 'date' } } ], tableRowBgColor: [ 'table-row-success', 'table-row-brand', 'table-row-warning', 'table-row-danger' ] } ``` ## 预设模板变量 > 预设模板变量不可直接修改,只能扩展,或通过配置文件修改 ### 路由 ``` { path: '/${{lever1Path}}', component: Layout, name:'${{lever1RouterName}}', meta: { title: '${{lever1PageName}}', icon: 'el-icon-orange', code: '' // 设置code即可启用权限控制 }, redirect: '${{lever2Path}}', children: [ { path: '${{lever2Path}}', component: () => import('@/views/${{filePath}}'), name: '${{lever2RouterName}}', meta: { title: '${{lever2PageName}}', code: '' } } ] } ``` ### API (内置方法,API、路由与页面生成均依赖此对象) ``` { name, // api名称 nameHump, // api名称, 大驼峰格式 nameToPathfilter, // 过滤后的api名称,主要用于生成 view 页面 nameToPath, // 连接符(-)的 api名称 desc, // 接口描述 type, // 请求类型 get|post|del|put, 注意delete统一转换为del uri, // 接口地址 fileName, // API 所属分组 tags,连接符(-)格式,用于生成api文件名 fileNameHump, // API 所属分组 tags, 大驼峰格式 fileDesc // API 所属分组的描述 } ``` ### 页面 ``` { rootPath, // 项目根路径 formData: [ // 列表页检索项 { column, // 列名 示例:username isShow, // 是否显示 opts: { range: range_, // 双日历配置项 valid: null, // 表单验证配置项 attr: null // 可选,表单组件配置属性 }, // 配置项 needValidateOpts: false, // 是否需要验证配置项 label, // 示例:用户名 labelDesc, // 字段描述 示例:用户名,英文字母 columnType, // 类型 string|integer|array formItemType, // 表单元素类型 input|dataPicker 对应配置文件中 formItemOpts range: { // 默认: null , 仅当是双日历表单组件时返回 f_: '__DateTime', // 所执行的自动匹配模式 ,注意仅 'startDateTime' 与 'endDateTime' 可自动匹配为 '__DateTime';'startDateTime' 与 'dateTimeEnd' 不会自动匹配 to_: 'endDateTime', // 自动匹配到的对象列名称 isDatePickerRange: 'true|false', // 是否是双日历 isStart: 'true|false' // 是否是start 否则为end } } ], tableData: [ // 列表项 { column, label, columnType, isShow, showTips, // 单元格内容溢出后是否显示气泡 alignType // 列文本对齐方式 ,默认数字居中,文本居左;参照配置文件中 listPage 的配置 } ], otherConfig: { // 额外的扩展配置 showBtnCol: false, // 显示按钮列 showNumCol: true, // 显示序号列 showFormRightBtns: false // 显示表单右侧按钮区域 。。。 }, apiConfig, // 参照 模板预设变量中 《API》的说明 } ``` ### 表单元素配置 ``` 1、支持表单验证(validate) 2、部分组件支持自定义配置;详见目录 /art-template/base/form; 可自行修改或扩展,注意文件名称必须与 config.js 中 formItemOpts 声明的属性匹配; ``` ![表单元素配置](./src/assets/readme-imgs/img-03.png) ![表单元素配置](./src/assets/readme-imgs/img-04.png) ### 全局变量 #### 访问配置文件 config ``` 方法 :$imports.comConfig 示例 :输出作者 ${{$imports.comConfig.author}} ``` #### 获取需要注册的自定义组件列表(该方法只返回被实际使用到的组件,即按需注入) ``` 方法 :$imports.getCusPluginsListImport(formData) ; 其中 formData 为预设页面模板变量 示例 : # 1、声明变量 <% var _CusPluginsList_ = $imports.getCusPluginsListImport(formData) %> # 2、注入自定义组件 ${{each _CusPluginsList_}} import ${{$value.name}} from '${{$value.path}}' ${{/each}} > Tips: $value.name 与 $value.path 分别对应配置文件中 formItemOpts 对象的 value 与 path # 3、注册自定义组件 export default { components: { ${{each _CusPluginsList_}}${{$value.name}},${{/each}} } } ``` #### 获取表单验证配置信息 ``` 方法 :$imports.getValidationListImport(formData) ; 其中 formData 为预设页面模板变量 示例 : # 1、声明变量 <% var _ValidationList_ = $imports.getValidationListImport(formData) %> # 2、绑定到form组件 # 3、在data()中声明 rules ${{if _ValidationList_.length}} rules:{ ${{include 'base/base-form-rule.art' _ValidationList_}} }, ${{/if}} ``` #### 获取表单元素组件的枚举属性 ``` 方法 :$imports.getFormItemAttr(itemOpts) ; 其中 itemOpts 为预设页面模板变量: opts.attr 描述:返回属性的键值对字符串,注意此方法不会返回以'_'开头并且以 '_'结尾 (/^_[\w-]+_$/)的私有属性或临时变量 示例 : ``` #### 生成 mock 文件 > 有接口的请忽略,默认也未开启; 配置路径:config.js -> makeFile -> isMakeMock (是否生成mock数据文件)
> 参照 /art-template/base/base-mock-item.art ``` { url: '${{apiConfig.uri | getMockRouterUrl}}', type: '${{apiConfig.type}}', response: config => { if (!demo.__cacheKey__['${{apiConfig.name}}']) { const tobj = { ${{@ tableData | getMockRouterResData}} } demo.demoFnGetTheListKey(tobj) demo.__cacheKey__['${{apiConfig.name}}'] = { ...tobj } } return demo.demoFnMakeListPageData('${{apiConfig.name}}', config.query) } } ```