订餐系统之按距离[根据经纬度]排序、搜索

  上周六,写了第一篇博客《订餐系统之权限设计》,在此感谢那些鼓励、关注我的园友们,更要感谢那些提出宝贵建议的朋友们。看了你们的评论,才真切的感受到:朋友们的评论往往会让文章更有看点。上篇文章中
郑明人生就是赌 等几个园友的留言让我对我们系统的权限优化有了方向。当然,这样的优化肯定不是一天两天的事,做技术的朋友应该都知道:一个难题经常啃啃,某天也许就有了好的方案了(近段时间啃掉了几个2、3年前未处理好的的问题,才想起初中数学老师让我们经常啃一些竞赛题的良苦用心),今天的文章说的就是一个从2010年就想优化,但一直未优化好的功能,也从
幸福框架的评论中,看到了他的博客,更是从他博客的留言中,找到了处理:按日期+6位顺序号生成订单编号(主要处理并发的情况)的方案,之前有客户要这样生成订单编号,我只能回复实现不了,因为当时只知道,每次获取最大的订单编号,处理不了并发的情况,惭愧。

  关于这个标题,我还是交代下背景吧。这个问题从2010年第一次实现时,就觉得当时那种方案太差了,自己都看不去,只因没有别的办法,从那以后,每每得空,就拿出来琢磨下,现在这个方案也许还有不少问题,也希望各位指点下。我们是做订餐系统的,主要实体就是商家(有坐标)和用户(有坐标)。所以就有这么个需求,返回距离N公里内的商家,按距离从近到远排序。先看下,数据库设计吧,如图(1):

图(1)

  下面我先介绍下这几个表的关系吧:

    ETogo :商家表,dataid表示商家编号,togoname表示商家名称。

    ETogoLocalInfo:商家定位表,togoid对应etogo.dataid,lat表示商家纬度,lng表示商家经度(经纬度在地图上标注所得)

EAddress :用户地址表,保存用户的经纬度,lat表示用户纬度,lng表示用户经度(经纬度在地图上标注所得)

   生活的经验告诉我们:一条成功的路,背后总有数不完的错误的路。下面我把那些曾经错误的路也写下来,以作对比。

