使用SQL语句生成Web图表

简单学了下nodejs web开发框架express,以及一些相关的技术…

关于express的部分主要参考:Node.js开发框架Express4.xNode.js + Express 构建网站简单示例

需要注意的是,express 4.x 构建器独立成了一个模块,如果要使用系统中的express命令,就必须安装独立的generator:

npm install -g express express-generator bower supervisor
express -e bower-express

使用-g(global)安装后默认安装到用户目录下,需要添加环境变量才能被应用识别:

export NODE_PATH=$HOME/AppData/Roaming/npm/node_modules

supervisor 是个好东西,代码变更可以热加载,自动重启:supervisor app.js

 

(一).首先来看主文件,app.js
var express = require('express'), ejs = require('ejs'), routes = require('./routes/index'), users = require('./routes/users'), session = require('express-session'), RDBStore = require('express-mysql-session');
var app = express();
// 定义视图路径及修改ejs模板后缀名
app.set('views', 'views');
app.engine('.html', ejs.__express);
app.set('view engine', 'html');
app.use(require('body-parser').urlencoded({ extended: false }));
// 定义静态文件路径
app.use(express.static('public'));
app.use(express.static('bower_components'));
// session保存
const options = {
    host : '1.1.1.1',
    user : 'test',
    port : 5029,
    password : 'test',
    database : 'test'
};
app.use(session({
    secret : 'test',
    store : new RDBStore(options),
    cookie : { maxAge: 10000 },
    resave : true,
    saveUninitialized : true
}));
// URL路由
app.get('/', routes.index).post('/', routes.index);
// 显示404错误及输出
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});
// 生产环境异常打印
if (app.get('env') === 'development')
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
// 启动及端口
//require('http').createServer(app).listen(3000);
app.listen(3000, function() {
    console.log('Express server listening on 3000');
});

由于没装No-SQL数据库,因此就用mysql来缓存session,

进入express生成的项目后使用npm安装即可:npm install express-mysql-session

用法很简单,启动项目后会在目标库自动新建一张innodb表,可以将其改为memory引擎:

ALTER TABLE sessions MODIFY data VARCHAR(5000),ENGINE=MEMORY;

当然,使用mongos或者rethinkdb会更方便,问题是node模块太多了有点眼花缭乱不知道用哪个好(bug少)……譬如:

npm install express-session-rethinkdb connect-rethinkdb session-rethinkdb

 

(二).好吧,接下来看“action”,routes/index.js:
var router = require('express').Router(), mysql = require('mysql');

