rails全国订单发货热力图

31 篇文章 0 订阅
[b]路由配置[/b]

get '/monitor' => 'dashboard#monitor'
get '/inquiries/stats' => 'inquiries#stats'
get '/inquiries/day' => 'inquiries#day'
get '/inquiries/now' => 'inquiries#now'


[b]视图[/b]

<!DOCTYPE html>
<html>
<head>
<title>订单热力分布报表</title>
<script type="text/javascript">
window.odometerOptions = { theme: 'plaza', fixedLenght: 6 ,format: '(ddd).dd',};
</script>
<%= stylesheet_link_tag 'application' %>
<style type="text/css">
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
background: transparent;
border: 0;
margin: 0;
padding: 0;
vertical-align: baseline;
list-style-type: none;
}
body{
font-size: 12px;
background-color: #2e302f ;
font-family: "微软雅黑";
}
.large_screen{
overflow: hidden;
width: 1980px;
height: 1320px;
margin:40px 15px;
background-image: url('/assets/main_frame_lv.png');
background-repeat:no-repeat;
}
.large_screen .statistics{
float: left;
margin-left: 50px;
margin-top: 163px;
width: 520px;
height: 1055px;
}
.large_screen .map{
float: left;
margin-top: 216px;
width: 1300px;
height: 1012px !important;
background-color: #2e302f !important;
}
.large_screen .statistics .num{
width: 572px;
height: 160px;
margin-left: 40px;
margin-bottom: 10px;
padding: 15px;
color: #fff;
}
.large_screen .statistics .num .title{
width: 140px;
height: 27px;
font-size: 27px;
}
.large_screen .statistics .num .quantity ul li{
float: left;
width: 60px;
height: 65px;
margin-top: 25px;
margin-right: 10px;
text-align: center;
line-height: 60px;
font-size: 40px;
color: #fff;
border:1px solid #129d7b;
}
.large_screen .statistics .num .quantity ul li:first-child{
margin-left: 20px;
}
.large_screen .statistics .pid{
width: 640px;
height: 455px;
margin-top: 70px;
margin-left: 40px;
margin-bottom: 10px;
background-image: url('/assets/pid_lv.png');
background-repeat: no-repeat;
}

</style>
<%= javascript_include_tag 'application' %>
<%= csrf_meta_tags %>
</head>
<body>

<div class="large_screen">
<div class="statistics">
<div class="num">
<div class="title">总询单量</div>
<div class="quantity">
<div id='inquiry_count' class="odometer">

</div>
</div>
</div>
<div class="num">
<div class="title">总定单量</div>
<div class="quantity">
<div id="order_count" class="odometer">

</div>
</div>
</div>
<div class="num">
<div class="title">总用户量</div>
<div class="quantity">
<div id="user_count" class="odometer">

</div>
</div>
</div>
<div class="pid"></div>
</div>
<div class="map" id="map"></div>
</div>

<script type="text/javascript">

var updateInqury = (function(el){
var element = $(el);
var total = 0;
return function(data){
if(typeof data == 'number'){
total = data;
}else{
total += _.sumBy(data, function(o) { return o.value; });
}
element.html(total);
}
})("#inquiry_count");

var updateStats = (function(){
var user = $('#user_count');
var order = $('#order_count');
var inq = $('#inquiry_count')
return function(){
$.get('/inquiries/stats',function(response){
updateInqury(response.data.inquiries);
order.html(response.data.orders);
user.html(response.data.users);
});
}
})();
updateStats();
setInterval(updateStats, 120 * 1000);
var monitor;
$('#map').css('height', $(window).height() + 'px');
$.get('/inquiries/day',function(response){
var last_id = response.last_id;
monitor = MyMonitor(document.getElementById('map'), {data: response.data, geoCoordMap: allCities});
setInterval(function(){
$.get('/inquiries/now',{id: last_id},function(response){
updateInqury(response.data);
last_id = response.last_id;
monitor.add(response.data);
})}
,10 * 1000);
setInterval(function(){
$.get('/inquiries/day',function(response){
last_id = response.last_id;
monitor.refresh(response.data);
});
},30 * 60 * 1000);

$(window).resize(function() {
$('#map').css('height', $(window).height() + 'px');
monitor.chart.resize();
});
});
</script>
</body>
</html>