2010年方案

  当时年少,对sql基本只会简单的select,更多的东西依赖于应用程序,于是有了下面的代码,由于对第二页的处理不了,所以用了方法:getDistancetogoid获取前N页的id然后再处理,里面关于距离的语句每次同事用到都抱怨,如果再加的N公里内的,这个语句就麻烦了。

        /// <summary>
        /// 获取列表,返回距离排序(出现商家重复的现象目前不采用)
        /// </summary>
        /// <param name="pagesize">每页大小</param>
        /// <param name="pageindex">当前页数</param>
        /// <param name="strWhere">搜索条件</param>
        /// <param name="orderName">排序字段</param>
        /// <param name="orderType">排序类型</param>
        /// <param name="mylat">用户纬度</param>
        /// <param name="mylng">用户经度</param>
        /// <returns></returns>
        public IList<TogoInfo> GetDistanceList(int pagesize, int pageindex, string strWhere, string orderName, int orderType, string mylat, string mylng)
        {
            IList<TogoInfo> infos = new List<TogoInfo>();
            string ids = "";
            if (pageindex > 1)
            {
                ids = getDistancetogoid(pagesize, pageindex, strWhere, orderName, orderType, mylat, mylng);
                if (ids == "")
                {
                    return infos;
                }
            }
            SqlParameter[] parameters =
            {
                new SqlParameter("@tblName", SqlDbType.VarChar,255),
                new SqlParameter("@strGetFields", SqlDbType.VarChar,2000),
                new SqlParameter("@primary", SqlDbType.VarChar,255),
                new SqlParameter("@orderName", SqlDbType.VarChar,255),
                new SqlParameter("@PageSize", SqlDbType.Int),
                new SqlParameter("@PageIndex", SqlDbType.Int),
                new SqlParameter("@OrderType", SqlDbType.Bit),
                new SqlParameter("@strWhere", SqlDbType.VarChar,4500),
                new SqlParameter("@ids", SqlDbType.VarChar,2000)
            };
            string orderstr = orderType > 0 ? "desc" : "asc";
            parameters[0].Value = "etogo";
            string field = "*, (select Lat from ETogoLocalInfo where togoid = etogo.dataid) as lat ,(select lng from ETogoLocalInfo where togoid = etogo.dataid) as lng, (select lastlogindate from ETogoPrinter where ETogoPrinter.togoid =  etogo.dataid ) lastlogindate,(select (Case when DateDiff(mi,LastLoginDate,getdate()) < 5 then 1 else 0 end) from etogoprinter where ETogoPrinter.togoid =  etogo.dataid)  as online";
            field += ",(( 6371 * acos( cos( radians(" + mylat + ") ) * cos( radians( (select Lat from ETogoLocalInfo where togoid = etogo.dataid) )) * cos( radians( (select lng from ETogoLocalInfo where togoid = etogo.dataid) ) - radians(" + mylng + ") ) + sin( radians(" + mylat + ") ) * sin( radians( (select Lat from ETogoLocalInfo where togoid = etogo.dataid) ) ) ) )) as Distance ";
            field += " ,CASE WHEN( ( CONVERT(varchar(12) , Time1Start, 114 ) < CONVERT(varchar(12) , getdate(), 114 )";
            field += "and CONVERT(varchar(12) , Time1End, 114 ) > CONVERT(varchar(12) , getdate(), 114 )";
            field += ") or  ( CONVERT(varchar(12) , Time2Start, 114 ) < CONVERT(varchar(12) , getdate(), 114 )";
            field += "and CONVERT(varchar(12) , Time2End, 114 ) > CONVERT(varchar(12) , getdate(), 114 )";
            field += ") )THEN 1 ELSE 0 END AS havenew ";

            parameters[1].Value = field;
            parameters[2].Value = "DataID";
            parameters[3].Value = orderName;
            parameters[4].Value = pagesize;
            parameters[5].Value = pageindex;
            parameters[6].Value = orderType;
            parameters[7].Value = strWhere;
            parameters[8].Value = ids;
            using (SqlDataReader dr = SQLHelper.ExecuteReader(CommandType.StoredProcedure, "pageselectpri_togo", parameters))
            {
                while (dr.Read())
                {
                    TogoInfo info = new TogoInfo();
                    info.DataID = HJConvert.ToInt32(dr["DataID"]);
                    info.Picture = HJConvert.ToString(dr["Picture"]);
                    info.TogoName = HJConvert.ToString(dr["TogoName"]);
                    int isonline = HJConvert.ToInt32(dr["havenew"]);

                    if (togostatus == 1 && isonline == 1)
                    {
                        info.Status = 1;
                    }
                    else
                    {
                        info.Status = 0;
                    }
                    string _distance = HJConvert.ToString(dr["Distance"]);

                    if (mylat == "0" || _distance == "")
                    {
                        info.mydistance = "0";
                    }
                    else
                    {
                        info.mydistance = Convert.ToString(Convert.ToInt32(Convert.ToDecimal(_distance) * 1000));
                    }

                    info.Lat = HJConvert.ToString(dr["Lat"]);
                    if (info.Lat == "")
                    {
                        info.Lat = "0";
                    }
                    info.Lng = HJConvert.ToString(dr["Lng"]);
                    if (info.Lng == "")
                    {
                        info.Lng = "0";
                    }

                    infos.Add(info);
                }
            }
            return infos;
        }

        /// <summary>
        /// 获取所有商家的名称和对应的编号
        /// </summary>
        /// <param name="pagesize">每页大小</param>
        /// <param name="pageindex">当前页数</param>
        /// <param name="strWhere">搜索条件</param>
        /// <param name="orderName">排序字段</param>
        /// <param name="orderType">排序类型</param>
        /// <param name="mylat">用户纬度</param>
        /// <param name="mylng">用户经度</param>
        public string getDistancetogoid(int pagesize, int pageindex, string sqlwhere, string sortname, int ordertype, string mylat, string mylng)
        {
            string ids = "";
            string orderstr = ordertype > 0 ? "desc" : "asc";
            int top = (pageindex - 1) * pagesize;
            string field = "select top " + top + " dataid";
            field += ",(( 6371 * acos( cos( radians(" + mylat + ") ) * cos( radians( (select Lat from ETogoLocalInfo where togoid = etogo.dataid) )) * cos( radians( (select lng from ETogoLocalInfo where togoid = etogo.dataid) ) - radians(" + mylng + ") ) + sin( radians(" + mylat + ") ) * sin( radians( (select Lat from ETogoLocalInfo where togoid = etogo.dataid) ) ) ) )) as Distance ";
            field += " from etogo where " + sqlwhere + " order by " + sortname + " " + orderstr + " , dataid desc";
            using (SqlDataReader dr = SQLHelper.ExecuteReader(CommandType.Text, field, null))
            {
                while (dr.Read())
                {
                    ids += dr["dataid"] + ",";
                }
            }
            ids = System.Text.RegularExpressions.Regex.Replace(ids, @",$", "");
            return ids;
        }