const options = [{ host : '1.1.1.1', user : 'test', port : 5029, password : 'test', database : 'test', dateStrings : true }, {
{ host : '1.1.1.2', user : 'test', port : 3306, password : 'test', database : 'test', dateStrings : true }, {
{ host : '1.1.1.3', user : 'test', port : 3307, password : 'test', database : 'test', dateStrings : true//, multipleStatements : true
}];

module.exports.index = function(req, res) {
    var connection, sql;
    if (req.method == 'POST' && req.body && req.body.host && /^[1-3]$/.test(req.body.host) && req.body.title && req.body.sql) {
        //var pool = mysql.createPool(options[2]);
        connection = mysql.createConnection(options[req.body.host - 1]);
        sql = req.body.sql;
    } else {
        res.render('index', {
            'params' : { title : '', sql : '', host : ''}, 'x' : '[]', 'y' : '[]'
        });
        return;
    }
    connection.query(sql, function(err, rows, fields) {
        if (err) throw err;
        var x = [], y = [];
        for (var i in rows) {
            //if (rows[i].x instanceof Date) x[i] = require('moment')(rows[i].x).format('YYYY-MM-DD');
            x[i] = rows[i].x;
            y[i] = rows[i].y;
        }
        res.json({ 'x' : x, 'y' : y });
    });
    connection.end();
};

代码很简单,GET请求直接返回页面(当然也可以处理queryString),POST请求返回JSON数据。

一开始不知道node-mysql有个 dateStrings的参数,所以用 moment.js来转换日期格式,也很方便。

在开发页面前先使用 bower下载好所需的jQuery、BootstrapACEECharts等库:

bower install ace echarts bootstrap jquery

 

(三).最后来上展示页面,views/index.html:
<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <title><%-params.title%></title>
    <link rel="stylesheet" href="bootstrap/dist/css/bootstrap.min.css">
</head>
<body>
    <div id="editor" style="height:60px;font-size:16px"><%-params.sql%></div>
    <form style="width:60%;height:90px;padding:10px 40px">
        <div class="form-group col-xs-4" style="padding-left:0px">
            <select class="form-control" name="host">
                <option value="">Select Host</option>
                <option value="1">1.1.1.1:5029</option>
                <option value="2">1.1.1.2:3306</option>
                <option value="3">1.1.1.3:3306</option>
            </select>
        </div>
        <div class="form-group col-xs-4" style="padding-left:0px">
            <input type="text" name="title" class="form-control" placeholder="title" value="<%-params.title%>" />
        </div>
        <button type="button" onclick="query()" class="btn btn-primary">Query</button>
    </form>
    <hr />
    <div id="main" style="height:400px"></div>
    <script src="echarts/build/dist/echarts.js"></script>
    <script type="text/javascript" src="jquery/dist/jquery.min.js"></script>
    <script type="text/javascript" src="bootstrap/dist/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="javascripts/ace/src-min-noconflict/ace.js"></script>
    <script type="text/javascript">
// js在下面  ↓↓↓↓↓
    </script>
</body>

以上的JS代码如下:

$('select').val(<%-params.host%>);
var editor = ace.edit('editor'), myChart, options = {
    tooltip: { show: true },
    legend: { data : ['<%-params.title%>'] },
    xAxis : [{ type : 'category', data : <%-x%> }],
    yAxis : [{ type : 'value' }],
    series : [{ 'name' : '<%-params.title%>', 'type' : 'bar', 'data' : <%-y%> }]
};
editor.setTheme('ace/theme/sql');
editor.getSession().setUseWrapMode(true);
editor.getSession().setMode('ace/mode/sql');
// 路径配置
require.config({ paths: { echarts: 'echarts/build/dist' } });
// 使用
require(
    [ 'echarts', 'echarts/chart/bar' ],
    function (ec) {
        myChart = ec.init($('#main').get(0));
        myChart.setOption(options);
    }
);
 
function query() {
    myChart.showLoading();
    $.ajax({
        url : window.location.pathname,
        cache : false,
        type : 'POST',
        dataType : 'json',
        data : $('form').serialize() + '&sql=' + editor.getValue(),
        success : function(obj) {
            var title = $(':text').val();
            options.legend.data[0] = title;
            options.xAxis[0].data = obj.x;
            options.series[0].data = obj.y;
            options.series[0].name = title;
            myChart.clear();
            myChart.hideLoading();
            myChart.setOption(options);
        }
    });
}

注意:

  • echarts的 setOption 方法是更新操作,因此要先clear图表后重新绘图;
  • ACE是一个源码编辑器,同大名鼎鼎的 CodeMirror 类似,API也是大同小异;
  • 如果bower 下载的ACE没有编译,前往 ace-builds 页面下载。

 

至此,一个简单的web应用就诞生了,就像 ChartSQL做的那样,可以再完善ajax异常处理、node-mysql的连接池等。

好久没碰过前端相关的技术,写起来各种生疏,代码拙劣、欢迎指教。最后来一张效果图:

 

(其他):

关于http代理设置,NPM如下:

npm config set proxy=http://127.0.0.1:8080

bower需要在用户目录下新建文件:.bowerrc

{
  "proxy":       "http://127.0.0.1:8080",
  "https-proxy": "http://127.0.0.1:8080",
  "strict-ssl":  false
}

转载于:https://my.oschina.net/cwalet/blog/497448

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值