[b]控制层[/b]

class InquiriesController < ApplicationController
def stats
results = {}
results[:data] = {}
results[:data][:users] = User.count
results[:data][:inquiries] = Inquiry.count
results[:data][:orders] = OrderDetail.count
render :json => results
end
def day
render :json => report_json(0,DateTime.now.beginning_of_day)
#render :json => report_json(0,3.month.ago)
end

def now
render :json => report_json(params.require(:id).to_i, 1.hours.ago.at_beginning_of_hour)
end

private
FORMAT_CITY_REGEXP = /布依族|苗族|藏族|羌族|傈僳族|傣族|哈尼族|彝族|景颇族|蒙古族|回族|朝鲜族|县|自治州|地区|市|/
def format_city(name)
name.to_s.gsub(FORMAT_CITY_REGEXP,'')
end

def report_json(id,time=nil)
query = Inquiry.group(:inquiry_city).select(:inquiry_city, 'count(id) as cnt')
query = query.where("id > ?", id) if (id && id > 0)
query = query.where("created_at > ?", time) if (time)
results = {}
results[:data] = query.map do |stats|
{:name => format_city(stats.inquiry_city), :value => stats[:cnt]}
end
results[:last_id] = Inquiry.last.id
results
end
end


[b]渲染js[/b]

var MyMonitor = function(dom, opts){
opts = opts || {};
var data = opts.data || [];
var geoCoordMap = opts.geoCoordMap || {};

var currentDate = function(){
var cur = new Date();
return '' + cur.getFullYear() + '-' + (cur.getMonth() + 1) + '-' + cur.getDate();
}

var convertData = function (data) {
var res = [];
for (var i = 0; i < data.length; i++) {
var geoCoord = geoCoordMap[data[i].name];
if (geoCoord) {
res.push({
name: data[i].name,
value: geoCoord.concat(data[i].value)
});
}
}
return res;
};

 var option = {
backgroundColor: '#404a59',
title: {
subtext: 'From whmall.com ' + currentDate(),
left: 'right',
subtextStyle:{
color: '#129d7b',
fontSize: '23',
},
bottom :'0',
},


geo: {
map: 'china',
label: {
emphasis: {
show: false
}
},
roam: true,
itemStyle: {
normal: {
borderWidth: 2,
areaColor: '#2e302f',
borderColor: '#129d7b'
},
emphasis: {
areaColor: '#2a333d'
}
}
},
tooltip : {
trigger: 'item',
formatter: function(params,ticket,callback){
return '' + params.name + ': ' + params.value[2];
}
},
legend: {
orient: 'vertical',
y: 'bottom',
x:'right',
data:['pm2.5'],
textStyle: {
color: '#fff'
}
},
series : [
{
type: 'scatter',
coordinateSystem: 'geo',
data: convertData(data),
symbolSize: function (val) {
if(val){
return 2 + Math.log2(val[2]) * 2;
}else{
return 0;
}},
label: {
normal: {
textStyle: { fontSize: '22', color: '#fff'},
formatter: '{b}',
position: 'right',
show: false
},
emphasis: {
show: true
}
},
itemStyle: {
normal: {
color: '#ddb926'
}
}
},
{
type: 'effectScatter',
coordinateSystem: 'geo',
data: convertData(data.sort(function (a, b) {
return b.value - a.value;
}).slice(0, 6)),
symbolSize: function (val) {
if(val){
return 2 + Math.log2(val[2]) * 2;
}else{
return 0;
}
},
showEffectOn: 'render',
rippleEffect: {
brushType: 'stroke'
},
hoverAnimation: true,
label: {
normal: {
textStyle: { fontSize: '22', color: '#fff'},
formatter: '{b}',
position: 'right',
show: true
}
},
itemStyle: {
normal: {
color: '#f4e925',
shadowBlur: 10,
shadowColor: '#333'
}
},
zlevel: 1
},
{
zlevel: 2,
type: 'scatter',
coordinateSystem: 'geo',
hoverAnimation: false,
data: [],
symbolSize: function (val) {
return 10;
},
label: {
normal: {
//textStyle: { color: '#24e925' },
show: true,
textStyle: { fontSize: '18', color: '#fff'},
formatter: function(params,ticket,callback){
return '' + params.name + '有' + params.value[2] + '个新订单';
}
},
emphasis: { show: false }
},
itemStyle: {
normal: {
color: '#fdd946'
}
}
}
]
};


var chart = echarts.init(dom);
chart.setOption(option);

var clearNewHandle;
var clearNew = function(){
option.series[2].data = [];
chart.setOption(option);
}

return {
geoCoordMap: geoCoordMap,
chart: chart,
refresh: function(newData){
data = newData;
option.series[0].data = convertData(data);
option.series[1].data = convertData(data.sort(function (a, b) { return b.value - a.value; }).slice(0, 6));
option.title.subtext = 'From me ' + currentDate();
chart.setOption(option);
},
add: function(newData){
if(newData.length == 0){ return; }
_(newData).forEach(function(t) {
var c = _.find(data, function(o) { return o.name == t.name; });
if(c){
c.value += t.value;
}else{
data.push(t);
}
});

option.series[0].data = convertData(data);
option.series[1].data = convertData(data.sort(function (a, b) { return b.value - a.value; }).slice(0, 6));
option.series[2].data = convertData(newData);
option.title.subtext = 'From me ' + currentDate();
chart.setOption(option);
if(clearNewHandle){ clearTimeout(clearNewHandle); }
clearNewHandle = setTimeout(clearNew, 2000);
}
}
}


