最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 动手做一个通用代码生成器

    正文概述 掘金(coderzhouyu)   2021-02-06   469

    思路分析

    我们可以认为代码生成器是收集一些信息后讲信息渲染到固定的代码模板中生成最终代码

    动手做一个通用代码生成器

    准备知识

    通过上面的分析,我们知道要写一个代码生成器要有以下一些预备知识:

    1. 可以获取用户输入
    2. 可以获取数据库信息
    3. 可以将内存信息写入到本地文件

    上面的这几点几乎所有流行的编程语言都可以做得到。我们这里选择使用nodeJs express

    ejs mysql

    关键步骤代码

    1. 安装Express 应用程序生成器

      # 如果安装缓慢请使用 cnpm  https://www.oschina.net/p/cnpm?hmsr=aladdin1e1
      npm install -g express-generator
         
      # 高版本node(包含在 Node.js 8.2.0 及更高版本中)可以用下面命令安装
      npx express-generator
      
    2. 生成Express 基本框架

      # 生成项目文件夹
      mkdir gen
      cd gen
         
      # 生成Express框架
      express -e --git
      
    3. 安装依赖包

      # mysql 用来操作数据库  lodash 是一个JavaScript常用的工具包
      npm install --save lodash mysql
      
    4. 创建基本信息收集表单

      打开前面通过命令生成的Express项目文件夹,打开项目根目录下的app.js 文件

      // 代码的12 - 14左右 
      // view engine setup
      app.set('views', path.join(__dirname, 'views'));
      app.set('view engine', 'ejs');
      

      可以看到ejs模板目录是项目根目录下的views文件夹,在index.ejs中添加一个表单,如下代码

      <!DOCTYPE html>
      <html>
         
      <head>
          <title>速聚代码生成器</title>
          <link rel='stylesheet' href='/lib/bootstrap-4.6.0/css/bootstrap.min.css'/>
          <link rel='stylesheet' href='/stylesheets/style.css'/>
      </head>
         
      <body>
      <nav class="navbar navbar-expand-lg navbar-light bg-light">
          <a class="navbar-brand" href="#">速聚代码生成器</a>
          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
                  aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
              <span class="navbar-toggler-icon"></span>
          </button>
          <div class="collapse navbar-collapse" id="navbarNav">
              <ul class="navbar-nav">
                  <li class="nav-item active">
                      <a class="nav-link" href="#">生成代码 <span class="sr-only">(current)</span></a>
                  </li>
              </ul>
          </div>
      </nav>
         
          <div class="row" style="margin:30px auto;width:600px ">
              <form action="/tables" method="post">
                  <div class="form-group">
                      <label for="exampleInputEmail1">项目名称</label>
                      <input type="name" class="form-control">
                  </div>
                  <div class="form-group">
                      <label for="exampleInputPassword1">作者</label>
                      <input class="form-control" name="author">
                  </div>
                  <div class="form-group">
                      <label for="exampleInputPassword1">表前缀移除</label>
                      <input class="form-control" name="pre">
                  </div>
                  <div class="form-group">
                      <label for="exampleInputPassword1">生成文件</label>
                      <br/>
                      <span>后端: </span>
                      <label><input type="checkbox" name="files[]" value="mappper">mappper</label>
                      <label><input type="checkbox" name="files[]" value="mappperXML">mappperXML</label>
                      <label><input type="checkbox" name="files[]" value="entity">entity</label>
                      <label><input type="checkbox" name="files[]" value="param">param</label>
                      <label><input type="checkbox" name="files[]" value="result">result</label>
                      <label><input type="checkbox" name="files[]" value="controller">controller</label>
                      <label><input type="checkbox" name="files[]" value="service">service</label>
                      <label><input type="checkbox" name="files[]" value="serviceimpl">serviceimpl</label>
                      <label><input type="checkbox" name="files[]" value="enum">enum</label>
                      <br/>
                      <span>前端: </span>
                      <label><input type="checkbox" name="files[]" value="indexJsx">indexJsx</label>
                      <label><input type="checkbox" name="files[]" value="addJsx">addJsx</label>
                      <label><input type="checkbox" name="files[]" value="editJsx">editJsx</label>
                      <label><input type="checkbox" name="files[]" value="apiJs">apiJs</label>
                  </div>
                  <div class="form-group">
                      <label for="exampleInputPassword1">是否生成api文档</label>
                      <br/>
                      <label><input type="radio" name="api">是</label>
                      <label><input type="radio" name="api">否</label>
                  </div>
                  <button type="submit" class="btn btn-primary">下一步</button>
              </form>
          </div>
      </body>
         
      </html>
         
      
    5. 创建接收表单信息路由

      Express 的路由文件写在项目根目录下的routes文件夹下,我们在routes/index.js添加一个新的路由用来接收表单信息

      Express基本路由

      router.post('/tables', function (req, res) {
         // req 就数据请求对象
      });
         
      
    6. 创建数据库连接池

      在获取到用户提交的信息之后我们还需要拿到数据库中的信息。

      # 在项目根目录下创建一个配置文件夹 用来存放配置文件
      mkdir config
      

      在config文件夹中创建一个db.js的文件用来配置数据库信息和创建数据库连接池

      var mysql = require('mysql')
      var pool = mysql.createPool({
          connectionLimit: 10,
          host: '127.0.0.1',
          user: 'root',
          password: '',
          database: 'database'
      });
         
      function  query(sql, values, callback) {
          console.log("db pool");
          pool.getConnection(function (err, connection) {
              if(err) throw err;
              console.log("sql ",sql,values);
              //Use the connection
              connection.query(sql, values,function (err, results, fields) {
                  console.log(JSON.stringify(results),err);
                  //每次查询都会 回调
                  callback(err, results);
                  //只是释放链接,在缓冲池了,没有被销毁
                  connection.release();
                  if(err) throw error;
              });
         
          });
      }
         
      exports.query = query;
      
    7. 获取指定库中所有的表信息

      通过上述创建的数据库连接池就能从数据库中读信息啦,我们回到routes/index.js文件

      // 引入数据库
      const db = require("../config/db")
         
      ....
         
      /**
       *  获取数据库中所有的数据表信息
       */
      router.post('/tables', function (req, res) {
          /**
           * 简单思路
           * 1. 通过 req.body 得到上一步中提交过来的信息
           * 2. 通过查询数据库得到目前连接的数据库的表信息
           */
          db.query("show tables", [], function (err, rows) {
              res.render('index', {
                  postData: {...req.body},
                  tables
              });
          });
      });
         
      
    8. 获取指定表中所有的字段信息

      同样的方法我们可以新建一个路由用来获取指定表的所有字段信息

      /**
       * 通过表名返回表结构信息
       */
      router.get('/table_info', function (req, res) {
          db.query('show full fields from' + req.query.name, [], function (err, rows) {
              res.send(rows);
          });
      });
      
    9. 汇总数据库信息和表单信息渲染到模板

      router.post('/gen', function (req, res) {
         
          // let dir = tempRootPath + new Date().getTime() + "/"
          let dir = tempRootPath
          const {tableColumn, postData} = req.body
         
          // 循环所有表
          _.each(tableColumn, function (item, key) {
              // 帕斯卡表名
              let pskTableName = _.capitalize(key)
         
              let frontPath = dir + key + "/front/" + pskTableName + "/"
              // 生成前端部分  按照表名称生成组件用帕斯卡方式
              mkdirsSync(frontPath)
         
              // 用到的值直接结构以免出现bug
              const {author, pre} = postData
              /*
               *  根据文件结构配置模板,生成对应的数据
               */
              let allColumns = tableColumn[key] ? tableColumn[key] : []
         
              // 生成代码
              generate(frontTemplateFiles, frontPath, {
                  updateColumns: _.filter(allColumns, item => item.showUpdate),
                  updateMustColumns: _.filter(allColumns, item => item.mustUpdate),
                  addColumns: _.filter(allColumns, item => item.showAdd),
                  addMustColumns: _.filter(allColumns, item => item.mustAdd),
                  listColumns: _.filter(allColumns, item => item.showList),
                  searchColumns: _.filter(allColumns, item => item.isSearch),
                  allColumns,
                  author,
                  pre,
                  pskTableName
              })
          })
         
         
          res.send("ok")
      })
      

    代码地址

    github地址


    起源地下载网 » 动手做一个通用代码生成器

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元