1. 小应用设计
1.1. 包含自定义存储过程的程序
通过一个实例介绍如何实现前端定义存储过程,并用js实现调用。
需求是:
通过当前经纬度和选择的所在城市获取附近门店
实现方式:
首先前端JavaScript 得到相应的参数,然后后端返回门店信息,并根据模板填充数据。
1.1.1. HTML模板定义
本例以手机端为例,所以只有手机模板
<table style="width: 100%;height: 50px;border: 1px solid #E2E6E7;">
<tbody>
<tr class="firstRow">
<td style="width:3%;padding-bottom: 6px; border-bottom: none;">
<em class="iconfont icon-YW-093" style="line-height: 30px;margin-left: 5px;padding-right:3px"></em>
</td>
<td style="width:89%;padding-right:10px; border-bottom: none;">
<select class="data" id="haha" style="color:#282828;padding-left: 2px;padding-top:5px;padding-bottom:10px;width:100%;font-size:14px!important;"><option value="0" id="currentLocation">
定位中
</option></select>
</td>
<td style="width:20px;color: #ebebeb; border-bottom: none; margin-top: 0px;">
<div class="arrow"></div>
</td>
</tr>
</tbody>
</table>
<div style="background-color:#ebebeb;height:8px"></div>
<table id="tb_shopinfo" nopopmenu="0" name="lists" class="tablebottomline excel" cellspacing="0" cellpadding="0" border="0" ord2tag="1" caption="待外呼" group="门店列表" style=";width:100%">
<tbody name="details" class="mynone">
<tr value="{ord_id}" class="firstRow" latitude="{ord_wd2}" longitude="{ord_jd2}" address="{ord_dpdz}" style="margin-top: 0px;">
<td style="padding-left: 20px;padding-top:15px;padding-bottom:10px;" onclick="wxnav(this)">
<div style="font-size: 14px!important;">
{ord_dpmc1}
</div>
<div class="f14" style="color:#BEBEBE;margin-top: 10px;">
<span style="font-size: 12px!important;padding-right:5px;width:40px;background: #ebebeb;padding-left: 8px;border-radius: 10px;padding-top: 1px;padding-bottom: 1px;margin-right: 10px;" id="distance">{ord_distance1}km</span><span style="font-size: 12px!important;padding-left: 3px;color:#adadac;">{ord_dpdz}</span>
</div>
</td>
<td style="width:20px;" onclick="wxnav(this)">
<div class="arrow"></div>
</td>
</tr>
</tbody>
</table>
<p>
<br/>
</p>
1.1.2. CSS规则
主要取消select 的默认样式
select {
/*Chrome和Firefox里面的边框是不一样的,所以复写了一下onclick="wxnav(this)"*/
border: solid 0px #000;
/*很关键:将默认的select选择框样式清除*/
appearance:none;
-moz-appearance:none;
-webkit-appearance:none;
/*在选择框的最右侧中间显示小箭头图片*/
background: url("") no-repeat scroll right center transparent;
/*为下拉小箭头留出一点位置,避免被文字覆盖*/
padding-right: 0px;
}
/*清除ie的默认选择框样式清除,隐藏下拉箭头*/
select::-ms-expand { display: none; }
.nearby-stores-add{
width:12px;
margin-right:5px;
display:inline-block;
position: absolute;
left: 14px;
top: 14px;
}
.arrow:after {
content: " ";
display: block;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
height: 8px;
width: 8px;
border-width: 2px 2px 0 0;
border-color: #c8c8cd;
border-style: solid;
position: relative;
top: -2px;
top: -1px;
margin-left: .3em
}
1.1.3. 存储过程定义
sql代码如下,如下格式的sql 代码提交后会在后台数据库生成名为“userfunc_?_shopinfo”的存储过程。其中shopinfo是自己定义的方法名,JavaScript中可以直接调用,但是需要注意的是JavaScript的参数需要逐个给出,即“paramA,paramB...”的形式,而不能用json格式。
/*根据经纬度或城市名获取门店*/
function shopinfo(@longtitude varchar(100),@latitude varchar(100),@city varchar(100))
begin
select top 20 cast(ROUND(ord_distance,2)as numeric(6,2)) ord_distance1,* from (select ROUND( dbo.fn_GetDistance(CONVERT (decimal(10,6),(@longtitude)),CONVERT (decimal(10,6),@latitude),ord_jd2,ord_wd2) ,2) ord_distance,ord_dpmc ord_dpmc1,* from order_188
where ord_wd2 is not null and ord_dpzt ='正常营业' and ord_cs like @city
union all
select ROUND( dbo.fn_GetDistance(CONVERT (decimal(10,6),(@longtitude)),CONVERT (decimal(10,6),@latitude),ord_jd2,ord_wd2),2) ord_distance,SUBSTRING(ord_dpmc,1,CHARINDEX('(',ord_dpmc)-1) +
SUBSTRING(ord_dpmc,len(ord_dpmc)-CHARINDEX(')',reverse(ord_dpmc))+2,100)+'(暂停)' ord_dpmc1,* from order_188 ) t
where ord_wd2 is not null and ord_dpzt ='暂停营业' and ord_dpmc like '(%' and ord_cs like @city) t order by t.ord_distance
end
/*城市信息*/
function citys(@longtitude varchar(100))
begin
select ROW_NUMBER() over(order by ord_cs) id,ord_cs from order_188 group by ord_cs having ord_cs !=''
end
所有的SQL代码都会生成如下结构的前端代码,并注入到页面,所以JavaScript代码可以直接使用如下的一些方法(以shopinfo为例)
var _t_ = document.location.search.substr(1);
var shopinfo = {};
shopinfo.runsql = function(longtitude, latitude, city, __c1) {
runsql('userfunc_583_shopinfo&' + _t_, {
ctgid: rsc_ctgid,
objtype: rsc_type,
ctgid2: rsc_ctg2id,
objid: rsc_id,
longtitude: longtitude,
latitude: latitude,
city: city
}, function(__io, __dd) {
if (__c1)
__c1(__io, __dd);
});
}
shopinfo.runsql4xml = function(longtitude, latitude, city, __c1) {
runsql4xml('userfunc_583_shopinfo&' + _t_, {
ctgid: rsc_ctgid,
objtype: rsc_type,
ctgid2: rsc_ctg2id,
objid: rsc_id,
longtitude: longtitude,
latitude: latitude,
city: city
}, function(__io, __dd, __nn) {
if (__c1)
__c1(__io, __dd, __nn);
});
}
shopinfo.loadata = function(__$j, longtitude, latitude, city, __f1, __c1) {
loaddata(__$j, 'userfunc_583_shopinfo&' + _t_, {
ctgid: rsc_ctgid,
objtype: rsc_type,
ctgid2: rsc_ctg2id,
objid: rsc_id,
longtitude: longtitude,
latitude: latitude,
city: city
}, __f1, __c1);
}
shopinfo.dialog = function(longtitude, latitude, city, __c1, __t1, __m1, __w1) {
pickany_user(__w1, '', __t1, 'userfunc_583_shopinfo', 'longtitude=' + tohex(longtitude) + '&' + 'latitude=' + tohex(latitude) + '&' + 'city=' + tohex(city), __c1, __m1);
}
shopinfo.table = function(__t1, longtitude, latitude, city, __f1, __c1, __c2) {
mytable(__t1, 'userfunc_583_shopinfo&' + 'longtitude=' + tohex(longtitude) + '&' + 'latitude=' + tohex(latitude) + '&' + 'city=' + tohex(city), __f1, 10, 20, __c1, __c2);
}
需要说明的是,shopinfo.table 中的__c1回调,接收两个参数,第一个参数无意义,第二个参数dataset为当前查询返回的xml的DOM对象。该回调只执行一次。如需要每行数据执行一次自己的逻辑,可以在回调中继续调用
dataseteach(data,function(iseof,dataset,dsname){ /*使用方法如runsql4xml的回调*/ })另附两点计算距离代码
SET ANSI_NULLS ON GO SET ANSI_NULLS ON GO create FUNCTION dbo.fn_GetDistance ( @LngBegin REAL, @LatBegin REAL, @LngEnd REAL, @LatEnd REAL ) RETURNS FLOAT AS BEGIN DECLARE @Distance REAL DECLARE @EARTH_RADIUS REAL SET @EARTH_RADIUS = 6378.137 --地球半径 已经是除以1000的值,所以后面计算出来的是千米及公里 DECLARE @RadLatBegin REAL, @RadLatEnd REAL, @RadLatDiff REAL, @RadLngDiff REAL SET @RadLatBegin = @LatBegin * PI() / 180.0 SET @RadLatEnd = @LatEnd * PI() / 180.0 SET @RadLatDiff = @RadLatBegin - @RadLatEnd SET @RadLngDiff = @LngBegin * PI() / 180.0 - @LngEnd * PI() / 180.0 SET @Distance = 2 * ASIN(SQRT(POWER(Sin(@RadLatDiff / 2), 2) + COS(@RadLatBegin) * COS(@RadLatEnd) * POWER(SIN(@RadLngDiff/2),2))) SET @Distance = @Distance * @EARTH_RADIUS --SET @Distance = Round(@Distance * 10000) / 10000 RETURN @Distance END GO
1.1.4. 调用
/*获取*/
function getShopInfoByLocation(){
loading(true);
_pobj2.wx.ready(function(){
_pobj2.getLocation(function(long,lati,addr){
$("#currentLocation").html(addr.substring(0,18)+".....");
shopinfo.table("tb_shopinfo",long,lati,'%');
citys.runsql4xml('100.11',function(iseof,date,dsname){
if(iseof==false&&dsname=="t1"){
var id = $f[_id];
var ord_cs = $f[_ord_cs]
$("#haha").append('<option value="'+id+'"><span onclick="" style="line-height: 30px;margin-left:5px">'+ord_cs+'</span></option>')
loading(false);
}
});
});
});
}
/*微信导航*/
function wxnav(obj){
var res ={};
var ctr = $(obj).parents("tr").first();
res.longitude = myparseFloat(ctr.attr("longitude"),0);
res.latitude = myparseFloat(ctr.attr("latitude"),0);
res.address = ctr.attr("address");
//使用微信内置地图查看位置接口
_pobj2.wx.openLocation({
latitude : res.latitude, // 纬度,浮点数,范围为90 ~ -90
longitude :res.longitude, // 经度,浮点数,范围为180 ~ -180。
name : '目标位置', // 位置名
address : res.address, // 地址详情说明
scale : 28, // 地图缩放级别,整形值,范围从1~28。默认为最大
infoUrl : '' // 在查看位置界面底部显示的超链接,可点击跳转(测试好像不可用)
});
}
/*位置发生了改变,刷新数据*/
$(".data").bind("change",function(){
_pobj2.getLocation(function(long,lati,addr){
var obj = $("#haha option:selected");
var val = obj.val();
var text = obj.text();
if(val!="0"){
shopinfo.table("tb_shopinfo",long,lati,text);
}else{
shopinfo.table("tb_shopinfo",long,lati,'%');
}
})
});
window.onload = function(){getShopInfoByLocation();}
function autorunwhilecacheloaded()
{
getShopInfoByLocation();
}
1.1.5. 菜单配置
手机微信
参数:
appid=微信ID
redirect_uri=http%3A%2F%2F域名%2Fwxmain
state=gzh|qyh.autostate??,具体参见mps_weixinstate的wxs_code字段
手机钉钉
电脑
菜单url:/commons/prg_应用ID