[b]城市经纬[/b]

var allCities = {
'上海':[121.29,31.14],
'北京':[116.40717,39.90469],
'天津':[117.19,39.08],
'重庆':[106.54,29.59],
'石家庄':[114.5143,38.04276],
'唐山':[118.18058,39.63048],
'秦皇岛':[119.59964,39.93545],
'邯郸':[114.53918,36.62556],
'邢台':[114.50443,37.07055],
'保定':[115.46459,38.87396],
'张家口':[114.88755,40.82444],
'承德':[117.9634,40.9515],
'沧州':[116.83869,38.30441],
'廊坊':[116.68376,39.53775],
'衡水':[115.67054,37.73886],
'太原':[112.55067,37.87059],
'大同':[113.30001,40.07637],
'阳泉':[113.58047,37.85668],
'长治':[113.11649,36.19581],
'晋城':[112.85113,35.49039],
'朔州':[112.43181,39.33159],
'晋中':[112.75278,37.68702],
'运城':[111.00699,35.02628],
'忻州':[112.73418,38.4167],
'临汾':[111.51962,36.08822],
'吕梁':[111.14165,37.51934],
'呼和浩特':[111.75199,40.84149],
'包头':[109.84021,40.65781],
'乌海':[106.79546,39.65384],
'赤峰':[118.88894,42.2586],
'通辽':[122.24469,43.65247],
'鄂尔多斯':[109.78087,39.60845],
'呼伦贝尔':[119.76584,49.21163],
'巴彦淖尔':[107.38773,40.74317],
'乌兰察布':[113.13376,40.99391],
'兴安':[122.03818,46.08208],
'锡林郭勒':[116.04775,43.9332],
'阿拉善':[105.72898,38.85153],
'沈阳':[123.43236,41.80563],
'大连':[121.61476,38.91369],
'鞍山':[122.9946,41.10777],
'抚顺':[123.95722,41.87971],
'本溪':[123.76686,41.29413],
'丹东':[124.35601,39.9998],
'锦州':[121.12703,41.09515],
'营口':[122.2349,40.66683],
'阜新':[121.67011,42.02166],
'辽阳':[123.23736,41.26809],
'盘锦':[122.07078,41.11996],
'铁岭':[123.84241,42.2862],
'朝阳':[120.4508,41.57347],
'葫芦岛':[120.83699,40.711],
'长春':[125.32357,43.81602],
'吉林':[126.54944,43.83784],
'四平':[124.35036,43.16646],
'辽源':[125.14368,42.88805],
'通化':[125.9399,41.72829],
'白山':[126.42443,41.9408],
'松原':[124.82515,45.1411],
'白城':[122.83871,45.6196],
'延边':[129.5091,42.89119],
'哈尔滨':[126.5358,45.80216],
'齐齐哈尔':[123.91796,47.35431],
'鸡西':[130.96954,45.29524],
'鹤岗':[130.29785,47.34989],
'双鸭山':[131.1591,46.64658],
'大庆':[125.10307,46.58758],
'伊春':[128.84049,47.72752],
'佳木斯':[130.3206,46.80019],
'七台河':[131.00306,45.77065],
'牡丹江':[129.63244,44.55269],
'黑河':[127.52852,50.24523],
'绥化':[126.96932,46.65246],
'大兴安岭':[124.59216,51.92398],
'南京':[118.79647,32.05838],
'无锡':[120.31237,31.49099],
'徐州':[117.28577,34.2044],
'常州':[119.97365,31.81072],
'苏州':[120.58319,31.29834],
'南通':[120.89371,31.97958],
'连云港':[119.22295,34.59669],
'淮安':[119.01595,33.61016],
'盐城':[120.16164,33.34951],
'扬州':[119.41269,32.39358],
'镇江':[119.425,32.18959],
'泰州':[119.92554,32.45546],
'宿迁':[118.27549,33.96193],
'杭州':[120.15515,30.27415],
'宁波':[121.55027,29.87386],
'温州':[120.69939,27.99492],
'嘉兴':[120.7555,30.74501],
'湖州':[120.08805,30.89305],
'绍兴':[120.5802,30.03033],
'金华':[119.64759,29.07812],
'衢州':[118.87419,28.93592],
'舟山':[122.20778,29.98539],
'台州':[121.42056,28.65611],
'丽水':[119.92293,28.4672],
'合肥':[117.22901,31.82057],
'芜湖':[118.43313,31.35246],
'蚌埠':[117.38932,32.91548],
'淮南':[116.9998,32.62549],
'马鞍山':[118.50611,31.67067],
'淮北':[116.79834,33.95479],
'铜陵':[117.81232,30.94486],
'安庆':[117.06354,30.54294],
'黄山':[118.33866,29.71517],
'滁州':[118.31683,32.30181],
'阜阳':[115.81495,32.88963],
'宿州':[116.96391,33.64614],
'六安':[116.52324,31.73488],
'亳州':[115.77931,33.84461],
'池州':[117.49142,30.66469],
'宣城':[118.75866,30.94078],
'福州':[119.29647,26.07421],
'厦门':[118.08948,24.47951],
'莆田':[119.00771,25.454],
'三明':[117.63922,26.26385],
'泉州':[118.67587,24.87389],
'漳州':[117.64725,24.51347],
'南平':[118.17783,26.64152],
'龙岩':[117.01722,25.07504],
'宁德':[119.54819,26.66571],
'南昌':[115.85794,28.68202],
'景德镇':[117.17839,29.26869],
'萍乡':[113.85427,27.62289],
'九江':[116.00146,29.70548],
'新余':[114.91713,27.81776],
'鹰潭':[117.06919,28.26019],
'赣州':[114.93476,25.83109],
'吉安':[114.99376,27.11382],
'宜春':[114.41612,27.81443],
'抚州':[116.35809,27.94781],
'上饶':[117.94357,28.45463],
'济南':[116.99493,36.66529],
'青岛':[120.38299,36.06623],
'淄博':[118.0548,36.8131],
'枣庄':[117.32196,34.81071],
'东营':[118.67466,37.43365],
'烟台':[121.44801,37.46353],
'潍坊':[119.16176,36.70686],
'济宁':[116.58724,35.41459],
'泰安':[117.0884,36.19994],
'威海':[122.12171,37.51348],
'日照':[119.52719,35.41646],
'莱芜':[117.67667,36.21359],
'临沂':[118.35646,35.10465],
'德州':[116.35927,37.4355],
'聊城':[115.98549,36.45702],
'滨州':[117.97279,37.38211],
'菏泽':[115.48115,35.23363],
'郑州':[113.62493,34.74725],
'开封':[114.30731,34.79726],
'洛阳':[112.45361,34.61812],
'平顶山':[113.19241,33.76609],
'安阳':[114.3931,36.09771],
'鹤壁':[114.29745,35.747],
'新乡':[113.92675,35.30323],
'焦作':[113.24201,35.21563],
'濮阳':[115.02932,35.76189],
'许昌':[113.85233,34.0357],
'漯河':[114.01681,33.58149],
'三门峡':[111.2003,34.77261],
'南阳':[112.52851,32.99073],
'商丘':[115.65635,34.41427],
'信阳':[114.09279,32.14714],
'周口':[114.69695,33.62583],
'驻马店':[114.02299,33.01142],
'武汉':[114.30525,30.59276],
'黄石':[115.0389,30.19953],
'十堰':[110.79801,32.62918],
'宜昌':[111.28642,30.69186],
'襄阳':[112.12255,32.009],
'鄂州':[114.89495,30.39085],
'荆门':[112.19945,31.03546],
'孝感':[113.91645,30.92483],
'荆州':[112.24069,30.33479],
'黄冈':[114.87238,30.45347],
'咸宁':[114.32245,29.84126],
'随州':[113.38262,31.69013],
'恩施':[109.48817,30.27217],
'长沙':[112.93886,28.22778],
'株洲':[113.13396,27.82767],
'湘潭':[112.94411,27.82975],
'衡阳':[112.57195,26.89324],
'邵阳':[111.4677,27.2389],
'岳阳':[113.12919,29.35728],
'常德':[111.69854,29.03158],
'张家界':[110.47839,29.11667],
'益阳':[112.35516,28.55391],
'郴州':[113.01485,25.77063],
'永州':[111.61225,26.42034],
'怀化':[110.0016,27.56974],
'娄底':[111.99458,27.69728],
'湘西':[109.73893,28.31173],
'广州':[113.26436,23.12908],
'韶关':[113.59723,24.81039],
'深圳':[114.05956,22.54286],
'珠海':[113.57668,22.27073],
'汕头':[116.68221,23.3535],
'佛山':[113.12192,23.02185],
'江门':[113.08161,22.57865],
'湛江':[110.35894,21.27134],
'茂名':[110.92523,21.66329],
'肇庆':[112.46528,23.0469],
'惠州':[114.41679,23.11075],
'梅州':[116.12264,24.28844],
'汕尾':[115.37514,22.78566],
'河源':[114.70065,23.74365],
'阳江':[111.98256,21.85829],
'清远':[113.05615,23.68201],
'东莞':[113.75181,23.02069],
'中山':[113.3926,22.51595],
'潮州':[116.62296,23.6567],
'揭阳':[116.37271,23.54972],
'云浮':[112.04453,22.91525],
'南宁':[108.3669,22.81673],
'柳州':[109.41552,24.32543],
'桂林':[110.29002,25.27361],
'梧州':[111.27913,23.47703],
'北海':[109.12008,21.48112],
'防城港':[108.35472,21.68713],
'钦州':[108.65431,21.9797],
'贵港':[109.59764,23.11306],
'玉林':[110.18098,22.65451],
'百色':[106.61838,23.90216],
'贺州':[111.56655,24.40346],
'河池':[108.0854,24.69291],
'来宾':[109.22238,23.7521],
'崇左':[107.36485,22.37895],
'海口':[110.19989,20.04422],
'三亚':[109.51209,18.25248],
'三沙':[112.33356,16.83272],
'成都':[104.06476,30.5702],
'自贡':[104.77844,29.3392],
'攀枝花':[101.71872,26.58228],
'泸州':[105.44257,28.8717],
'德阳':[104.3979,31.12679],
'绵阳':[104.6796,31.46751],
'广元':[105.84357,32.43549],
'遂宁':[105.59273,30.53286],
'内江':[105.05844,29.58015],
'乐山':[103.76539,29.55221],
'南充':[106.11073,30.83731],
'眉山':[103.84851,30.07563],
'宜宾':[104.6417,28.7513],
'广安':[106.63322,30.45596],
'达州':[107.46791,31.20864],
'雅安':[103.0398,30.01543],
'巴中':[106.74733,31.86715],
'资阳':[104.62798,30.12859],
'阿坝':[102.22477,31.8994],
'甘孜':[101.96254,30.04932],
'凉山':[102.26746,27.88164],
'贵阳':[106.63024,26.64702],
'六盘水':[104.83023,26.59336],
'遵义':[106.92723,27.72545],
'安顺':[105.9462,26.25367],
'毕节':[105.30504,27.29847],
'铜仁':[109.18099,27.69066],
'黔西南':[104.90437,25.08988],
'黔东南':[107.98416,26.58364],
'黔南':[107.52226,26.25427],
'昆明':[102.83322,24.87966],
'曲靖':[103.79625,25.49002],
'玉溪':[102.5466,24.35193],
'保山':[99.16181,25.11205],
'昭通':[103.7168,27.33817],
'丽江':[100.2271,26.85648],
'普洱':[100.96624,22.82521],
'临沧':[100.08884,23.88426],
'楚雄':[101.52767,25.04495],
'红河':[103.3756,23.36422],
'文山':[104.21504,23.39849],
'西双版纳':[100.79739,22.00749],
'大理':[100.26764,25.60648],
'德宏':[98.58486,24.43232],
'怒江':[98.8567,25.81763],
'迪庆':[99.70305,27.81908],
'拉萨':[91.1145,29.64415],
'日喀则':[88.88116,29.26705],
'昌都':[97.17225,31.14073],
'山南':[91.77313,29.23705],
'那曲':[92.05136,31.47614],
'阿里':[81.1454,30.40051],
'林芝':[94.36155,29.64895],
'西安':[108.93984,34.34127],
'铜川':[108.94515,34.89673],
'宝鸡':[107.23732,34.36194],
'咸阳':[108.70929,34.32932],
'渭南':[109.51015,34.49997],
'延安':[109.48978,36.58529],
'汉中':[107.02377,33.06761],
'榆林':[109.73458,38.2852],
'安康':[109.02932,32.68486],
'商洛':[109.94041,33.87036],
'兰州':[103.83417,36.06138],
'嘉峪关':[98.29011,39.77201],
'金昌':[102.18759,38.52006],
'白银':[104.13773,36.5447],
'天水':[105.72486,34.58085],
'武威':[102.63797,37.9282],
'张掖':[100.44981,38.92592],
'平凉':[106.6653,35.54303],
'酒泉':[98.49394,39.73255],
'庆阳':[107.64292,35.70978],
'定西':[104.62524,35.58113],
'陇南':[104.92166,33.401],
'临夏':[103.21091,35.60122],
'甘南':[102.91102,34.98327],
'西宁':[101.77782,36.61729],
'海东':[102.40173,36.48209],
'海北':[100.90096,36.95454],
'黄南':[102.01507,35.51991],
'海南':[100.62021,36.28643],
'果洛':[100.24475,34.47141],
'玉树':[97.0065,33.00528],
'海西':[97.37122,37.3771],
'银川':[106.23248,38.48644],
'石嘴山':[106.38418,38.9841],
'吴忠':[106.19879,37.99755],
'固原':[106.24259,36.0158],
'中卫':[105.19676,37.50026],
'乌鲁木齐':[87.61688,43.82663],
'克拉玛依':[84.88927,45.57999],
'吐鲁番':[89.18954,42.9513],
'哈密':[93.51626,42.81874],
'昌吉':[87.30822,44.01117],
'博州':[82.06665,44.90597],
'巴州':[86.14517,41.76404],
'阿克苏':[80.26008,41.16842],
'克州':[76.16661,39.7153],
'喀什':[75.98976,39.47042],
'和田':[79.92247,37.11431],
'伊犁':[81.32416,43.91689],
'塔城':[82.98046,46.74532],
'阿勒泰':[88.14023,47.84564],
'澳门':[113.54294,22.18684]
}


[b]加载插件[/b]

//= require echarts.min
//= require echarts/china
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值