场景

1
2
3
- 售后人员无法统计做好的API案例,KMS上只有商家信息
- 销售人员在谈单过程中无法根据地域,类型快速获取相关案例,仅凭记忆十分消耗精力
- 方便销售人员谈单前信息收集准备

项目计划与实施

实现的功能

1
2
3
- 根据城市、行业、合作类型等条件进行对案例的筛选
- 根据关键词对案例进行搜索,包括案例名称与公司名称的搜索
- 对数据进行统计,展现成图表形式

技术准备

1
2
3
4
5
6
7
8
* 后台选型
* 服务器:NodeJs+Express
* 中间件:Express Route
* 前端选型
* 表现层:HTML(Jade)
* BootStrap+jquery
* 数据处理层:Vue.js
* 数据库(Model):MongoDB

技术实施

express安装:

1
$ npm install express-generator -g

接下来,用express-generator生成自己的文件夹

1
$ express caseManager

然后安装所有依赖包:

1
2
$ cd caseManager 
$ npm install

安装好之后,文件夹结构如下:
enter description here
express默认使用jade作为表现层的模板引擎,关于jade,可以查看教程


MongoDB服务启动:

进入项目文件夹,启动mongodb服务

1
2
$ cd caseManager
$ mongodb --dbpath <root>/caseManager/server --port 27017

express 路由配置:

路由级中间件配置(user页面为例):
app.js

1
2
3
4
5
var express = require('express');
var users = require('./routes/users');
var app = express();

app.use('/', users);

routes/users.js

1
2
3
4
5
6
7
8
9
var express = require('express');
var router = express.Router();

/* GET users listing. */
router.get('/', function(req, res, next) {
res.render('users');
});

module.exports = router;

应用级中间件配置(以筛选数据为例):
app.js

1
2
var filter = require('./model/filter');
app.use('/filter', filter);

config.js

1
2
var db = require('mongoskin').db('mongodb://localhost:27017/cases');
module.exports=db;

filter.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var express = require('express');
var router = express.Router();
var db = require('./config');

router.use(function timeLog(req, res, next) {
console.log('Time: ', Date.now());
next();
});

router.get('/',function (req,res) {
// var query=req.param('query');
var industry=req.param('industry');
var city=req.param('city');
var type=req.param('type');
db.collection('case_info01').find({
'行业':{$regex:industry},
'城市':{$regex:city},
'版本':{$regex:type}
}).toArray(function (p1, p2) {
if(p1) throw p1;
res.send(p2);
});
});

module.exports = router;

最后附上vueModel.js的代码与我的Jade代码
vue_module.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
var vm_content = new Vue({
el: '#content-show',
data: {
is_Chased:false,
list_show:true,
caseDatas:[],
pageNum:0,
index:1,
detailIndex:0
},
methods: {
chase: function (type) {
var that=this;
that.list_show=true;
this.is_Chased = true;
if(type=='search'){
var query=$('#search_text').val();
$.get('/search',{
query:query
},function (data) {
that.caseDatas=data;
that.pageNum=Math.ceil(data.length/9);
that.index=1;
});
}
else if(type=='filter'){
var industry=$('#industry_filter>option:checked').val();
var city=$('#city_filter').val()?($('#city_filter').val().split('-')[1]):"";
var type=$('#type_filter>option:checked').val();
$.get('/filter',{
industry:industry,
city:city,
type:type
},function (data) {
that.caseDatas=data;
that.pageNum=Math.ceil(data.length/9);
that.index=1;
})
}


},
shift_layout: function (detail_index) {
var that=this;
console.log(that.caseDatas[detail_index]);
this.detailIndex=detail_index;
if(!this.is_Chased){
return 0;
}
var temp= this.list_show;
this.list_show= !temp;
},
uploop: function () {
var that=this;
if(that.index>1) {
that.index--;
}
},
downloop: function () {
var that=this;
if(that.index<that.pageNum){
that.index++;
}
}
}
});

layout.jade

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
doctype html
html(lang='en')
head
title= '酷家乐API接口经典案例'
link(rel='stylesheet', href='/bootstrap/css/bootstrap.css')
link(rel='stylesheet', href='/stylesheets/animate.css')
link(rel='stylesheet', href='/stylesheets/style.css')
script(src='/jquery/jquery.js')
script(src='/bootstrap/js/bootstrap.js')
block head
body
nav.navbar.navbar-default(style='margin-bottom:0')
div.container-fluid
div.navbar-header
a(href='javascript:void(0);' onclick='backToOrigin();')
span.navbar-brand KuJiaLe 接口经典案例
div.navbar-btn
a.btn.btn-success(href='/charts') 数据图表
block navbar
div#content-show
block content
div.modal.fade#addCaseModal(tabindex='-1' role='dialog' aria-labelledby='addCaseModalLabel')
div.modal-dialog(role='document')
div.modal-content
div.modal-header
button.close(type='button' data-dismiss='modal' aria-label='Close')
span(aria-hidden='true') &times;
h4.modal-title#addCaseModalLabel 增加优秀案例
div.modal-body
form.form-horizontal
div.form-group
label.col-sm-4.control-label *案例名:
div.col-sm-8
input.form-control(type='text' placeholder='请输入案例名')
div.form-group
label.col-sm-4.control-label *行业:
div.col-sm-8
select.form-control
option(value="0") 装修公司
option(value="1") 硬装
option(value="2") 软装
option(value="3") 定制家具
option(value="4") 其他
div.form-group
label.col-sm-4.control-label *合作类型:
div.col-sm-8
select.form-control
option(value="0") 单点登录
option(value="1") 定制版
option(value="2") 第三方登录
div.form-group
label.col-sm-4.control-label *地区:
div.col-sm-8
input.form-control(placeholder='请选择城市' style='cursor:pointer').cityChoice
input.form-control(type='hidden').province
input.form-control(type='hidden').city
div.form-group
label.col-sm-4.control-label *描述:
div.col-sm-8
textarea.form-control(style='resize:none;' placeholder='请输入案例描述')
div.col-sm-offset-4.col-sm-8
label.control-label tips: 带*的是必填字段
div.modal-footer
button.btn.btn-default(type='button' data-dismiss='modal') 取消
a.btn.btn-warning(type='button') 确认
block foot
script(type='text/javascript').
var backToOrigin=function(){
window.location.href=window.location.origin;
}

users.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
extends layout

append head
link(rel="stylesheet", href="/city-picker/css/cityPicker.css")
link(rel='stylesheet', href='/stylesheets/users.css')
script(src='/javascripts/vue.js')
script(src='/city-picker/js/cityData.js')
script(src='/city-picker/js/cityPicker.js')
script(src='/javascripts/users.js')
append navbar
include filter

append content
include single
include detail
append foot
script(src='/javascripts/vue_module.js')

最后,让我们启动服务

1
$ npm start

输入网址 localhost:3000

详情请见 API案例