背景,公司后台管理系统很多新需求都是类似的,都是加一个新报表,查询条件,导出,合计,列表展示。其实就是一个页面的复制黏贴,但是由于前辈们在项目架构时期分层做的比较好(但是后续开发挺个人觉得有点累),每次加一个新页面,起码要在6个文件夹中拷贝出一个新文件。几次拷贝之后,懒癌发作,还不如花点时间写一个node脚本,将模板文件整理好,后边开发新页面直接跑一下脚本不就完事了,多出的时间摸鱼他不香吗。
实现思路
- 拷贝目录时,先在模板文件夹下创建对应通用模板
- 获取模板路径和项目路径(用户输入/config配置?)
- 拷贝模板,修改模板名称与内容中的对应key值,并黏贴到项目对应位置
开发
开发过程还是比较顺利的,按照整理好的开发思路。一共不到100行的代码。碰到了几个小问题
- 关于创建目录,node在创建文件时,是不会自动创建不存在的目录的,所以,创建文件之前要校验目录是否存在,不存在的话,就要手动创建一下目录。
function mkdir(filePath) { const arr=filePath.split('/'); const dirCache = {}; let dir=arr[0]; for(let i=1;i<arr.length;i++){ if(dir && !dirCache[dir]&&!fs.existsSync(dir)){ dirCache[dir]=true; console.log('dir',dir) fs.mkdirSync(dir); } dir=dir+'/'+arr[i]; } } if (!fs.existsSync(targetPath)) { mkdir(targetPath); } // 写入文件 fs.writeFileSync(`${targetPath}/${targetFileName}`,fileData)
- 另外一个问题是在于,怎么解决需要单独创建目录和已经创建好目录的问题,因为不是所有的新页面都需要添加新的目录,少数部分是在老模块中加新页面,这时候,目录部分是已经创建好的。不需要再创建,核心代码如下:
// config.js module.exports = { // 页面名称 pageName: 'testpage', // 模板 版本 templateVersions: 'baseRepart', keys : { url:{ targetPath: '/src/common/url/',needDir: true }, models:{ targetPath: '/src/models/',needDir: true }, services:{ targetPath: '/src/services/',needDir: true }, pages:{ targetPath: '/src/pages/',needDir: true, fileNameTitleCase: true }, components:{ targetPath: '/src/components/Business/',needDir: true, fileNameTitleCase: true }, } } // app.js const fs = require('fs') const { mkdir, $log,titleCase } = require('./util/index') const { pageName, templateVersions, keys } = require('./config') // 项目路径 const projectUrl = 'C:/Users/*****/web'; // 页面名称 首字母大写版本 const PageName = titleCase(pageName) if(!projectUrl || !fs.existsSync(projectUrl)){ $log('目标项目,目录不存在,请检查配置') process.exit() } Object.keys(keys).forEach(key => { // 读取模板目录 const { targetPath, replaceObj,fileNameTitleCase,needDir } = keys[key] let _tmpDirPath = `./template/${templateVersions}/${key}` let fileDirData = fs.readdirSync(_tmpDirPath) fileDirData.forEach(fileName => { // 读取目录下单个文件 let fileData = fs.readFileSync(_tmpDirPath+'/'+fileName).toString() // 重组写入的文件名称 let targetFileName = fileName.replace('index', fileNameTitleCase? PageName : pageName) // 重组目标路径 根据needDir判断是否需要添加目录 let _targetPath = projectUrl + targetPath + (needDir && (fileNameTitleCase? PageName+'/' : pageName+'/')) // 校验目标目录是否存在 console.log('_targetPath',_targetPath) if (!fs.existsSync(_targetPath)) { mkdir(_targetPath); } /* 处理文件中的替换字符 开始*/ // 默认替换 pageName和PageName 对应页面名称和 首字母大写的页面名称 fileData = fileData.replace(/__pageName__/g, pageName) fileData = fileData.replace(/__PageName__/g, PageName) // 如果replaceObj 中有值 遍历去替换 if(replaceObj && Object.keys(replaceObj).length){ Object.keys(replaceObj).forEach(replaceKey => { fileData = fileData.replace(/__${replaceKey}__/g,replaceObj[replaceKey]) }) } /* 处理文件中的替换字符 结束 */ // 写入文件 let err = fs.writeFileSync(`${_targetPath}${targetFileName}`,fileData) if(err){ $log(` ${_targetPath}/${targetFileName}写入失败! ${err} `) process.exit() }else{ $log(` ${targetFileName}写入成功! 路径:${_targetPath} `) } }) }) ```
结语
这次开发的工具,满足了最基本的功能,只是还有些待优化的地方:
- 项目根目录,目前只能手动写入,能否开发成vsCode插件,一键获取,或者选择文件夹的形式获取?
- 关于模板的版本,因为虽然都是大同小异的报表页面,内部也是区分字段的。能否再细致一下,做到控制里边字段的程度?
- 选择模板,能否预览对应的页面(electron客户端?)感觉好像有点脱离刚开始脚本的初衷了。