dal层代码

以下是代码中用到的分页存储过程:pageselectpri_togo

CREATE   PROCEDURE [dbo].[pageselectpri_togo]

@tblName varchar(255),       -- 表名

@strGetFields varchar(1000) = ‘*‘,  -- 需要返回的列 

@primary varchar(255)=‘‘,      -- 主键的字段名

@orderName varchar(255)=‘‘,        --要排序的字段名

@PageSize   int = 10,          -- 页尺寸

@PageIndex  int = 1,           -- 页码

@OrderType bit = 0,  -- 设置排序类型, 非 0 值则降序

@strWhere  varchar(1500) = ‘‘,  -- 查询条件 (注意: 不要加 where)
@ids varchar(2000) 

AS

declare @strSQL   varchar(5000)       -- 主语句

declare @strTmp   varchar(110)        -- 临时变量

declare @strOrder varchar(400)        -- 排序类型

if @OrderType != 0

begin

    set @strTmp = ‘ not in (select ‘

    set @strOrder = ‘ order by ‘ + @orderName +‘ desc‘

    if @orderName <> @primary
    begin
        set @strOrder = @strOrder + ‘,[‘ + @primary +‘] desc‘
    end
    --如果@OrderType不是0,就执行降序,这句很重要!

end

else

begin

    set @strTmp = ‘ not in (select ‘

    set @strOrder = ‘ order by ‘ + @orderName +‘ asc‘

    if @orderName <> @primary
    begin
        set @strOrder = @strOrder + ‘,[‘ + @primary +‘] asc‘
    end

end

if @PageIndex = 1

begin

    if @strWhere != ‘‘   

    set @strSQL = ‘select top ‘ + str(@PageSize) +‘ ‘+@strGetFields+ ‘  from [‘ + @tblName + ‘] where ‘ + @strWhere + ‘ ‘ + @strOrder

     else

     set @strSQL = ‘select top ‘ + str(@PageSize) +‘ ‘+@strGetFields+ ‘  from [‘+ @tblName + ‘] ‘+ @strOrder

--如果是第一页就执行以上代码,这样会加快执行速度

end

else--后面的页数

begin

--以下代码赋予了@strSQL以真正执行的SQL代码

set @strSQL = ‘select top ‘ + str(@PageSize) +‘ ‘+@strGetFields+ ‘  from [‘

    + @tblName + ‘] where [‘ + @primary + ‘]‘ + @strTmp + ‘[‘+ @primary + ‘] from (select top ‘ 

    + str((@PageIndex-1)*@PageSize) + ‘ [‘+ @primary + ‘] from [‘ + @tblName + ‘]) as tblTmp)‘+ @strOrder

if @strWhere != ‘‘

    set @strSQL = ‘select top ‘ + str(@PageSize) +‘ ‘+@strGetFields+ ‘  from [‘

        + @tblName + ‘] where [‘ + @primary + ‘] not in ( ‘+@ids+‘ ) and ‘ + @strWhere + ‘ ‘ + @strOrder

end 

exec (@strSQL)

分页存储过程

此方案用时基本没有问题,但是就是太麻烦了,一个不留神,sql语句就拼错了。

2011年方案

  从那时实现了之前的方案后,后面的项目都沿用,每每用起时,心中总会不痛快,于是开始经常关注这个,一次机会看到了下面的代码(之前一篇博客中看到的,已太久了,记不起出处了,哪位看到别介意),这个方案中也是大量拼接sql,很容易就出错了,另外,对最后一页还要做特别的处理,只因可以用一个方法(2010年方案要用两个方法,查两次数据库)实现,就放到项目中了,后来,经常有重复的商家,或者有些未显示出来,于是部分项目又用了2010年的方案,那个是麻烦,但至少没有错误。

        /// <summary>
        /// 获取列表,返回距离排序
        /// </summary>
        /// <param name="pagesize">每页大小</param>
        /// <param name="pageindex">当前页数</param>
        /// <param name="strWhere">搜索条件</param>
        /// <param name="orderName">排序名称</param>
        /// <param name="orderType">排序类型</param>
        /// <param name="mylat">用户纬度</param>
        /// <param name="mylng">用户经度</param>
        /// <returns></returns>
        public IList<TogoInfo> GetDistanceList(int pagesize, int pageindex, string strWhere, string orderName, int orderType, string mylat, string mylng)
        {
            IList<TogoInfo> infos = new List<TogoInfo>();

            StringBuilder sb = new StringBuilder();

            string distancepstr = "(( 6371 * acos( cos( radians(" + mylat + ") ) * cos( radians( (b.lat) )) * cos( radians( (b.lng) ) - radians(" + mylng + ") ) + sin( radians(" + mylat + ") ) * sin( radians( ( b.Lat) ) ) ) )) as Distance ";
            int endrow = pagesize * pageindex;

            string ordertype = orderType == 1 ? "desc" : "asc";
            string _ordertype = orderType == 0 ? "desc" : "asc";

            sb.Append("select a.* ,b.* ,");
            sb.Append(distancepstr);
            string field = " CASE WHEN( ( CONVERT(varchar(12) , Time1Start, 114 ) < CONVERT(varchar(12) , getdate(), 114 )";
            field += "and CONVERT(varchar(12) , Time1End, 114 ) > CONVERT(varchar(12) , getdate(), 114 )";
            field += ") or  ( CONVERT(varchar(12) , Time2Start, 114 ) < CONVERT(varchar(12) , getdate(), 114 )";
            field += "and CONVERT(varchar(12) , Time2End, 114 ) > CONVERT(varchar(12) , getdate(), 114 )";
            field += ") )THEN 1 ELSE 0 END AS havenew";
            sb.Append(" , "+ field);
            sb.Append(" from etogo as a left join  ETogoLocalInfo as b  on a.dataid = b.togoid ");
            sb.Append("  where  a.dataid in ");
            sb.Append(" ( select top " + pagesize + " dataid from  ");
            sb.Append(" (select top " + endrow + " a.dataid , " + distancepstr + ",sortnum  from  etogo as a left join  ETogoLocalInfo as b  on a.dataid = b.togoid where " + strWhere);
            sb.Append("  order by  " + orderName + " " + ordertype + "" + " ,a.dataid  desc ) as mytepm ");
            sb.Append("  order by  " + orderName + " " + _ordertype + "" + ", dataid asc )");
            sb.Append(" order by  " + orderName + " " + ordertype + "" + ",    a.dataid desc ");

            //Hangjing.Common.HJlog.toLog(sb.ToString());

            using (SqlDataReader dr = SQLHelper.ExecuteReader(CommandType.Text,sb.ToString(), null))
            {
                while (dr.Read())
                {
                    TogoInfo info = new TogoInfo();
                    info.DataID = HJConvert.ToInt32(dr["DataID"]);
                    info.Picture = HJConvert.ToString(dr["Picture"]);
                    info.TogoName = HJConvert.ToString(dr["TogoName"]);
                    int togostatus = HJConvert.ToInt32(dr["Status"]);
                    int isonline = HJConvert.ToInt32(dr["havenew"]);

                    if (togostatus == 1 && isonline == 1)
                    {
                        info.Status = 1;
                    }
                    else
                    {
                        info.Status = 0;
                    }
                    info.mydistance = HJConvert.ToString(dr["Distance"]);

                    if (info.mydistance == "")
                    {
                        info.mydistance = "-1";
                    }
                    info.Lat = HJConvert.ToString(dr["Lat"]);
                    info.Lng = HJConvert.ToString(dr["Lng"]);

                    infos.Add(info);
                }
            }
            return infos;
        }

dal层代码

2013年方案

终于有一次再也忍受不了了,于是下定决心要优化(当然,就我目前的水平,想到的更多还是方便书写)了,当前就想了一点,不在程序中拼接距离的sql语句。经过多次修改,于是有了下面的代码:

-- =============================================
-- Author:        jijunjian
-- Create date: 2013-5-7
-- Description:    获取商家列表(含坐标,按距离排序)
-- 调用 EXEC ETogo_GetShopListWithDistance 10,1,‘distance‘,‘asc‘,‘1=1‘,‘30.313035‘,‘120.390998‘,‘distance<1‘
-- =============================================
CREATE PROCEDURE [dbo].[ETogo_GetShopListWithDistance]
@pagesize int,          --分页大小
@pageindex int,         --页码
@orderfield varchar(20),--排序字段名称
@ordertype varchar(5),  --排序类别 desc asc
@where varchar(2000),     --查询条件
@lat VARCHAR(50),--用户纬度
@lng VARCHAR(50),--用户经度,
@otherwhere VARCHAR(2000)--这个条件是用来判断距离,及根据营业时间的状态条件
AS
DECLARE @startRow int,
        @endRow    int,
        @sql varchar(4000),
        @ordername varchar(200)--排序字段

SET    @ordername = ‘( 6371 * acos( cos( radians(‘ + @lat + ‘) ) * cos( radians( Lat )) * cos( radians( lng ) - radians(‘ + @lng + ‘) ) + sin( radians(‘ + @lat + ‘) ) * sin( radians( Lat ) ) ) )‘

IF @otherwhere = ‘‘
    SET @otherwhere = ‘1=1‘

SET @startRow = (@pageindex - 1) * @pagesize + 1
SET @endRow = @startRow + @pagesize - 1
SET @sql = ‘
  SELECT * FROM
  (
    select *,row_number() over(order by  ‘+@orderfield+‘ ‘+@ordertype+‘) as [rowid] from
    (
        select ‘+@ordername+‘ as distance,dbo.ETogo.*,ETogoLocalInfo.Lat,ETogoLocalInfo.Lng,  

        CASE WHEN( ( CONVERT(varchar(12) , Time1Start, 114 ) < CONVERT(varchar(12) , getdate(), 114 )
                and CONVERT(varchar(12) , Time1End, 114 ) > CONVERT(varchar(12) , getdate(), 114 )
                ) or  ( CONVERT(varchar(12) , Time2Start, 114 ) < CONVERT(varchar(12) , getdate(), 114 )
                and CONVERT(varchar(12) , Time2End, 114 ) > CONVERT(varchar(12) , getdate(), 114 )
                ) )THEN 1 ELSE 0 END AS havenew

        from  etogo
        LEFT JOIN ETogoLocalInfo ON etogo.dataid=ETogoLocalInfo.togoid WHERE  ‘+ @where +‘
    ) m where ‘+ @otherwhere +‘ 

  )m2

 WHERE ROWID BETWEEN ‘+convert(varchar(5), @startRow) +‘ AND ‘+ convert(varchar(5), @endRow)+ ‘
‘
print @sql
EXEC(@sql)

存储过程

   这个方案让我们搜索N公里内的代码变得简单了 :@otherwhere 参数 设置成 :distance < n 即可了。按距离排序只用:@orderfield=‘distance’就可以了。程序中再也不用出现距离两点距离的sql语句,另一个意外收获就是让我搜索营业中的商家也变得简单了(我们营业根据商家设置的两个时间段(如:8:00-12:00 16:00-20:00)及一个状态值而定).

  以上便是此问题这几年的优化历程,当然,可能很多人对我们行业不了解,也可能我只是抽出了代码片段,很多人看了可能还是会不知所云,不过我想真正想研究这个问题的人看了,就应该能明白了。2013年的方案,可能还有不少问题,或者可以再进一步优化。希望有部分人能用到的同时 ,也能对此方案提出更多更好的意见或建议。

  成为一名优秀的程序员!

  

时间: 2024-10-06 03:41:08

订餐系统之按距离[根据经纬度]排序、搜索的相关文章

php根据经纬度排序,根据经纬度筛选距离段

SQL 语句:select location.* from (select *,round(6378.138*2*asin(sqrt(pow(sin( (36.668530*pi()/180-px_lat*pi()/180)/2),2)+cos(36.668530*pi()/180)*cos(px_lat*pi()/180)* pow(sin( (117.020359*pi()/180-px_lon*pi()/180)/2),2)))*1000) as distance from bsx_tra

微铺子点单系统详细介绍 - 争做国内最专业的微信商店平台,微信外卖订餐系统!

什么是微铺子? 微铺子是国内专业的微信点单系统,集成了外卖.点餐.订座等众多功能.通过微铺子,店家可以在微信上建立店铺,消费者只需关注店家的帐号,即可浏览商品与店家的信息,消费者关注到商家后,根据提示,进行点击点单,简单三步,15秒内,即可完成订餐.店家可以通过电脑后台.电子邮件.短信或无线打印机多种方式即时查看订单,并提供相应的服务. 微铺子系统适用于:餐饮.酒店.水果店.蛋糕店.花店.零售.超市等. 微铺子从创立到与合作商家的长期测试,再到正式投入商用,期间不断根据客户的需求完善产品,不断开

订餐系统之同步美团商家订单

引子    早上和往常一样去工商大学打球,除了今天三分比较准外,一切都还是那样的循规蹈矩. 也许股子里还有那么一些不甘平庸,总想着能改变一下如此无趣的按部就班. 转过行政楼,一波一波的学生在谈笑风生.哦,是了,又到拍毕业照片的时间了. 又是一年过去了(也不知从何时起,开始以毕业来计年了),弹指一挥间,已经在这里工作7年半了. 一份工作越是做得久,反到越羞于提起.也许是羞于现状,也是羞于未来的我吧.说不清,道不明,有点乱... 脚步也随着不安的思绪加快了频率,迅速的穿过了人群...未来还需多努力,

订餐系统之同步口碑外卖商家菜单与点点送订单

2015年饿了么.百度外卖.美团外卖.口碑外卖几家几乎分完了外卖这碗羹,让其他外卖网站几乎举步维艰,也让那些蠢蠢欲动想进入外卖领域的人犹豫不决了(这估计是要砸我饭碗的节奏啊,ヾ(@⌒ー⌒@)ノ).当然了,喝了外卖这碗羹,肯定得有“产物”,不然,还不被撑破了肚皮么.对,这个"产物"就是外卖订单,是大量的外卖订单,商户的配送员能力非常有限,于是第三方的配送公司如雨后春笋般的冒了出来,当然了,市场大,竞争也非常残酷,有些刚冒出头,就被"扼杀"在襁褓里了:估计还有不少的没找

微铺子点单系统具体介绍 - 争做国内最专业的微信商店平台,微信外卖订餐系统!

什么是微铺子? 微铺子是国内专业的微信点单系统,集成了外卖.点餐.订座等众多功能.通过微铺子,店家能够在微信上建立店铺,消费者仅仅需关注店家的帐号,就可以浏览商品与店家的信息,消费者关注到商家后,依据提示,进行点击点单,简单三步,15秒内,就可以完毕订餐.店家能够通过电脑后台.电子邮件.短信或无线打印机多种方式即时查看订单,并提供对应的服务. 微铺子系统适用于:餐饮.酒店.水果店.蛋糕店.花店.零售.超市等. 微铺子从创立到与合作商家的长期測试,再到正式投入商用,期间不断依据客户的需求完好产品,

用微信点单 订餐系统打造属于个人的O2O外卖订餐行业商业平台

首先,我不能说我是一个成功的微信达人,我也不能说我是一个优秀的互联网专家,但我就目前所使用的一套订餐系统来讲,正在逐渐的规划一个餐饮行业的商业圈! 我所使用的系统叫"微铺子订餐系统",所购买的是[豪华旗舰版],最主要的功能就是:不限制店铺个数!就是看到这点才选择的这套系统!下面我详细说一下思路. 1.建立一个独立平台官网,便于宣传平台,增加可信度.官网不用太花哨,简单明了,毕竟咱是做微信平台的,还是尽量把客户引到微信来,所以,我准备在主页只放一个大的微信二维码,提示客户,我们只针对微信

订餐系统之获取淘宝外卖订单

当时的情况是这样的:我们一个客户用了我们的订餐系统,也在淘宝外卖上开了店,但是订餐系统中的订单都要通过调度系统,根据配送员的位置,把订单发送给合适的配送员,所以要把淘宝外卖的订单加到订餐系统中(据说淘宝外卖也是因为味捷外卖才开发这个接口的). 淘宝外卖提供的接口我知道的有三个,1.获取未确认的订单:2.确认订单:3.拒绝订单.所以订餐系统要做的就是从淘宝外卖获取未确认的订单.确认订单并加入订餐系统. 开放平台地址: http://open.taobao.com/doc/api_cat_detai

www.vpuzi.cn微铺子微信订餐系统 - 餐饮O2O创业硝烟弥漫 草根创业者如何立足?

(中国电子商务研究中心讯)2014年以淘点点为代表的BAT大佬们杀入餐饮O2O市场了,当餐饮O2O市场狼烟四起.硝烟弥漫,大众点评网.美团和糯米团都在虎视眈眈,草根创业者还有没有机会呢? 中国有上千家的餐饮软件企业,他们在餐饮业扎根多年,难道这一次他们会全军覆没?餐饮O2O市场真的只是资本的战争吗?难道这些平常习惯于空中作战的大佬们深入餐饮腹地依然能够所向无敌?他们所到之处真的会寸草不生?真的会赢者通吃吗?今天,我们就来解析草根餐饮O2O创业者的发展机会. 首先,我认为,以淘点点为代表的BAT大

订餐系统

<!doctype html> <html> <head> <meta charset="utf-8"> <title>蜡笔小新订餐网</title> <link rel="shortcut icon" href="images/logo.png" /> <link rel="stylesheet" href="basic.cs