Просмотр исходного кода

!16 更新一些bug
Merge pull request !16 from 聆听/develop

聆听 7 лет назад
Родитель
Сommit
a9fa1ee8bd
35 измененных файлов с 1068 добавлено и 530 удалено
  1. 2 1
      application/admin/controller/setting/SystemGroupData.php
  2. 0 1
      application/admin/controller/store/StoreCategory.php
  3. 14 9
      application/admin/controller/store/StoreProduct.php
  4. 9 2
      application/admin/controller/system/SystemFile.php
  5. 1 1
      application/admin/controller/ump/StoreCoupon.php
  6. 8 8
      application/admin/controller/ump/StoreSeckill.php
  7. 18 0
      application/admin/model/order/StoreOrder.php
  8. 24 2
      application/admin/model/store/StoreCategory.php
  9. 1 1
      application/admin/model/store/StoreProductAttr.php
  10. 38 13
      application/admin/view/order/store_order/index.php
  11. 152 113
      application/admin/view/store/store_category/index.php
  12. 9 9
      application/admin/view/store/store_product/index.php
  13. 2 2
      application/admin/view/ump/store_combination/index.php
  14. 11 11
      application/admin/view/ump/store_seckill/index.php
  15. 1 1
      application/admin/view/ump/user_point/index.php
  16. 1 1
      application/admin/view/wechat/reply/keyword.php
  17. 4 3
      application/wap/model/store/StoreCart.php
  18. 9 21
      extend/service/WechatService.php
  19. 106 56
      public/system/css/layui-admin.css
  20. 89 50
      thinkphp/library/think/db/Builder.php
  21. 65 28
      thinkphp/library/think/db/Connection.php
  22. 48 0
      thinkphp/library/think/db/Expression.php
  23. 330 159
      thinkphp/library/think/db/Query.php
  24. 72 6
      thinkphp/library/think/db/builder/Mysql.php
  25. 9 3
      thinkphp/library/think/db/builder/Pgsql.php
  26. 9 3
      thinkphp/library/think/db/builder/Sqlite.php
  27. 28 18
      thinkphp/library/think/db/builder/Sqlsrv.php
  28. 1 1
      thinkphp/library/think/db/connector/Mysql.php
  29. 1 1
      thinkphp/library/think/db/connector/Pgsql.php
  30. 1 1
      thinkphp/library/think/db/connector/Sqlite.php
  31. 1 1
      thinkphp/library/think/db/exception/BindParamException.php
  32. 1 1
      thinkphp/library/think/db/exception/DataNotFoundException.php
  33. 1 1
      thinkphp/library/think/db/exception/ModelNotFoundException.php
  34. 1 1
      view/crmebN/pages/orders-con/orders-con.js
  35. 1 1
      view/crmebN/pages/product-con/index.wxml

+ 2 - 1
application/admin/controller/setting/SystemGroupData.php

@@ -109,7 +109,8 @@ class SystemGroupData extends AuthController
         foreach ($params as $key => $param) {
         foreach ($params as $key => $param) {
             foreach ($Fields['fields'] as $index => $field) {
             foreach ($Fields['fields'] as $index => $field) {
                 if($key == $field["title"]){
                 if($key == $field["title"]){
-                    if($param == "" || count($param) == 0)
+//                    if($param == "" || count($param) == 0)
+                    if($param == "")
                         return Json::fail($field["name"]."不能为空!");
                         return Json::fail($field["name"]."不能为空!");
                     else{
                     else{
                         $value[$key]["type"] = $field["type"];
                         $value[$key]["type"] = $field["type"];

+ 0 - 1
application/admin/controller/store/StoreCategory.php

@@ -1,5 +1,4 @@
 <?php
 <?php
-
 namespace app\admin\controller\store;
 namespace app\admin\controller\store;
 
 
 use app\admin\controller\AuthController;
 use app\admin\controller\AuthController;

+ 14 - 9
application/admin/controller/store/StoreProduct.php

@@ -138,22 +138,27 @@ class StoreProduct extends AuthController
                     $menus[] = ['value'=>$menu['id'],'label'=>$menu['html'].$menu['cate_name'],'disabled'=>$menu['pid']== 0];//,'disabled'=>$menu['pid']== 0];
                     $menus[] = ['value'=>$menu['id'],'label'=>$menu['html'].$menu['cate_name'],'disabled'=>$menu['pid']== 0];//,'disabled'=>$menu['pid']== 0];
                 }
                 }
                 return $menus;
                 return $menus;
-            })->filterable(1)->multiple(1),
-            Form::input('store_name','产品名称')->col(Form::col(24)),
+            })->filterable(1)->multiple(1)->required(),
+            Form::input('store_name','产品名称')->col(Form::col(24))->validateFn(function($validate){
+                $validate->min(5)->max(32);
+            })->required(),
             Form::input('store_info','产品简介')->type('textarea'),
             Form::input('store_info','产品简介')->type('textarea'),
             Form::input('keyword','产品关键字')->placeholder('多个用英文状态下的逗号隔开'),
             Form::input('keyword','产品关键字')->placeholder('多个用英文状态下的逗号隔开'),
-            Form::input('unit_name','产品单位','件'),
-            Form::frameImageOne('image','产品主图片(305*305px)',Url::build('admin/widget.images/index',array('fodder'=>'image')))->icon('image')->width('100%')->height('500px'),
-            Form::frameImages('slider_image','产品轮播图(640*640px)',Url::build('admin/widget.images/index',array('fodder'=>'slider_image')))->maxLength(5)->icon('images')->width('100%')->height('500px')->spin(0),
-            Form::number('price','产品售价')->min(0)->col(8),
+            Form::input('unit_name','产品单位','件')->required(),
+            Form::frameImageOne('image','产品主图片(305*305px)',Url::build('admin/widget.images/index',array('fodder'=>'image')))->icon('image')->width('100%')->height('500px')->required(),
+            Form::frameImages('slider_image','产品轮播图(640*640px)',Url::build('admin/widget.images/index',array('fodder'=>'slider_image')))->maxLength(5)->icon('images')->width('100%')->height('500px')->spin(0)
+                ->required()->validateFn(function($validate){
+                $validate->min(1)->max(5);
+            }),
+            Form::number('price','产品售价')->min(0)->col(8)->required(),
             Form::number('ot_price','产品市场价')->min(0)->col(8),
             Form::number('ot_price','产品市场价')->min(0)->col(8),
             Form::number('give_integral','赠送积分')->min(0)->precision(0)->col(8),
             Form::number('give_integral','赠送积分')->min(0)->precision(0)->col(8),
-            Form::number('postage','邮费')->min(0)->col(Form::col(8)),
+            Form::number('postage','邮费')->min(0)->col(Form::col(8))->required(),
             Form::number('sales','销量',0)->min(0)->precision(0)->col(8)->readonly(1),
             Form::number('sales','销量',0)->min(0)->precision(0)->col(8)->readonly(1),
             Form::number('ficti','虚拟销量')->min(0)->precision(0)->col(8),
             Form::number('ficti','虚拟销量')->min(0)->precision(0)->col(8),
-            Form::number('stock','库存')->min(0)->precision(0)->col(8),
+            Form::number('stock','库存')->min(0)->precision(0)->col(8)->required(),
             Form::number('cost','产品成本价')->min(0)->col(8),
             Form::number('cost','产品成本价')->min(0)->col(8),
-            Form::number('sort','排序')->col(8),
+            Form::number('sort','排序',0)->col(8)->required(),
             Form::radio('is_show','产品状态',0)->options([['label'=>'上架','value'=>1],['label'=>'下架','value'=>0]])->col(8),
             Form::radio('is_show','产品状态',0)->options([['label'=>'上架','value'=>1],['label'=>'下架','value'=>0]])->col(8),
             Form::radio('is_hot','热卖单品',0)->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(8),
             Form::radio('is_hot','热卖单品',0)->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(8),
             Form::radio('is_benefit','促销单品',0)->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(8),
             Form::radio('is_benefit','促销单品',0)->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(8),

+ 9 - 2
application/admin/controller/system/SystemFile.php

@@ -20,11 +20,11 @@ class SystemFile extends AuthController
     public function opendir($filedir=''){
     public function opendir($filedir=''){
         $fileAll = array('dir'=>[],'file'=>[]);
         $fileAll = array('dir'=>[],'file'=>[]);
         if(Request::instance()->param('superior') && !empty(Request::instance()->param('dir'))){
         if(Request::instance()->param('superior') && !empty(Request::instance()->param('dir'))){
-            $path = '.'.DS.Request::instance()->param('dir');
+            $path = './'.Request::instance()->param('dir');
             $path = dirname($path);
             $path = dirname($path);
         }else{
         }else{
             $path = !empty(Request::instance()->param('dir'))?Request::instance()->param('dir'):'.';
             $path = !empty(Request::instance()->param('dir'))?Request::instance()->param('dir'):'.';
-            $path = $path.DS.Request::instance()->param('filedir');
+            $path = $path.'/'.Request::instance()->param('filedir');
         }
         }
         $list = scandir($path);
         $list = scandir($path);
         foreach($list as $key=>$v) {
         foreach($list as $key=>$v) {
@@ -38,6 +38,9 @@ class SystemFile extends AuthController
             }
             }
         }
         }
 //        var_dump($fileAll['file']);
 //        var_dump($fileAll['file']);
+        //兼容windows
+        $uname=php_uname('s');
+        if(strstr($uname,'Windows')!==false) $path = ltrim($path,'\\');
         $dir = ltrim($path,'./');
         $dir = ltrim($path,'./');
         $this->assign(compact('fileAll','dir'));
         $this->assign(compact('fileAll','dir'));
         return $this->fetch();
         return $this->fetch();
@@ -65,6 +68,10 @@ class SystemFile extends AuthController
         $comment = $this->request->post('comment');
         $comment = $this->request->post('comment');
         $filepath = $this->request->post('filepath');
         $filepath = $this->request->post('filepath');
         if(!empty($comment) && !empty($filepath)){
         if(!empty($comment) && !empty($filepath)){
+            //兼容windows
+            $uname=php_uname('s');
+            if(strstr($uname,'Windows')!==false)
+            $filepath = ltrim(str_replace('/', DS, $filepath),'.');
             $res = FileClass::write_file($filepath,$comment);
             $res = FileClass::write_file($filepath,$comment);
             if($res){
             if($res){
                 return Json::successful('保存成功!');
                 return Json::successful('保存成功!');

+ 1 - 1
application/admin/controller/ump/StoreCoupon.php

@@ -42,7 +42,7 @@ class StoreCoupon extends AuthController
     public function create()
     public function create()
     {
     {
         $f = array();
         $f = array();
-        $f[] = Form::input('title','优惠券名称');
+        $f[] = Form::input('title','优惠券名称')->required();
         $f[] = Form::number('coupon_price','优惠券面值',0)->min(0);
         $f[] = Form::number('coupon_price','优惠券面值',0)->min(0);
         $f[] = Form::number('use_min_price','优惠券最低消费')->min(0);
         $f[] = Form::number('use_min_price','优惠券最低消费')->min(0);
         $f[] = Form::number('coupon_time','优惠券有效期限')->min(0);
         $f[] = Form::number('coupon_time','优惠券有效期限')->min(0);

+ 8 - 8
application/admin/controller/ump/StoreSeckill.php

@@ -75,13 +75,13 @@ class StoreSeckill extends AuthController
     public function create()
     public function create()
     {
     {
         $f = array();
         $f = array();
-        $f[] = Form::input('title','产品标题');
-        $f[] = Form::input('info','秒杀活动简介')->type('textarea');
-        $f[] = Form::input('unit_name','单位')->placeholder('个、位');
-        $f[] = Form::dateTimeRange('section_time','活动时间');
-        $f[] = Form::frameImageOne('image','产品主图片(305*305px)',Url::build('admin/widget.images/index',array('fodder'=>'image')))->icon('image');
-        $f[] = Form::frameImages('images','产品轮播图(640*640px)',Url::build('admin/widget.images/index',array('fodder'=>'images')))->maxLength(5)->icon('images');
-        $f[] = Form::number('price','秒杀价')->min(0)->col(12);
+        $f[] = Form::input('title','产品标题')->required();
+        $f[] = Form::input('info','秒杀活动简介')->type('textarea')->required();
+        $f[] = Form::input('unit_name','单位')->placeholder('个、位')->required();
+        $f[] = Form::dateTimeRange('section_time','活动时间')->required();
+        $f[] = Form::frameImageOne('image','产品主图片(305*305px)',Url::build('admin/widget.images/index',array('fodder'=>'image')))->icon('image')->required();
+        $f[] = Form::frameImages('images','产品轮播图(640*640px)',Url::build('admin/widget.images/index',array('fodder'=>'images')))->maxLength(5)->icon('images')->required();
+        $f[] = Form::number('price','秒杀价')->min(0)->col(12)->required();
         $f[] = Form::number('ot_price','原价')->min(0)->col(12);
         $f[] = Form::number('ot_price','原价')->min(0)->col(12);
         $f[] = Form::number('cost','成本价')->min(0)->col(12);
         $f[] = Form::number('cost','成本价')->min(0)->col(12);
         $f[] = Form::number('stock','库存')->min(0)->precision(0)->col(12);
         $f[] = Form::number('stock','库存')->min(0)->precision(0)->col(12);
@@ -93,7 +93,7 @@ class StoreSeckill extends AuthController
         $f[] = Form::radio('is_postage','是否包邮',1)->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(12);
         $f[] = Form::radio('is_postage','是否包邮',1)->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(12);
         $f[] = Form::radio('is_hot','热门推荐',1)->options([['label'=>'开启','value'=>1],['label'=>'关闭','value'=>0]])->col(12);
         $f[] = Form::radio('is_hot','热门推荐',1)->options([['label'=>'开启','value'=>1],['label'=>'关闭','value'=>0]])->col(12);
         $f[] = Form::radio('status','活动状态',1)->options([['label'=>'开启','value'=>1],['label'=>'关闭','value'=>0]])->col(12);
         $f[] = Form::radio('status','活动状态',1)->options([['label'=>'开启','value'=>1],['label'=>'关闭','value'=>0]])->col(12);
-        $form = Form::make_post_form('添加用户通知',$f,Url::build('save'));
+        $form = Form::make_post_form('开启秒杀',$f,Url::build('save'));
         $this->assign(compact('form'));
         $this->assign(compact('form'));
         return $this->fetch('public/form-builder');
         return $this->fetch('public/form-builder');
     }
     }

+ 18 - 0
application/admin/model/order/StoreOrder.php

@@ -54,6 +54,7 @@ class StoreOrder extends ModelBasic
                 $_info[$k]['cart_info'] = json_decode($v['cart_info'],true);
                 $_info[$k]['cart_info'] = json_decode($v['cart_info'],true);
             }
             }
             $item['_info'] = $_info;
             $item['_info'] = $_info;
+            $item['add_time'] = date('Y-m-d H:i:s',$item['add_time']);
             if($item['pink_id'] && $item['combination_id']){
             if($item['pink_id'] && $item['combination_id']){
                 $pinkStatus = StorePink::where('order_id_key',$item['id'])->value('status');
                 $pinkStatus = StorePink::where('order_id_key',$item['id'])->value('status');
                 switch ($pinkStatus){
                 switch ($pinkStatus){
@@ -904,4 +905,21 @@ HTML;
           if(!$uid) return 0;
           if(!$uid) return 0;
           return self::where('uid',$uid)->where('paid',1)->where('refund_status',0)->where('status',2)->count();
           return self::where('uid',$uid)->where('paid',1)->where('refund_status',0)->where('status',2)->count();
       }
       }
+    /**
+     * 获取已支付的订单
+     * @param int $is_promoter
+     * @return int|string
+     */
+    public static function getOrderPayCount($is_promoter = 0){
+        return self::where('o.paid',1)->alias('o')->join('User u','u.uid=o.uid')->where('u.is_promoter',$is_promoter)->count();
+    }
+
+    /**
+     * 获取最后一个月已支付的订单
+     * @param int $is_promoter
+     * @return int|string
+     */
+    public static function getOrderPayMonthCount($is_promoter = 0){
+        return self::where('o.paid',1)->alias('o')->whereTime('o.pay_time','last month')->join('User u','u.uid=o.uid')->where('u.is_promoter',$is_promoter)->count();
+    }
 }
 }

+ 24 - 2
application/admin/model/store/StoreCategory.php

@@ -7,7 +7,6 @@
 
 
 namespace app\admin\model\store;
 namespace app\admin\model\store;
 
 
-
 use traits\ModelTrait;
 use traits\ModelTrait;
 use basic\ModelBasic;
 use basic\ModelBasic;
 use service\UtilService;
 use service\UtilService;
@@ -20,16 +19,39 @@ class StoreCategory extends ModelBasic
 {
 {
     use ModelTrait;
     use ModelTrait;
 
 
+    /*
+     * 异步获取分类列表
+     * @param $where
+     * @return array
+     */
+    public static function CategoryList($where){
+        $data=($data=self::systemPage($where,true)->page((int)$where['page'],(int)$where['limit'])->select()) && count($data) ? $data->toArray() :[];
+        foreach ($data as &$item){
+            if($item['pid']){
+                $item['pid_name'] = self::where('id',$item['pid'])->value('cate_name');
+            }else{
+                $item['pid_name'] = '顶级';
+            }
+        }
+        $count=self::systemPage($where,true)->count();
+        return compact('count','data');
+    }
     /**
     /**
      * @param $where
      * @param $where
      * @return array
      * @return array
      */
      */
-    public static function systemPage($where){
+    public static function systemPage($where,$isAjax=false){
         $model = new self;
         $model = new self;
         if($where['pid'] != '')  $model = $model->where('pid',$where['pid']);
         if($where['pid'] != '')  $model = $model->where('pid',$where['pid']);
         else if($where['pid']=='' && $where['cate_name']=='') $model = $model->where('pid',0);
         else if($where['pid']=='' && $where['cate_name']=='') $model = $model->where('pid',0);
         if($where['is_show'] != '')  $model = $model->where('is_show',$where['is_show']);
         if($where['is_show'] != '')  $model = $model->where('is_show',$where['is_show']);
         if($where['cate_name'] != '')  $model = $model->where('cate_name','LIKE',"%$where[cate_name]%");
         if($where['cate_name'] != '')  $model = $model->where('cate_name','LIKE',"%$where[cate_name]%");
+        if($isAjax===true){
+            if(isset($where['order']) && $where['order']!=''){
+                $model=$model->order(self::setOrder($where['order']));
+            }
+            return $model;
+        }
         return self::page($model,function ($item){
         return self::page($model,function ($item){
             if($item['pid']){
             if($item['pid']){
                 $item['pid_name'] = self::where('id',$item['pid'])->value('cate_name');
                 $item['pid_name'] = self::where('id',$item['pid'])->value('cate_name');

+ 1 - 1
application/admin/model/store/StoreProductAttr.php

@@ -77,7 +77,7 @@ class StoreProductAttr extends ModelBasic
             ];
             ];
         }
         }
         foreach ($valueList as $k=>$value){
         foreach ($valueList as $k=>$value){
-            ksort($value['detail'],SORT_STRING);
+            sort($value['detail'],SORT_STRING);
             $suk = implode(',',$value['detail']);
             $suk = implode(',',$value['detail']);
             $valueGroup[$suk] = [
             $valueGroup[$suk] = [
                 'product_id'=>$productId,
                 'product_id'=>$productId,

+ 38 - 13
application/admin/view/order/store_order/index.php

@@ -82,7 +82,7 @@
                     <table class="layui-hide" id="List" lay-filter="List"></table>
                     <table class="layui-hide" id="List" lay-filter="List"></table>
                     <!--订单-->
                     <!--订单-->
                     <script type="text/html" id="order_id">
                     <script type="text/html" id="order_id">
-                       <h4>{{d.order_id}}</h4>
+                       {{d.order_id}}
                        <span style="color: {{d.color}};">{{d.pink_name}}</span>  
                        <span style="color: {{d.color}};">{{d.pink_name}}</span>  
                     </script>
                     </script>
                     <!--用户信息-->
                     <!--用户信息-->
@@ -112,32 +112,32 @@
                         {{#  if(item.cart_info.productInfo.attrInfo!=undefined){ }}
                         {{#  if(item.cart_info.productInfo.attrInfo!=undefined){ }}
                         <p>
                         <p>
                             <span>
                             <span>
-                                <img style="width: 30px;height: 30px;cursor: pointer;" src="{{item.cart_info.productInfo.attrInfo.image}}">
+                                <img style="width: 30px;height: 30px;margin:0;cursor: pointer;" src="{{item.cart_info.productInfo.attrInfo.image}}">
                             </span>
                             </span>
                             <span>{{item.cart_info.productInfo.store_name}}&nbsp;{{item.cart_info.productInfo.attrInfo.suk}}</span>
                             <span>{{item.cart_info.productInfo.store_name}}&nbsp;{{item.cart_info.productInfo.attrInfo.suk}}</span>
                             <span> | ¥{{item.cart_info.truePrice}}×{{item.cart_info.cart_num}}</span>
                             <span> | ¥{{item.cart_info.truePrice}}×{{item.cart_info.cart_num}}</span>
                         </p>
                         </p>
                         {{#  }else{ }}
                         {{#  }else{ }}
                         <p>
                         <p>
-                            <span><img style="width: 30px;height: 30px;cursor: pointer;" src="{{item.cart_info.productInfo.image}}"></span>
+                            <span><img style="width: 30px;height: 30px;margin:0;cursor: pointer;" src="{{item.cart_info.productInfo.image}}"></span>
                             <span>{{item.cart_info.productInfo.store_name}}</span><span> | ¥{{item.cart_info.truePrice}}×{{item.cart_info.cart_num}}</span>
                             <span>{{item.cart_info.productInfo.store_name}}</span><span> | ¥{{item.cart_info.truePrice}}×{{item.cart_info.cart_num}}</span>
                         </p>
                         </p>
                         {{# } }}
                         {{# } }}
                         {{#  }); }}
                         {{#  }); }}
                     </script>
                     </script>
-                    <!--详情-->
-                    <script type="text/html" id="order_info">
-                        <button class="btn btn-white btn-bitbucket btn-xs" onclick="$eb.createModalFrame('{{d.nickname}}-订单详情','{:Url('order_info')}?oid={{d.id}}')">
-                            <i class="fa fa-file-text"></i> 订单详情
-                        </button>
-                    </script>
+
                     <script type="text/html" id="act">
                     <script type="text/html" id="act">
                         {{#  if(d._status==1){ }}
                         {{#  if(d._status==1){ }}
                         <button type="button" class="layui-btn layui-btn-xs" onclick="dropdown(this)">操作 <span class="caret"></span></button>
                         <button type="button" class="layui-btn layui-btn-xs" onclick="dropdown(this)">操作 <span class="caret"></span></button>
                         <ul class="layui-nav-child layui-anim layui-anim-upbit">
                         <ul class="layui-nav-child layui-anim layui-anim-upbit">
+                            <li>
+                                <a href="javascript:void(0);" onclick="$eb.createModalFrame('{{d.nickname}}-订单详情','{:Url('order_info')}?oid={{d.id}}')">
+                                    <i class="fa fa-file-text"></i> 订单详情
+                                </a>
+                            </li>
                             <li>
                             <li>
                                 <a href="javascript:void(0);" onclick="$eb.createModalFrame('修改订单','{:Url('edit')}?id={{d.id}}')">
                                 <a href="javascript:void(0);" onclick="$eb.createModalFrame('修改订单','{:Url('edit')}?id={{d.id}}')">
-                                    <i class="fa fa-file-text"></i> 修改订单
+                                    <i class="fa fa-edit"></i> 修改订单
                                 </a>
                                 </a>
                             </li>
                             </li>
                             <li>
                             <li>
@@ -156,6 +156,11 @@
                             <i class="fa fa-cart-plus"></i> 去发货</button>
                             <i class="fa fa-cart-plus"></i> 去发货</button>
                         <button type="button" class="layui-btn layui-btn-xs" onclick="dropdown(this)">操作 <span class="caret"></span></button>
                         <button type="button" class="layui-btn layui-btn-xs" onclick="dropdown(this)">操作 <span class="caret"></span></button>
                         <ul class="layui-nav-child layui-anim layui-anim-upbit">
                         <ul class="layui-nav-child layui-anim layui-anim-upbit">
+                            <li>
+                                <a href="javascript:void(0);" onclick="$eb.createModalFrame('{{d.nickname}}-订单详情','{:Url('order_info')}?oid={{d.id}}')">
+                                    <i class="fa fa-file-text"></i> 订单详情
+                                </a>
+                            </li>
                             <li>
                             <li>
                                 <a  href="javascript:void(0);" onclick="$eb.createModalFrame('去送货','{:Url('delivery')}?id={{d.id}}',{w:400,h:300})">
                                 <a  href="javascript:void(0);" onclick="$eb.createModalFrame('去送货','{:Url('delivery')}?id={{d.id}}',{w:400,h:300})">
                                     <i class="fa fa-motorcycle"></i> 去送货
                                     <i class="fa fa-motorcycle"></i> 去送货
@@ -188,6 +193,11 @@
                         {{#  }else if(d._status==3){ }}
                         {{#  }else if(d._status==3){ }}
                         <button type="button" class="layui-btn layui-btn-xs" onclick="dropdown(this)">操作 <span class="caret"></span></button>
                         <button type="button" class="layui-btn layui-btn-xs" onclick="dropdown(this)">操作 <span class="caret"></span></button>
                         <ul class="layui-nav-child layui-anim layui-anim-upbit">
                         <ul class="layui-nav-child layui-anim layui-anim-upbit">
+                            <li>
+                                <a href="javascript:void(0);" onclick="$eb.createModalFrame('{{d.nickname}}-订单详情','{:Url('order_info')}?oid={{d.id}}')">
+                                    <i class="fa fa-file-text"></i> 订单详情
+                                </a>
+                            </li>
                             <li>
                             <li>
                                 <a  href="javascript:void(0);" onclick="$eb.createModalFrame('去送货','{:Url('delivery')}?id={{d.id}}',{w:400,h:300})">
                                 <a  href="javascript:void(0);" onclick="$eb.createModalFrame('去送货','{:Url('delivery')}?id={{d.id}}',{w:400,h:300})">
                                     <i class="fa fa-motorcycle"></i> 去送货
                                     <i class="fa fa-motorcycle"></i> 去送货
@@ -227,6 +237,11 @@
                             <i class="fa fa-cart-arrow-down"></i> 配送信息</button>
                             <i class="fa fa-cart-arrow-down"></i> 配送信息</button>
                         <button type="button" class="layui-btn layui-btn-xs" onclick="dropdown(this)">操作 <span class="caret"></span></button>
                         <button type="button" class="layui-btn layui-btn-xs" onclick="dropdown(this)">操作 <span class="caret"></span></button>
                         <ul class="layui-nav-child layui-anim layui-anim-upbit">
                         <ul class="layui-nav-child layui-anim layui-anim-upbit">
+                            <li>
+                                <a href="javascript:void(0);" onclick="$eb.createModalFrame('{{d.nickname}}-订单详情','{:Url('order_info')}?oid={{d.id}}')">
+                                    <i class="fa fa-file-text"></i> 订单详情
+                                </a>
+                            </li>
                             <li>
                             <li>
                                 <a lay-event='marke' href="javascript:void(0);" >
                                 <a lay-event='marke' href="javascript:void(0);" >
                                     <i class="fa fa-paste"></i> 订单备注
                                     <i class="fa fa-paste"></i> 订单备注
@@ -259,6 +274,11 @@
                         {{#  }else if(d._status==5 || d._status==6){ }}
                         {{#  }else if(d._status==5 || d._status==6){ }}
                         <button type="button" class="layui-btn layui-btn-xs" onclick="dropdown(this)">操作 <span class="caret"></span></button>
                         <button type="button" class="layui-btn layui-btn-xs" onclick="dropdown(this)">操作 <span class="caret"></span></button>
                         <ul class="layui-nav-child layui-anim layui-anim-upbit">
                         <ul class="layui-nav-child layui-anim layui-anim-upbit">
+                            <li>
+                                <a href="javascript:void(0);" onclick="$eb.createModalFrame('{{d.nickname}}-订单详情','{:Url('order_info')}?oid={{d.id}}')">
+                                    <i class="fa fa-file-text"></i> 订单详情
+                                </a>
+                            </li>
                             <li>
                             <li>
                                 <a lay-event='marke' href="javascript:void(0);" >
                                 <a lay-event='marke' href="javascript:void(0);" >
                                     <i class="fa fa-paste"></i> 订单备注
                                     <i class="fa fa-paste"></i> 订单备注
@@ -286,6 +306,11 @@
                         {{#  }else if(d._status==7){ }}
                         {{#  }else if(d._status==7){ }}
                         <button type="button" class="layui-btn layui-btn-xs" onclick="dropdown(this)">操作 <span class="caret"></span></button>
                         <button type="button" class="layui-btn layui-btn-xs" onclick="dropdown(this)">操作 <span class="caret"></span></button>
                         <ul class="layui-nav-child layui-anim layui-anim-upbit">
                         <ul class="layui-nav-child layui-anim layui-anim-upbit">
+                            <li>
+                                <a href="javascript:void(0);" onclick="$eb.createModalFrame('{{d.nickname}}-订单详情','{:Url('order_info')}?oid={{d.id}}')">
+                                    <i class="fa fa-file-text"></i> 订单详情
+                                </a>
+                            </li>
                             <li>
                             <li>
                                 <a lay-event='marke' href="javascript:void(0);" >
                                 <a lay-event='marke' href="javascript:void(0);" >
                                     <i class="fa fa-paste"></i> 订单备注
                                     <i class="fa fa-paste"></i> 订单备注
@@ -318,13 +343,13 @@
 <script>
 <script>
     layList.tableList('List',"{:Url('order_list',['real_name'=>$real_name])}",function (){
     layList.tableList('List',"{:Url('order_list',['real_name'=>$real_name])}",function (){
         return [
         return [
-            {field: 'order_id', title: '订单号', sort: true,event:'order_id',width:'12%',templet:'#order_id'},
+            {field: 'order_id', title: '订单号', sort: true,event:'order_id',width:'14%',templet:'#order_id'},
             {field: 'nickname', title: '用户信息',templet:'#userinfo',width:'10%'},
             {field: 'nickname', title: '用户信息',templet:'#userinfo',width:'10%'},
-            {field: 'info', title: '商品信息',templet:"#info",width:'36%'},
+            {field: 'info', title: '商品信息',templet:"#info"},
             {field: 'pay_price', title: '实际支付',width:'8%'},
             {field: 'pay_price', title: '实际支付',width:'8%'},
             {field: 'paid', title: '支付状态',templet:'#paid',width:'8%'},
             {field: 'paid', title: '支付状态',templet:'#paid',width:'8%'},
             {field: 'status', title: '订单状态',templet:'#status',width:'8%'},
             {field: 'status', title: '订单状态',templet:'#status',width:'8%'},
-            {field: 'order_info', title: '详情',templet:'#order_info',width:'8%'},
+            {field: 'add_time', title: '下单时间',width:'10%',sort: true},
             {field: 'right', title: '操作',align:'center',toolbar:'#act',width:'10%'},
             {field: 'right', title: '操作',align:'center',toolbar:'#act',width:'10%'},
         ];
         ];
     });
     });

+ 152 - 113
application/admin/view/store/store_category/index.php

@@ -1,133 +1,172 @@
 {extend name="public/container"}
 {extend name="public/container"}
 {block name="content"}
 {block name="content"}
-<div class="row">
-    <div class="col-sm-12">
-        <div class="ibox">
-            <div class="ibox-title">
-                <a type="button" class="btn btn-w-m btn-primary" href="{:Url('index')}">分类首页</a>
-                <button type="button" class="btn btn-w-m btn-primary" onclick="$eb.createModalFrame(this.innerText,'{:Url('create')}')">添加分类</button>
-                <div class="ibox-tools">
 
 
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15"  id="app">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">搜索条件</div>
+                <div class="layui-card-body">
+                    <form class="layui-form layui-form-pane" action="">
+                        <div class="layui-form-item">
+                            <div class="layui-inline">
+                                <label class="layui-form-label">所有分类</label>
+                                <div class="layui-input-block">
+                                    <select name="is_show">
+                                        <option value="">是否显示</option>
+                                        <option value="1">显示</option>
+                                        <option value="0">不显示</option>
+                                    </select>
+                                </div>
+                            </div>
+                            <div class="layui-inline">
+                                <label class="layui-form-label">所有分类</label>
+                                <div class="layui-input-block">
+                                    <select name="pid">
+                                        <option value="">所有菜单</option>
+                                        {volist name="cate" id="vo"}
+                                        <option value="{$vo.id}">{$vo.html}{$vo.cate_name}</option>
+                                        {/volist}
+                                    </select>
+                                </div>
+                            </div>
+                            <div class="layui-inline">
+                                <label class="layui-form-label">产品名称</label>
+                                <div class="layui-input-block">
+                                    <input type="text" name="cate_name" class="layui-input" placeholder="请输入分类名称">
+                                </div>
+                            </div>
+                            <div class="layui-inline">
+                                <div class="layui-input-inline">
+                                    <button class="layui-btn layui-btn-sm layui-btn-normal" lay-submit="search" lay-filter="search">
+                                        <i class="layui-icon layui-icon-search"></i>搜索</button>
+                                </div>
+                            </div>
+                        </div>
+                    </form>
                 </div>
                 </div>
             </div>
             </div>
-            <div class="ibox-content">
-                <div class="row">
-                    <div class="m-b m-l">
-                        <form action="" class="form-inline">
-                            <select name="is_show" aria-controls="editable" class="form-control input-sm">
-                                <option value="">是否显示</option>
-                                <option value="1" {eq name="where.is_show" value="1"}selected="selected"{/eq}>显示</option>
-                                <option value="0" {eq name="where.is_show" value="0"}selected="selected"{/eq}>不显示</option>
-                            </select>
-                            <select name="pid" aria-controls="editable" class="form-control input-sm">
-                                <option value="">所有菜单</option>
-                                {volist name="cate" id="vo"}
-                                <option value="{$vo.id}" {eq name="where.pid" value="$vo.id"}selected="selected"{/eq}>{$vo.html}{$vo.cate_name}</option>
-                                {/volist}
-                            </select>
-                            <div class="input-group">
-                                <input type="text" name="cate_name" value="{$where.cate_name}" placeholder="请输入分类名称" class="input-sm form-control"> <span class="input-group-btn">
-                                    <button type="submit" class="btn btn-sm btn-primary"><i class="fa fa-search" ></i> 搜索</button> </span>
-                            </div>
-                        </form>
+        </div>
+        <!--产品列表-->
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">分类列表</div>
+                <div class="layui-card-body">
+                    <div class="alert alert-info" role="alert">
+                        注:点击父级名称可查看子集分类,点击分页首页可返回顶级分类;分类名称和排序可进行快速编辑;
+                        <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                     </div>
                     </div>
-
-                </div>
-                <div class="table-responsive" style="overflow:visible">
-                    <table class="table table-striped  table-bordered">
-                        <thead>
-                        <tr>
-
-                            <th class="text-center" style="width: 40px;">编号</th>
-                            <th class="text-center">父级</th>
-                            <th class="text-center">分类名称</th>
-                            <th class="text-center">分类图标</th>
-                            <th class="text-center">排序</th>
-                            <th class="text-center">是否显示</th>
-                            <th class="text-center" width="5%">操作</th>
-                        </tr>
-                        </thead>
-                        <tbody class="">
-                        {volist name="list" id="vo"}
-                        <tr>
-                            <td class="text-center">
-                                {$vo.id}
-                            </td>
-                            <td class="text-center">
-                                {$vo.pid_name}
-                            </td>
-                            <td class="text-center">
-                                <a href="{:Url('index',array('pid'=>$vo['id']))}"> {$vo.cate_name}</a>
-                            </td>
-                            <td class="text-center">
-                                <img src="{$vo.pic}" alt="{$vo.cate_name}" class="open_image" data-image="{$vo.pic}" style="width: 50px;height: 50px;cursor: pointer;">
-                            </td>
-                            <td class="text-center">
-                                {$vo.sort}
-                            </td>
-                            <td class="text-center">
-                                <i class="fa {eq name='vo.is_show' value='1'}fa-check text-navy{else/}fa-close text-danger{/eq}"></i>
-                            </td>
-
-                            <td class="text-center">
-                                <div class="input-group-btn js-group-btn" style="min-width: 106px;">
-                                    <div class="btn-group">
-                                        <button data-toggle="dropdown" class="btn btn-warning btn-xs dropdown-toggle"
-                                                aria-expanded="false">操作
-                                            <span class="caret"></span>
-                                        </button>
-                                        <ul class="dropdown-menu">
-                                            <li>
-                                                <a href="javascript:void(0);"onclick="$eb.createModalFrame('编辑','{:Url('edit',array('id'=>$vo['id']))}')">
-                                                    <i class="fa fa-paste"></i> 编辑
-                                                </a>
-                                            </li>
-                                            <li>
-                                                <a href="javascript:void(0);" class="delstor" data-url="{:Url('delete',array('id'=>$vo['id']))}">
-                                                    <i class="fa fa-warning"></i> 删除
-                                                </a>
-                                            </li>
-
-                                        </ul>
-                                    </div>
-                                </div>
-                            </td>
-                        </tr>
-                        {/volist}
-                        </tbody>
-                    </table>
+                    <div class="layui-btn-container">
+                        <a class="layui-btn layui-btn-sm" href="{:Url('index')}">分类首页</a>
+                        <button type="button" class="layui-btn layui-btn-sm" onclick="$eb.createModalFrame(this.innerText,'{:Url('create')}')">添加分类</button>
+                    </div>
+                    <table class="layui-hide" id="List" lay-filter="List"></table>
+                    <script type="text/html" id="pic">
+                        <img style="cursor: pointer" lay-event='open_image' src="{{d.pic}}">
+                    </script>
+                    <script type="text/html" id="is_show">
+                        <input type='checkbox' name='id' lay-skin='switch' value="{{d.id}}" lay-filter='is_show' lay-text='显|隐'  {{ d.is_show == 1 ? 'checked' : '' }}>
+                    </script>
+                    <script type="text/html" id="pid">
+                        <a href="{:Url('index')}?pid={{d.id}}">查看</a>
+                    </script>
+                    <script type="text/html" id="act">
+                        <button class="layui-btn layui-btn-xs" onclick="$eb.createModalFrame('编辑','{:Url('edit')}?id={{d.id}}')">
+                            <i class="fa fa-paste"></i> 编辑
+                        </button>
+                        <button class="layui-btn layui-btn-xs" lay-event='delstor'>
+                            <i class="fa fa-warning"></i> 删除
+                        </button>
+                    </script>
                 </div>
                 </div>
-                {include file="public/inner_page"}
             </div>
             </div>
         </div>
         </div>
     </div>
     </div>
 </div>
 </div>
+<script src="{__ADMIN_PATH}js/layuiList.js"></script>
 {/block}
 {/block}
 {block name="script"}
 {block name="script"}
 <script>
 <script>
-    $('.js-group-btn').on('click',function(){
-        $('.js-group-btn').css({zIndex:1});
-        $(this).css({zIndex:2});
+    setTimeout(function () {
+        $('.alert-info').hide();
+    },3000);
+    //实例化form
+    layList.form.render();
+    //加载列表
+    layList.tableList('List',"{:Url('category_list',['pid'=>$pid])}",function (){
+        return [
+            {field: 'id', title: 'ID', sort: true,event:'id',width:'6%'},
+            {field: 'pid_name', title: '父级'},
+            {field: 'cate_name', title: '分类名称',edit:'cate_name'},
+            {field: 'pid', title: '查看子分类',templet:'#pid'},
+            {field: 'pic', title: '分类图标',templet:'#pic'},
+            {field: 'sort', title: '排序',sort: true,event:'sort',edit:'sort',width:'8%'},
+            {field: 'is_show', title: '状态',templet:'#is_show',width:'6%'},
+            {field: 'right', title: '操作',align:'center',toolbar:'#act',width:'14%'},
+        ];
+    });
+    //自定义方法
+    var action= {
+        set_category: function (field, id, value) {
+            layList.baseGet(layList.Url({
+                c: 'store.store_category',
+                a: 'set_category',
+                q: {field: field, id: id, value: value}
+            }), function (res) {
+                layList.msg(res.msg);
+            });
+        },
+    }
+    //查询
+    layList.search('search',function(where){
+        layList.reload(where);
     });
     });
-    $('.delstor').on('click',function(){
-        window.t = $(this);
-        var _this = $(this),url =_this.data('url');
-        $eb.$swal('delete',function(){
-            $eb.axios.get(url).then(function(res){
-                console.log(res);
-                if(res.status == 200 && res.data.code == 200) {
-                    $eb.$swal('success',res.data.msg);
-                    _this.parents('tr').remove();
-                }else
-                    return Promise.reject(res.data.msg || '删除失败')
-            }).catch(function(err){
-                $eb.$swal('error',err);
+    layList.switch('is_show',function (odj,value) {
+        if(odj.elem.checked==true){
+            layList.baseGet(layList.Url({c:'store.store_category',a:'set_show',p:{is_show:1,id:value}}),function (res) {
+                layList.msg(res.msg);
             });
             });
-        })
+        }else{
+            layList.baseGet(layList.Url({c:'store.store_category',a:'set_show',p:{is_show:0,id:value}}),function (res) {
+                layList.msg(res.msg);
+            });
+        }
+    });
+    //快速编辑
+    layList.edit(function (obj) {
+        var id=obj.data.id,value=obj.value;
+        switch (obj.field) {
+            case 'cate_name':
+                action.set_category('cate_name',id,value);
+                break;
+            case 'sort':
+                action.set_category('sort',id,value);
+                break;
+        }
     });
     });
-    $(".open_image").on('click',function (e) {
-        var image = $(this).data('image');
-        $eb.openImage(image);
+    //监听并执行排序
+    layList.sort(['id','sort'],true);
+    //点击事件绑定
+    layList.tool(function (event,data,obj) {
+        switch (event) {
+            case 'delstor':
+                var url=layList.U({c:'store.store_category',a:'delete',q:{id:data.id}});
+                $eb.$swal('delete',function(){
+                    $eb.axios.get(url).then(function(res){
+                        if(res.status == 200 && res.data.code == 200) {
+                            $eb.$swal('success',res.data.msg);
+                            obj.del();
+                        }else
+                            return Promise.reject(res.data.msg || '删除失败')
+                    }).catch(function(err){
+                        $eb.$swal('error',err);
+                    });
+                })
+                break;
+            case 'open_image':
+                $eb.openImage(data.pic);
+                break;
+        }
     })
     })
 </script>
 </script>
 {/block}
 {/block}

+ 9 - 9
application/admin/view/store/store_product/index.php

@@ -71,7 +71,7 @@
                     <div class="layui-btn-container">
                     <div class="layui-btn-container">
                         {switch name='type'}
                         {switch name='type'}
                             {case value="1"}
                             {case value="1"}
-                                <button class="layui-btn layui-btn-sm" onclick="$eb.createModalFrame(this.innerText,'{:Url('create')}',{h:760,w:1100})">添加产品</button>
+                                <button class="layui-btn layui-btn-sm" onclick="$eb.createModalFrame(this.innerText,'{:Url('create')}',{h:700,w:1100})">添加产品</button>
                             {/case}
                             {/case}
                             {case value="2"}
                             {case value="2"}
                                 <button class="layui-btn layui-btn-sm" data-type="show">批量上架</button>
                                 <button class="layui-btn layui-btn-sm" data-type="show">批量上架</button>
@@ -175,15 +175,15 @@
             case 2:
             case 2:
                 join=[
                 join=[
                     {type:'checkbox'},
                     {type:'checkbox'},
-                    {field: 'id', title: 'ID', sort: true,event:'id',width:'5%'},
-                    {field: 'image', title: '产品图片',templet:'#image'},
+                    {field: 'id', title: 'ID', sort: true,event:'id',width:'6%'},
+                    {field: 'image', title: '产品图片',templet:'#image',width:'10%'},
                     {field: 'store_name', title: '产品名称',templet:'#store_name'},
                     {field: 'store_name', title: '产品名称',templet:'#store_name'},
-                    {field: 'price', title: '产品价格',edit:'price'},
-                    {field: 'ficti', title: '虚拟销量',edit:'ficti'},
-                    {field: 'stock', title: '库存',edit:'stock'},
-                    {field: 'sort', title: '排序',edit:'sort'},
-                    {field: 'sales', title: '销量',sort: true,event:'sales'},
-                    {field: 'status', title: '状态',templet:"#checkboxstatus"},
+                    {field: 'price', title: '价格',edit:'price',width:'8%'},
+                    {field: 'ficti', title: '虚拟销量',edit:'ficti',width:'8%'},
+                    {field: 'stock', title: '库存',edit:'stock',width:'6%'},
+                    {field: 'sort', title: '排序',edit:'sort',width:'6%'},
+                    {field: 'sales', title: '销量',sort: true,event:'sales',width:'6%'},
+                    {field: 'status', title: '状态',templet:"#checkboxstatus",width:'8%'},
                     {field: 'right', title: '操作',align:'center',toolbar:'#act',width:'14%'},
                     {field: 'right', title: '操作',align:'center',toolbar:'#act',width:'14%'},
                 ];
                 ];
                 break;
                 break;

+ 2 - 2
application/admin/view/ump/store_combination/index.php

@@ -135,8 +135,8 @@
     layList.tableList('combinationList',"{:Url('get_combination_list')}",function () {
     layList.tableList('combinationList',"{:Url('get_combination_list')}",function () {
         return [
         return [
             {field: 'id', title: '编号', sort: true,event:'id'},
             {field: 'id', title: '编号', sort: true,event:'id'},
-            {field: 'image', title: '拼团图片',templet: '<p><img src="{{d.image}}" alt="{{d.title}}" class="open_image" data-image="{{d.image}}"></p>'},
-            {field: 'title', title: '拼团名称'},
+            {field: 'image', title: '拼团图片',width:'10%',templet: '<p><img src="{{d.image}}" alt="{{d.title}}" class="open_image" data-image="{{d.image}}"></p>'},
+            {field: 'title', title: '拼团名称',width:'10%'},
             {field: 'ot_price', title: '原价'},
             {field: 'ot_price', title: '原价'},
             {field: 'price', title: '拼团价'},
             {field: 'price', title: '拼团价'},
             {field: 'stock', title: '库存'},
             {field: 'stock', title: '库存'},

+ 11 - 11
application/admin/view/ump/store_seckill/index.php

@@ -113,17 +113,17 @@
     layList.form.render();
     layList.form.render();
     layList.tableList('seckillList',"{:Url('get_seckill_list')}",function () {
     layList.tableList('seckillList',"{:Url('get_seckill_list')}",function () {
         return [
         return [
-            {field: 'id', title: '编号', sort: true,width:'5%',event:'id',unresize:true},
-            {field: 'image', title: '产品图片',unresize:true, width: '8%',templet: '<p><img src="{{d.image}}" alt="{{d.title}}" class="open_image" data-image="{{d.image}}"></p>'},
-            {field: 'title', title: '活动标题',width:'14%',unresize:true},
-            {field: 'info', title: '活动简介',width:'17%',unresize:true},
-            {field: 'ot_price', title: '原价',width:'6%',unresize:true},
-            {field: 'price', title: '秒杀价',unresize:true,width:'6%'},
-            {field: 'stock', title: '库存',width:'7%',unresize:true},
-            {field: 'start_name', title: '秒杀状态',width:'13%',toolbar:"#statusCn",unresize:true},
-            {field: 'stop_time', title: '结束时间', width: '13%',toolbar: '#stopTime',unresize:true},
-            {field: 'status', title: '状态',width:'6%',toolbar:"#status",unresize:true},
-            {field: 'right', title: '操作', width: '5%', align: 'center', toolbar: '#barDemo',unresize:true}
+            {field: 'id', title: 'ID', sort: true,width:'6%',event:'id'},
+            {field: 'image', title: '产品图片', width: '10%',templet: '<p><img src="{{d.image}}" alt="{{d.title}}" class="open_image" data-image="{{d.image}}"></p>'},
+            {field: 'title', title: '活动标题'},
+            {field: 'info', title: '活动简介',width:'20%'},
+            {field: 'ot_price', title: '原价',width:'6%'},
+            {field: 'price', title: '秒杀价',width:'6%'},
+            {field: 'stock', title: '库存',width:'6%'},
+            {field: 'start_name', title: '秒杀状态',width:'8%',toolbar:"#statusCn"},
+            {field: 'stop_time', title: '结束时间', width: '13%',toolbar: '#stopTime'},
+            {field: 'status', title: '状态',width:'6%',toolbar:"#status"},
+            {field: 'right', title: '操作', width: '6%', align: 'center', toolbar: '#barDemo'}
         ]
         ]
     });
     });
     layList.tool(function (event,data,obj) {
     layList.tool(function (event,data,obj) {

+ 1 - 1
application/admin/view/ump/user_point/index.php

@@ -88,7 +88,7 @@
                 layList.form.render();
                 layList.form.render();
                 layList.tableList('userList',"{:Url('getponitlist')}",function () {
                 layList.tableList('userList',"{:Url('getponitlist')}",function () {
                     return [
                     return [
-                        {field: 'id', title: '编号', sort: true,event:'uid'},
+                        {field: 'id', title: 'ID', sort: true,event:'uid',width:'8%'},
                         {field: 'title', title: '标题' },
                         {field: 'title', title: '标题' },
                         {field: 'balance', title: '积分余量',sort:true,event:'now_money'},
                         {field: 'balance', title: '积分余量',sort:true,event:'now_money'},
                         {field: 'number', title: '明细数字',sort:true},
                         {field: 'number', title: '明细数字',sort:true},

+ 1 - 1
application/admin/view/wechat/reply/keyword.php

@@ -64,7 +64,7 @@
                                 {/switch}
                                 {/switch}
                             </td>
                             </td>
 
 
-                            <td class="text-center">
+                            <td class="text-right">
                                 <button class="btn btn-info btn-xs" type="button"  onclick="window.location.href='{:Url('info_keyword',array('key'=>$vo['key']))}'" ><i class="fa fa-paste"></i> 编辑</button>
                                 <button class="btn btn-info btn-xs" type="button"  onclick="window.location.href='{:Url('info_keyword',array('key'=>$vo['key']))}'" ><i class="fa fa-paste"></i> 编辑</button>
                                 <button class="btn btn-warning btn-xs" data-url="{:Url('delete',array('id'=>$vo['id']))}" type="button"><i class="fa fa-warning"></i> 删除
                                 <button class="btn btn-warning btn-xs" data-url="{:Url('delete',array('id'=>$vo['id']))}" type="button"><i class="fa fa-warning"></i> 删除
                                 </button>
                                 </button>

+ 4 - 3
application/wap/model/store/StoreCart.php

@@ -99,14 +99,15 @@ class StoreCart extends ModelBasic
         foreach ($list as $k=>$cart) {
         foreach ($list as $k=>$cart) {
             if ($cart['seckill_id']) {
             if ($cart['seckill_id']) {
                 $product = StoreSeckill::field($seckillInfoField)
                 $product = StoreSeckill::field($seckillInfoField)
-                    ->find($cart['seckill_id'])->toArray();
+                    ->find($cart['seckill_id']);
             }elseif($cart['bargain_id']){
             }elseif($cart['bargain_id']){
                 $product = StoreBargain::field($bargainInfoField)
                 $product = StoreBargain::field($bargainInfoField)
-                    ->find($cart['bargain_id'])->toArray();
+                    ->find($cart['bargain_id']);
             }else{
             }else{
                 $product = StoreProduct::field($productInfoField)
                 $product = StoreProduct::field($productInfoField)
-                    ->find($cart['product_id'])->toArray();
+                    ->find($cart['product_id']);
             }
             }
+            if(!empty($product)) $product = $product->toArray();
             $cart['productInfo'] = $product;
             $cart['productInfo'] = $product;
             //商品不存在
             //商品不存在
             if (!$product) {
             if (!$product) {

Разница между файлами не показана из-за своего большого размера
+ 9 - 21
extend/service/WechatService.php


+ 106 - 56
public/system/css/layui-admin.css

@@ -1,4 +1,11 @@
 @charset "UTF-8";
 @charset "UTF-8";
+.layui-btn {
+    background-color: #0092DC;
+}
+.layui-btn-primary:hover {
+    border-color: #0092DC;
+    color: #333;
+}
 .layui-table-box{
 .layui-table-box{
     overflow: initial;
     overflow: initial;
 }
 }
@@ -11,44 +18,14 @@
 .table-responsive{
 .table-responsive{
     overflow: initial;
     overflow: initial;
 }
 }
-.layui-table img{width: 100% !important;}
-/*
-部分样式重构
- */
-.layui-form-pane .layui-input, .layui-select, .layui-textarea {
-    height: 32px;
-    line-height: 1.5;
-    padding: 4px 7px;
-    font-size: 12px;
-    border: 1px solid #dddee1;
-    color: #495060;
-    background-color: #fff;
+/*.layui-table img{width: 100% !important;}*/
+/*部分样式重构*/
+.layui-laypage-limits select{
+    height: 26px;
 }
 }
 .layui-card-body {
 .layui-card-body {
 }
 }
-.layui-form-pane{
-    /*padding: 20px;*/
-}
-.layui-form-pane .layui-form-label {
-    padding: 5px 15px;
-    height: 32px;
-}
-.layui-fluid {
-    padding: 0;
-}
-.layui-btn-normal{
-    background-color:#0092DC;
-}
-.layui-btn .layui-icon {
-    font-size: 12px;
-}
-.layui-btn-sm i {
-    font-size: 12px!important;
-}
-.layui-form-onswitch {
-    border-color: #0092DC;
-    background-color: #0092DC;
-}
+
 .layui-table-cell p{
 .layui-table-cell p{
     height: 20px;
     height: 20px;
     line-height: 20px;
     line-height: 20px;
@@ -58,6 +35,10 @@
     width: 14px;
     width: 14px;
     height: 14px;
     height: 14px;
 }
 }
+
+.layui-laypage a, .layui-laypage button, .layui-laypage input, .layui-laypage select, .layui-laypage span {
+    color:#333 !important;
+}
 .layui-form-checked[lay-skin=primary] i {
 .layui-form-checked[lay-skin=primary] i {
     border-color: #0093DE;
     border-color: #0093DE;
     background-color: #0093DE;
     background-color: #0093DE;
@@ -73,23 +54,6 @@
 .layui-tab-title .layui-this:after{
 .layui-tab-title .layui-this:after{
     border-bottom: 2px solid #0092DC !important;
     border-bottom: 2px solid #0092DC !important;
 }
 }
-.layui-form-label{
-    width: auto;
-}
-.layui-table-cell {
-    white-space:normal;
-    height: auto!important;
-}
-.layui-input-block .layui-admin-input{
-    width: 50%;
-    height: 34px;
-}
-.layui-form-item{
-    margin-bottom: 0;
-}
-.layui-input-block .time-w{
-    width: 200px;
-}
 
 
 .layui-btn-group button i{
 .layui-btn-group button i{
     line-height: 30px;
     line-height: 30px;
@@ -99,11 +63,8 @@
 .back-f8{
 .back-f8{
     background-color: #F8F8F8;
     background-color: #F8F8F8;
 }
 }
-.layui-input-block button{
-    border: 1px solid #C9C9C9;
-}
 .layui-card-body p.layuiadmin-big-font {
 .layui-card-body p.layuiadmin-big-font {
-    font-size: 36px;
+    font-size: 24px;
     color: #666;
     color: #666;
     line-height: 36px;
     line-height: 36px;
     padding: 5px 0 10px;
     padding: 5px 0 10px;
@@ -184,3 +145,92 @@
 .layadmin-text-center{
 .layadmin-text-center{
     text-align: center;
     text-align: center;
 }
 }
+/*表格样式*/
+.layui-table-view .layui-table td, .layui-table-view .layui-table th {
+    font-size: 13px;
+    font-weight: bolder;
+}
+.layui-table-cell {
+    white-space:normal;
+    height: auto!important;
+    font-size: 13px;
+    font-weight: normal;
+}
+/*form 样式*/
+
+.layui-form-select .layui-input {
+    padding-right: 30px;
+    cursor: pointer;
+    font-size: 12px;
+    height: 32px;
+}
+.layui-form-select dl {
+    top: 32px;
+    font-size: 12px;
+}
+.layui-form-select dl dd.layui-this {
+    background-color: #0092DC;
+    color: #fff;
+}
+.layui-input{
+    height: 32px;
+    font-size: 12px;
+}
+.layui-input-block .layui-admin-input{
+    width: 50%;
+    font-size: 12px;
+    height: 32px;
+}
+.layui-form-item{
+    margin-bottom: 0;
+}
+.layui-input-block .time-w{
+    width: 200px;
+}
+.layui-form-pane .layui-input, .layui-select, .layui-textarea {
+    height: 34px;
+    line-height: 1.5;
+    padding: 4px 12px;
+    font-size: 12px;
+    border: 1px solid #e5e6e7;
+    color: #333;
+    background-color: #fff;
+}
+.layui-form-pane{
+    /*padding: 20px;*/
+}
+.layui-form-pane .layui-inline .layui-form-label {
+    padding: 5px 15px;
+    height: 34px;
+    line-height: 24px;
+    background: none;
+    border-radius: 5px 0 0 5px;
+}
+.layui-form-item .layui-btn{
+    margin-top: -5px;
+}
+.layui-form-label{
+    width: auto;
+    padding: 6px;
+}
+.layui-fluid {
+    padding: 0;
+}
+.layui-btn-normal{
+    background-color:#0092DC;
+}
+.layui-btn .layui-icon {
+    font-size: 12px;
+}
+.layui-btn-sm i {
+    font-size: 12px!important;
+}
+.layui-form-onswitch {
+    border-color: #0092DC;
+    background-color: #0092DC;
+}
+.layui-btn-primary {
+    border: 1px solid #e5e6e7;
+    background-color: #fff;
+    color: #333;
+}

Разница между файлами не показана из-за своего большого размера
+ 89 - 50
thinkphp/library/think/db/Builder.php


+ 65 - 28
thinkphp/library/think/db/Connection.php

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
-// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
@@ -90,6 +90,8 @@ abstract class Connection
         'master_num'      => 1,
         'master_num'      => 1,
         // 指定从服务器序号
         // 指定从服务器序号
         'slave_no'        => '',
         'slave_no'        => '',
+        // 模型写入后自动读取主服务器
+        'read_master'     => false,
         // 是否严格检查字段是否存在
         // 是否严格检查字段是否存在
         'fields_strict'   => true,
         'fields_strict'   => true,
         // 数据返回类型
         // 数据返回类型
@@ -354,15 +356,15 @@ abstract class Connection
             $this->bind = $bind;
             $this->bind = $bind;
         }
         }
 
 
-        // 释放前次的查询结果
-        if (!empty($this->PDOStatement)) {
-            $this->free();
-        }
-
         Db::$queryTimes++;
         Db::$queryTimes++;
         try {
         try {
             // 调试开始
             // 调试开始
             $this->debug(true);
             $this->debug(true);
+
+            // 释放前次的查询结果
+            if (!empty($this->PDOStatement)) {
+                $this->free();
+            }
             // 预处理
             // 预处理
             if (empty($this->PDOStatement)) {
             if (empty($this->PDOStatement)) {
                 $this->PDOStatement = $this->linkID->prepare($sql);
                 $this->PDOStatement = $this->linkID->prepare($sql);
@@ -378,7 +380,7 @@ abstract class Connection
             // 执行查询
             // 执行查询
             $this->PDOStatement->execute();
             $this->PDOStatement->execute();
             // 调试结束
             // 调试结束
-            $this->debug(false);
+            $this->debug(false, '', $master);
             // 返回结果集
             // 返回结果集
             return $this->getResult($pdo, $procedure);
             return $this->getResult($pdo, $procedure);
         } catch (\PDOException $e) {
         } catch (\PDOException $e) {
@@ -386,6 +388,11 @@ abstract class Connection
                 return $this->close()->query($sql, $bind, $master, $pdo);
                 return $this->close()->query($sql, $bind, $master, $pdo);
             }
             }
             throw new PDOException($e, $this->config, $this->getLastsql());
             throw new PDOException($e, $this->config, $this->getLastsql());
+        } catch (\Throwable $e) {
+            if ($this->isBreak($e)) {
+                return $this->close()->query($sql, $bind, $master, $pdo);
+            }
+            throw $e;
         } catch (\Exception $e) {
         } catch (\Exception $e) {
             if ($this->isBreak($e)) {
             if ($this->isBreak($e)) {
                 return $this->close()->query($sql, $bind, $master, $pdo);
                 return $this->close()->query($sql, $bind, $master, $pdo);
@@ -397,13 +404,14 @@ abstract class Connection
     /**
     /**
      * 执行语句
      * 执行语句
      * @access public
      * @access public
-     * @param string        $sql sql指令
-     * @param array         $bind 参数绑定
+     * @param  string        $sql sql指令
+     * @param  array         $bind 参数绑定
+     * @param  Query         $query 查询对象
      * @return int
      * @return int
      * @throws PDOException
      * @throws PDOException
      * @throws \Exception
      * @throws \Exception
      */
      */
-    public function execute($sql, $bind = [])
+    public function execute($sql, $bind = [], Query $query = null)
     {
     {
         $this->initConnect(true);
         $this->initConnect(true);
         if (!$this->linkID) {
         if (!$this->linkID) {
@@ -416,15 +424,15 @@ abstract class Connection
             $this->bind = $bind;
             $this->bind = $bind;
         }
         }
 
 
-        //释放前次的查询结果
-        if (!empty($this->PDOStatement) && $this->PDOStatement->queryString != $sql) {
-            $this->free();
-        }
-
         Db::$executeTimes++;
         Db::$executeTimes++;
         try {
         try {
             // 调试开始
             // 调试开始
             $this->debug(true);
             $this->debug(true);
+
+            //释放前次的查询结果
+            if (!empty($this->PDOStatement) && $this->PDOStatement->queryString != $sql) {
+                $this->free();
+            }
             // 预处理
             // 预处理
             if (empty($this->PDOStatement)) {
             if (empty($this->PDOStatement)) {
                 $this->PDOStatement = $this->linkID->prepare($sql);
                 $this->PDOStatement = $this->linkID->prepare($sql);
@@ -440,18 +448,27 @@ abstract class Connection
             // 执行语句
             // 执行语句
             $this->PDOStatement->execute();
             $this->PDOStatement->execute();
             // 调试结束
             // 调试结束
-            $this->debug(false);
+            $this->debug(false, '', true);
+
+            if ($query && !empty($this->config['deploy']) && !empty($this->config['read_master'])) {
+                $query->readMaster();
+            }
 
 
             $this->numRows = $this->PDOStatement->rowCount();
             $this->numRows = $this->PDOStatement->rowCount();
             return $this->numRows;
             return $this->numRows;
         } catch (\PDOException $e) {
         } catch (\PDOException $e) {
             if ($this->isBreak($e)) {
             if ($this->isBreak($e)) {
-                return $this->close()->execute($sql, $bind);
+                return $this->close()->execute($sql, $bind, $query);
             }
             }
             throw new PDOException($e, $this->config, $this->getLastsql());
             throw new PDOException($e, $this->config, $this->getLastsql());
+        } catch (\Throwable $e) {
+            if ($this->isBreak($e)) {
+                return $this->close()->execute($sql, $bind, $query);
+            }
+            throw $e;
         } catch (\Exception $e) {
         } catch (\Exception $e) {
             if ($this->isBreak($e)) {
             if ($this->isBreak($e)) {
-                return $this->close()->execute($sql, $bind);
+                return $this->close()->execute($sql, $bind, $query);
             }
             }
             throw $e;
             throw $e;
         }
         }
@@ -466,6 +483,10 @@ abstract class Connection
      */
      */
     public function getRealSql($sql, array $bind = [])
     public function getRealSql($sql, array $bind = [])
     {
     {
+        if (is_array($sql)) {
+            $sql = implode(';', $sql);
+        }
+
         foreach ($bind as $key => $val) {
         foreach ($bind as $key => $val) {
             $value = is_array($val) ? $val[0] : $val;
             $value = is_array($val) ? $val[0] : $val;
             $type  = is_array($val) ? $val[1] : PDO::PARAM_STR;
             $type  = is_array($val) ? $val[1] : PDO::PARAM_STR;
@@ -478,8 +499,8 @@ abstract class Connection
             $sql = is_numeric($key) ?
             $sql = is_numeric($key) ?
             substr_replace($sql, $value, strpos($sql, '?'), 1) :
             substr_replace($sql, $value, strpos($sql, '?'), 1) :
             str_replace(
             str_replace(
-                [':' . $key . ')', ':' . $key . ',', ':' . $key . ' '],
-                [$value . ')', $value . ',', $value . ' '],
+                [':' . $key . ')', ':' . $key . ',', ':' . $key . ' ', ':' . $key . PHP_EOL],
+                [$value . ')', $value . ',', $value . ' ', $value . PHP_EOL],
                 $sql . ' ');
                 $sql . ' ');
         }
         }
         return rtrim($sql);
         return rtrim($sql);
@@ -648,6 +669,11 @@ abstract class Connection
                 return $this->close()->startTrans();
                 return $this->close()->startTrans();
             }
             }
             throw $e;
             throw $e;
+        } catch (\Error $e) {
+            if ($this->isBreak($e)) {
+                return $this->close()->startTrans();
+            }
+            throw $e;
         }
         }
     }
     }
 
 
@@ -725,7 +751,7 @@ abstract class Connection
      * @param array $sqlArray SQL批处理指令
      * @param array $sqlArray SQL批处理指令
      * @return boolean
      * @return boolean
      */
      */
-    public function batchQuery($sqlArray = [])
+    public function batchQuery($sqlArray = [], $bind = [], Query $query = null)
     {
     {
         if (!is_array($sqlArray)) {
         if (!is_array($sqlArray)) {
             return false;
             return false;
@@ -734,7 +760,7 @@ abstract class Connection
         $this->startTrans();
         $this->startTrans();
         try {
         try {
             foreach ($sqlArray as $sql) {
             foreach ($sqlArray as $sql) {
-                $this->execute($sql);
+                $this->execute($sql, $bind, $query);
             }
             }
             // 提交事务
             // 提交事务
             $this->commit();
             $this->commit();
@@ -742,6 +768,7 @@ abstract class Connection
             $this->rollback();
             $this->rollback();
             throw $e;
             throw $e;
         }
         }
+
         return true;
         return true;
     }
     }
 
 
@@ -803,6 +830,7 @@ abstract class Connection
             'SSL connection has been closed unexpectedly',
             'SSL connection has been closed unexpectedly',
             'Error writing data to the connection',
             'Error writing data to the connection',
             'Resource deadlock avoided',
             'Resource deadlock avoided',
+            'failed with errno',
         ];
         ];
 
 
         $error = $e->getMessage();
         $error = $e->getMessage();
@@ -883,9 +911,10 @@ abstract class Connection
      * @access protected
      * @access protected
      * @param boolean $start 调试开始标记 true 开始 false 结束
      * @param boolean $start 调试开始标记 true 开始 false 结束
      * @param string  $sql 执行的SQL语句 留空自动获取
      * @param string  $sql 执行的SQL语句 留空自动获取
+     * @param boolean $master 主从标记
      * @return void
      * @return void
      */
      */
-    protected function debug($start, $sql = '')
+    protected function debug($start, $sql = '', $master = false)
     {
     {
         if (!empty($this->config['debug'])) {
         if (!empty($this->config['debug'])) {
             // 开启数据库调试模式
             // 开启数据库调试模式
@@ -902,7 +931,7 @@ abstract class Connection
                     $result = $this->getExplain($sql);
                     $result = $this->getExplain($sql);
                 }
                 }
                 // SQL监听
                 // SQL监听
-                $this->trigger($sql, $runtime, $result);
+                $this->trigger($sql, $runtime, $result, $master);
             }
             }
         }
         }
     }
     }
@@ -924,19 +953,27 @@ abstract class Connection
      * @param string    $sql SQL语句
      * @param string    $sql SQL语句
      * @param float     $runtime SQL运行时间
      * @param float     $runtime SQL运行时间
      * @param mixed     $explain SQL分析
      * @param mixed     $explain SQL分析
-     * @return bool
+     * @param  bool     $master 主从标记
+     * @return void
      */
      */
-    protected function trigger($sql, $runtime, $explain = [])
+    protected function trigger($sql, $runtime, $explain = [], $master = false)
     {
     {
         if (!empty(self::$event)) {
         if (!empty(self::$event)) {
             foreach (self::$event as $callback) {
             foreach (self::$event as $callback) {
                 if (is_callable($callback)) {
                 if (is_callable($callback)) {
-                    call_user_func_array($callback, [$sql, $runtime, $explain]);
+                    call_user_func_array($callback, [$sql, $runtime, $explain, $master]);
                 }
                 }
             }
             }
         } else {
         } else {
             // 未注册监听则记录到日志中
             // 未注册监听则记录到日志中
-            Log::record('[ SQL ] ' . $sql . ' [ RunTime:' . $runtime . 's ]', 'sql');
+            if ($this->config['deploy']) {
+                // 分布式记录当前操作的主从
+                $master = $master ? 'master|' : 'slave|';
+            } else {
+                $master = '';
+            }
+
+            Log::record('[ SQL ] ' . $sql . ' [ ' . $master . 'RunTime:' . $runtime . 's ]', 'sql');
             if (!empty($explain)) {
             if (!empty($explain)) {
                 Log::record('[ EXPLAIN : ' . var_export($explain, true) . ' ]', 'sql');
                 Log::record('[ EXPLAIN : ' . var_export($explain, true) . ' ]', 'sql');
             }
             }

+ 48 - 0
thinkphp/library/think/db/Expression.php

@@ -0,0 +1,48 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+namespace think\db;
+
+class Expression
+{
+    /**
+     * 查询表达式
+     *
+     * @var string
+     */
+    protected $value;
+
+    /**
+     * 创建一个查询表达式
+     *
+     * @param  string  $value
+     * @return void
+     */
+    public function __construct($value)
+    {
+        $this->value = $value;
+    }
+
+    /**
+     * 获取表达式
+     *
+     * @return string
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+
+    public function __toString()
+    {
+        return (string) $this->value;
+    }
+}

+ 330 - 159
thinkphp/library/think/db/Query.php

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
-// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
@@ -53,14 +53,16 @@ class Query
     protected static $info = [];
     protected static $info = [];
     // 回调事件
     // 回调事件
     private static $event = [];
     private static $event = [];
+    // 读取主库
+    private static $readMaster = [];
 
 
     /**
     /**
      * 构造函数
      * 构造函数
      * @access public
      * @access public
      * @param Connection $connection 数据库对象实例
      * @param Connection $connection 数据库对象实例
-     * @param string     $model      模型名
+     * @param Model      $model      模型对象
      */
      */
-    public function __construct(Connection $connection = null, $model = '')
+    public function __construct(Connection $connection = null, $model = null)
     {
     {
         $this->connection = $connection ?: Db::connect([], true);
         $this->connection = $connection ?: Db::connect([], true);
         $this->prefix     = $this->connection->getConfig('prefix');
         $this->prefix     = $this->connection->getConfig('prefix');
@@ -131,15 +133,34 @@ class Query
     }
     }
 
 
     /**
     /**
-     * 获取当前的模型对象
+     * 获取当前的模型对象实例
      * @access public
      * @access public
-     * @return string
+     * @return Model|null
      */
      */
     public function getModel()
     public function getModel()
     {
     {
         return $this->model;
         return $this->model;
     }
     }
 
 
+    /**
+     * 设置后续从主库读取数据
+     * @access public
+     * @param  bool $allTable
+     * @return void
+     */
+    public function readMaster($allTable = false)
+    {
+        if ($allTable) {
+            $table = '*';
+        } else {
+            $table = isset($this->options['table']) ? $this->options['table'] : $this->getTable();
+        }
+
+        static::$readMaster[$table] = true;
+
+        return $this;
+    }
+
     /**
     /**
      * 获取当前的builder实例对象
      * 获取当前的builder实例对象
      * @access public
      * @access public
@@ -238,7 +259,7 @@ class Query
      */
      */
     public function execute($sql, $bind = [])
     public function execute($sql, $bind = [])
     {
     {
-        return $this->connection->execute($sql, $bind);
+        return $this->connection->execute($sql, $bind, $this);
     }
     }
 
 
     /**
     /**
@@ -312,9 +333,9 @@ class Query
      * @param array $sql SQL批处理指令
      * @param array $sql SQL批处理指令
      * @return boolean
      * @return boolean
      */
      */
-    public function batchQuery($sql = [])
+    public function batchQuery($sql = [], $bind = [])
     {
     {
-        return $this->connection->batchQuery($sql);
+        return $this->connection->batchQuery($sql, $bind);
     }
     }
 
 
     /**
     /**
@@ -403,7 +424,7 @@ class Query
             if (empty($this->options['table'])) {
             if (empty($this->options['table'])) {
                 $this->options['table'] = $this->getTable();
                 $this->options['table'] = $this->getTable();
             }
             }
-            $key    = is_string($cache['key']) ? $cache['key'] : md5($field . serialize($this->options) . serialize($this->bind));
+            $key    = is_string($cache['key']) ? $cache['key'] : md5($this->connection->getConfig('database') . '.' . $field . serialize($this->options) . serialize($this->bind));
             $result = Cache::get($key);
             $result = Cache::get($key);
         }
         }
         if (false === $result) {
         if (false === $result) {
@@ -420,7 +441,7 @@ class Query
                 $result += 0;
                 $result += 0;
             }
             }
 
 
-            if (isset($cache)) {
+            if (isset($cache) && false !== $result) {
                 // 缓存数据
                 // 缓存数据
                 $this->cacheData($key, $result, $cache);
                 $this->cacheData($key, $result, $cache);
             }
             }
@@ -447,7 +468,7 @@ class Query
             if (empty($this->options['table'])) {
             if (empty($this->options['table'])) {
                 $this->options['table'] = $this->getTable();
                 $this->options['table'] = $this->getTable();
             }
             }
-            $guid   = is_string($cache['key']) ? $cache['key'] : md5($field . serialize($this->options) . serialize($this->bind));
+            $guid   = is_string($cache['key']) ? $cache['key'] : md5($this->connection->getConfig('database') . '.' . $field . serialize($this->options) . serialize($this->bind));
             $result = Cache::get($guid);
             $result = Cache::get($guid);
         }
         }
         if (false === $result) {
         if (false === $result) {
@@ -534,22 +555,24 @@ class Query
      * MIN查询
      * MIN查询
      * @access public
      * @access public
      * @param string $field 字段名
      * @param string $field 字段名
+     * @param bool   $force   强制转为数字类型
      * @return mixed
      * @return mixed
      */
      */
-    public function min($field)
+    public function min($field, $force = true)
     {
     {
-        return $this->value('MIN(' . $field . ') AS tp_min', 0, true);
+        return $this->value('MIN(' . $field . ') AS tp_min', 0, $force);
     }
     }
 
 
     /**
     /**
      * MAX查询
      * MAX查询
      * @access public
      * @access public
      * @param string $field 字段名
      * @param string $field 字段名
+     * @param bool   $force   强制转为数字类型
      * @return mixed
      * @return mixed
      */
      */
-    public function max($field)
+    public function max($field, $force = true)
     {
     {
-        return $this->value('MAX(' . $field . ') AS tp_max', 0, true);
+        return $this->value('MAX(' . $field . ') AS tp_max', 0, $force);
     }
     }
 
 
     /**
     /**
@@ -607,7 +630,7 @@ class Query
                 return true;
                 return true;
             }
             }
         }
         }
-        return $this->setField($field, ['exp', $field . '+' . $step]);
+        return $this->setField($field, ['inc', $step]);
     }
     }
 
 
     /**
     /**
@@ -635,8 +658,9 @@ class Query
                 $this->options = [];
                 $this->options = [];
                 return true;
                 return true;
             }
             }
+            return $this->setField($field, ['inc', $step]);
         }
         }
-        return $this->setField($field, ['exp', $field . '-' . $step]);
+        return $this->setField($field, ['dec', $step]);
     }
     }
 
 
     /**
     /**
@@ -704,7 +728,8 @@ class Query
     {
     {
         // 传入的表名为数组
         // 传入的表名为数组
         if (is_array($join)) {
         if (is_array($join)) {
-            list($table, $alias) = each($join);
+            $table = $join;
+            $alias = array_shift($join);
         } else {
         } else {
             $join = trim($join);
             $join = trim($join);
             if (false !== strpos($join, '(')) {
             if (false !== strpos($join, '(')) {
@@ -725,13 +750,9 @@ class Query
                     $table = $this->getTable($table);
                     $table = $this->getTable($table);
                 }
                 }
             }
             }
-        }
-        if (isset($alias)) {
-            if (isset($this->options['alias'][$table])) {
-                $table = $table . '@think' . uniqid();
+            if (isset($alias) && $table != $alias) {
+                $table = [$table => $alias];
             }
             }
-            $table = [$table => $alias];
-            $this->alias($table);
         }
         }
         return $table;
         return $table;
     }
     }
@@ -769,8 +790,15 @@ class Query
     {
     {
         if (empty($field)) {
         if (empty($field)) {
             return $this;
             return $this;
+        } elseif ($field instanceof Expression) {
+            $this->options['field'][] = $field;
+            return $this;
         }
         }
+
         if (is_string($field)) {
         if (is_string($field)) {
+            if (preg_match('/[\<\'\"\(]/', $field)) {
+                return $this->fieldRaw($field);
+            }
             $field = array_map('trim', explode(',', $field));
             $field = array_map('trim', explode(',', $field));
         }
         }
         if (true === $field) {
         if (true === $field) {
@@ -794,12 +822,30 @@ class Query
         }
         }
 
 
         if (isset($this->options['field'])) {
         if (isset($this->options['field'])) {
-            $field = array_merge($this->options['field'], $field);
+            $field = array_merge((array) $this->options['field'], $field);
         }
         }
         $this->options['field'] = array_unique($field);
         $this->options['field'] = array_unique($field);
         return $this;
         return $this;
     }
     }
 
 
+    /**
+     * 表达式方式指定查询字段
+     * @access public
+     * @param  string $field    字段名
+     * @param  array  $bind     参数绑定
+     * @return $this
+     */
+    public function fieldRaw($field, array $bind = [])
+    {
+        $this->options['field'][] = $this->raw($field);
+
+        if ($bind) {
+            $this->bind($bind);
+        }
+
+        return $this;
+    }
+
     /**
     /**
      * 设置数据
      * 设置数据
      * @access public
      * @access public
@@ -828,7 +874,7 @@ class Query
     {
     {
         $fields = is_string($field) ? explode(',', $field) : $field;
         $fields = is_string($field) ? explode(',', $field) : $field;
         foreach ($fields as $field) {
         foreach ($fields as $field) {
-            $this->data($field, ['exp', $field . '+' . $step]);
+            $this->data($field, ['inc', $step]);
         }
         }
         return $this;
         return $this;
     }
     }
@@ -844,7 +890,7 @@ class Query
     {
     {
         $fields = is_string($field) ? explode(',', $field) : $field;
         $fields = is_string($field) ? explode(',', $field) : $field;
         foreach ($fields as $field) {
         foreach ($fields as $field) {
-            $this->data($field, ['exp', $field . '-' . $step]);
+            $this->data($field, ['dec', $step]);
         }
         }
         return $this;
         return $this;
     }
     }
@@ -858,25 +904,36 @@ class Query
      */
      */
     public function exp($field, $value)
     public function exp($field, $value)
     {
     {
-        $this->data($field, ['exp', $value]);
+        $this->data($field, $this->raw($value));
         return $this;
         return $this;
     }
     }
 
 
+    /**
+     * 使用表达式设置数据
+     * @access public
+     * @param  mixed $value 表达式
+     * @return Expression
+     */
+    public function raw($value)
+    {
+        return new Expression($value);
+    }
+
     /**
     /**
      * 指定JOIN查询字段
      * 指定JOIN查询字段
      * @access public
      * @access public
      * @param string|array $table 数据表
      * @param string|array $table 数据表
      * @param string|array $field 查询字段
      * @param string|array $field 查询字段
-     * @param string|array $on    JOIN条件
+     * @param mixed        $on    JOIN条件
      * @param string       $type  JOIN类型
      * @param string       $type  JOIN类型
      * @return $this
      * @return $this
      */
      */
     public function view($join, $field = true, $on = null, $type = 'INNER')
     public function view($join, $field = true, $on = null, $type = 'INNER')
     {
     {
         $this->options['view'] = true;
         $this->options['view'] = true;
-        if (is_array($join) && key($join) !== 0) {
+        if (is_array($join) && key($join) === 0) {
             foreach ($join as $key => $val) {
             foreach ($join as $key => $val) {
-                $this->view($key, $val[0], isset($val[1]) ? $val[1] : null, isset($val[2]) ? $val[2] : 'INNER');
+                $this->view($val[0], $val[1], isset($val[2]) ? $val[2] : null, isset($val[3]) ? $val[3] : 'INNER');
             }
             }
         } else {
         } else {
             $fields = [];
             $fields = [];
@@ -975,6 +1032,37 @@ class Query
         return $this;
         return $this;
     }
     }
 
 
+    /**
+     * 指定表达式查询条件
+     * @access public
+     * @param  string $where  查询条件
+     * @param  array  $bind   参数绑定
+     * @param  string $logic  查询逻辑 and or xor
+     * @return $this
+     */
+    public function whereRaw($where, $bind = [], $logic = 'AND')
+    {
+        $this->options['where'][$logic][] = $this->raw($where);
+
+        if ($bind) {
+            $this->bind($bind);
+        }
+
+        return $this;
+    }
+
+    /**
+     * 指定表达式查询条件 OR
+     * @access public
+     * @param  string $where  查询条件
+     * @param  array  $bind   参数绑定
+     * @return $this
+     */
+    public function whereOrRaw($where, $bind = [])
+    {
+        return $this->whereRaw($where, $bind, 'OR');
+    }
+
     /**
     /**
      * 指定Null查询条件
      * 指定Null查询条件
      * @access public
      * @access public
@@ -984,7 +1072,7 @@ class Query
      */
      */
     public function whereNull($field, $logic = 'AND')
     public function whereNull($field, $logic = 'AND')
     {
     {
-        $this->parseWhereExp($logic, $field, 'null', null);
+        $this->parseWhereExp($logic, $field, 'null', null, [], true);
         return $this;
         return $this;
     }
     }
 
 
@@ -997,7 +1085,7 @@ class Query
      */
      */
     public function whereNotNull($field, $logic = 'AND')
     public function whereNotNull($field, $logic = 'AND')
     {
     {
-        $this->parseWhereExp($logic, $field, 'notnull', null);
+        $this->parseWhereExp($logic, $field, 'notnull', null, [], true);
         return $this;
         return $this;
     }
     }
 
 
@@ -1037,7 +1125,7 @@ class Query
      */
      */
     public function whereIn($field, $condition, $logic = 'AND')
     public function whereIn($field, $condition, $logic = 'AND')
     {
     {
-        $this->parseWhereExp($logic, $field, 'in', $condition);
+        $this->parseWhereExp($logic, $field, 'in', $condition, [], true);
         return $this;
         return $this;
     }
     }
 
 
@@ -1051,7 +1139,7 @@ class Query
      */
      */
     public function whereNotIn($field, $condition, $logic = 'AND')
     public function whereNotIn($field, $condition, $logic = 'AND')
     {
     {
-        $this->parseWhereExp($logic, $field, 'not in', $condition);
+        $this->parseWhereExp($logic, $field, 'not in', $condition, [], true);
         return $this;
         return $this;
     }
     }
 
 
@@ -1065,7 +1153,7 @@ class Query
      */
      */
     public function whereLike($field, $condition, $logic = 'AND')
     public function whereLike($field, $condition, $logic = 'AND')
     {
     {
-        $this->parseWhereExp($logic, $field, 'like', $condition);
+        $this->parseWhereExp($logic, $field, 'like', $condition, [], true);
         return $this;
         return $this;
     }
     }
 
 
@@ -1079,7 +1167,7 @@ class Query
      */
      */
     public function whereNotLike($field, $condition, $logic = 'AND')
     public function whereNotLike($field, $condition, $logic = 'AND')
     {
     {
-        $this->parseWhereExp($logic, $field, 'not like', $condition);
+        $this->parseWhereExp($logic, $field, 'not like', $condition, [], true);
         return $this;
         return $this;
     }
     }
 
 
@@ -1093,7 +1181,7 @@ class Query
      */
      */
     public function whereBetween($field, $condition, $logic = 'AND')
     public function whereBetween($field, $condition, $logic = 'AND')
     {
     {
-        $this->parseWhereExp($logic, $field, 'between', $condition);
+        $this->parseWhereExp($logic, $field, 'between', $condition, [], true);
         return $this;
         return $this;
     }
     }
 
 
@@ -1107,7 +1195,7 @@ class Query
      */
      */
     public function whereNotBetween($field, $condition, $logic = 'AND')
     public function whereNotBetween($field, $condition, $logic = 'AND')
     {
     {
-        $this->parseWhereExp($logic, $field, 'not between', $condition);
+        $this->parseWhereExp($logic, $field, 'not between', $condition, [], true);
         return $this;
         return $this;
     }
     }
 
 
@@ -1121,7 +1209,7 @@ class Query
      */
      */
     public function whereExp($field, $condition, $logic = 'AND')
     public function whereExp($field, $condition, $logic = 'AND')
     {
     {
-        $this->parseWhereExp($logic, $field, 'exp', $condition);
+        $this->parseWhereExp($logic, $field, 'exp', $this->raw($condition), [], true);
         return $this;
         return $this;
     }
     }
 
 
@@ -1148,9 +1236,10 @@ class Query
      * @param mixed                 $op        查询表达式
      * @param mixed                 $op        查询表达式
      * @param mixed                 $condition 查询条件
      * @param mixed                 $condition 查询条件
      * @param array                 $param     查询参数
      * @param array                 $param     查询参数
+     * @param  bool                 $strict    严格模式
      * @return void
      * @return void
      */
      */
-    protected function parseWhereExp($logic, $field, $op, $condition, $param = [])
+    protected function parseWhereExp($logic, $field, $op, $condition, $param = [], $strict = false)
     {
     {
         $logic = strtoupper($logic);
         $logic = strtoupper($logic);
         if ($field instanceof \Closure) {
         if ($field instanceof \Closure) {
@@ -1161,8 +1250,17 @@ class Query
         if (is_string($field) && !empty($this->options['via']) && !strpos($field, '.')) {
         if (is_string($field) && !empty($this->options['via']) && !strpos($field, '.')) {
             $field = $this->options['via'] . '.' . $field;
             $field = $this->options['via'] . '.' . $field;
         }
         }
-        if (is_string($field) && preg_match('/[,=\>\<\'\"\(\s]/', $field)) {
-            $where[] = ['exp', $field];
+
+        if ($field instanceof Expression) {
+            return $this->whereRaw($field, is_array($op) ? $op : []);
+        } elseif ($strict) {
+            // 使用严格模式查询
+            $where[$field] = [$op, $condition];
+
+            // 记录一个字段多次查询条件
+            $this->options['multi'][$logic][$field][] = $where[$field];
+        } elseif (is_string($field) && preg_match('/[,=\>\<\'\"\(\s]/', $field)) {
+            $where[] = ['exp', $this->raw($field)];
             if (is_array($op)) {
             if (is_array($op)) {
                 // 参数绑定
                 // 参数绑定
                 $this->bind($op);
                 $this->bind($op);
@@ -1183,21 +1281,28 @@ class Query
             $where[$field] = $param;
             $where[$field] = $param;
         } elseif (in_array(strtolower($op), ['null', 'notnull', 'not null'])) {
         } elseif (in_array(strtolower($op), ['null', 'notnull', 'not null'])) {
             // null查询
             // null查询
-            $where[$field]                            = [$op, ''];
+            $where[$field] = [$op, ''];
+
             $this->options['multi'][$logic][$field][] = $where[$field];
             $this->options['multi'][$logic][$field][] = $where[$field];
         } elseif (is_null($condition)) {
         } elseif (is_null($condition)) {
             // 字段相等查询
             // 字段相等查询
-            $where[$field]                            = ['eq', $op];
+            $where[$field] = ['eq', $op];
+
             $this->options['multi'][$logic][$field][] = $where[$field];
             $this->options['multi'][$logic][$field][] = $where[$field];
         } else {
         } else {
-            $where[$field] = [$op, $condition, isset($param[2]) ? $param[2] : null];
-            if ('exp' == strtolower($op) && isset($param[2]) && is_array($param[2])) {
+            if ('exp' == strtolower($op)) {
+                $where[$field] = ['exp', $this->raw($condition)];
                 // 参数绑定
                 // 参数绑定
-                $this->bind($param[2]);
+                if (isset($param[2]) && is_array($param[2])) {
+                    $this->bind($param[2]);
+                }
+            } else {
+                $where[$field] = [$op, $condition];
             }
             }
             // 记录一个字段多次查询条件
             // 记录一个字段多次查询条件
             $this->options['multi'][$logic][$field][] = $where[$field];
             $this->options['multi'][$logic][$field][] = $where[$field];
         }
         }
+
         if (!empty($where)) {
         if (!empty($where)) {
             if (!isset($this->options['where'][$logic])) {
             if (!isset($this->options['where'][$logic])) {
                 $this->options['where'][$logic] = [];
                 $this->options['where'][$logic] = [];
@@ -1239,6 +1344,7 @@ class Query
         $logic = strtoupper($logic);
         $logic = strtoupper($logic);
         if (isset($this->options['where'][$logic][$field])) {
         if (isset($this->options['where'][$logic][$field])) {
             unset($this->options['where'][$logic][$field]);
             unset($this->options['where'][$logic][$field]);
+            unset($this->options['multi'][$logic][$field]);
         }
         }
         return $this;
         return $this;
     }
     }
@@ -1414,31 +1520,59 @@ class Query
      */
      */
     public function order($field, $order = null)
     public function order($field, $order = null)
     {
     {
-        if (!empty($field)) {
-            if (is_string($field)) {
-                if (!empty($this->options['via'])) {
-                    $field = $this->options['via'] . '.' . $field;
-                }
-                $field = empty($order) ? $field : [$field => $order];
-            } elseif (!empty($this->options['via'])) {
-                foreach ($field as $key => $val) {
-                    if (is_numeric($key)) {
-                        $field[$key] = $this->options['via'] . '.' . $val;
-                    } else {
-                        $field[$this->options['via'] . '.' . $key] = $val;
-                        unset($field[$key]);
-                    }
-                }
-            }
-            if (!isset($this->options['order'])) {
-                $this->options['order'] = [];
+        if (empty($field)) {
+            return $this;
+        } elseif ($field instanceof Expression) {
+            $this->options['order'][] = $field;
+            return $this;
+        }
+
+        if (is_string($field)) {
+            if (!empty($this->options['via'])) {
+                $field = $this->options['via'] . '.' . $field;
             }
             }
-            if (is_array($field)) {
-                $this->options['order'] = array_merge($this->options['order'], $field);
+            if (strpos($field, ',')) {
+                $field = array_map('trim', explode(',', $field));
             } else {
             } else {
-                $this->options['order'][] = $field;
+                $field = empty($order) ? $field : [$field => $order];
+            }
+        } elseif (!empty($this->options['via'])) {
+            foreach ($field as $key => $val) {
+                if (is_numeric($key)) {
+                    $field[$key] = $this->options['via'] . '.' . $val;
+                } else {
+                    $field[$this->options['via'] . '.' . $key] = $val;
+                    unset($field[$key]);
+                }
             }
             }
         }
         }
+        if (!isset($this->options['order'])) {
+            $this->options['order'] = [];
+        }
+        if (is_array($field)) {
+            $this->options['order'] = array_merge($this->options['order'], $field);
+        } else {
+            $this->options['order'][] = $field;
+        }
+
+        return $this;
+    }
+
+    /**
+     * 表达式方式指定Field排序
+     * @access public
+     * @param  string $field 排序字段
+     * @param  array  $bind  参数绑定
+     * @return $this
+     */
+    public function orderRaw($field, array $bind = [])
+    {
+        $this->options['order'][] = $this->raw($field);
+
+        if ($bind) {
+            $this->bind($bind);
+        }
+
         return $this;
         return $this;
     }
     }
 
 
@@ -1523,7 +1657,12 @@ class Query
     {
     {
         if (is_array($alias)) {
         if (is_array($alias)) {
             foreach ($alias as $key => $val) {
             foreach ($alias as $key => $val) {
-                $this->options['alias'][$key] = $val;
+                if (false !== strpos($key, '__')) {
+                    $table = $this->parseSqlTable($key);
+                } else {
+                    $table = $key;
+                }
+                $this->options['alias'][$table] = $val;
             }
             }
         } else {
         } else {
             if (isset($this->options['table'])) {
             if (isset($this->options['table'])) {
@@ -1651,46 +1790,49 @@ class Query
      * 查询日期或者时间
      * 查询日期或者时间
      * @access public
      * @access public
      * @param string       $field 日期字段名
      * @param string       $field 日期字段名
-     * @param string       $op    比较运算符或者表达式
+     * @param string|array $op    比较运算符或者表达式
      * @param string|array $range 比较范围
      * @param string|array $range 比较范围
      * @return $this
      * @return $this
      */
      */
     public function whereTime($field, $op, $range = null)
     public function whereTime($field, $op, $range = null)
     {
     {
         if (is_null($range)) {
         if (is_null($range)) {
-            // 使用日期表达式
-            $date = getdate();
-            switch (strtolower($op)) {
-                case 'today':
-                case 'd':
-                    $range = ['today', 'tomorrow'];
-                    break;
-                case 'week':
-                case 'w':
-                    $range = 'this week 00:00:00';
-                    break;
-                case 'month':
-                case 'm':
-                    $range = mktime(0, 0, 0, $date['mon'], 1, $date['year']);
-                    break;
-                case 'year':
-                case 'y':
-                    $range = mktime(0, 0, 0, 1, 1, $date['year']);
-                    break;
-                case 'yesterday':
-                    $range = ['yesterday', 'today'];
-                    break;
-                case 'last week':
-                    $range = ['last week 00:00:00', 'this week 00:00:00'];
-                    break;
-                case 'last month':
-                    $range = [date('y-m-01', strtotime('-1 month')), mktime(0, 0, 0, $date['mon'], 1, $date['year'])];
-                    break;
-                case 'last year':
-                    $range = [mktime(0, 0, 0, 1, 1, $date['year'] - 1), mktime(0, 0, 0, 1, 1, $date['year'])];
-                    break;
-                default:
-                    $range = $op;
+            if (is_array($op)) {
+                $range = $op;
+            } else {
+                // 使用日期表达式
+                switch (strtolower($op)) {
+                    case 'today':
+                    case 'd':
+                        $range = ['today', 'tomorrow'];
+                        break;
+                    case 'week':
+                    case 'w':
+                        $range = ['this week 00:00:00', 'next week 00:00:00'];
+                        break;
+                    case 'month':
+                    case 'm':
+                        $range = ['first Day of this month 00:00:00', 'first Day of next month 00:00:00'];
+                        break;
+                    case 'year':
+                    case 'y':
+                        $range = ['this year 1/1', 'next year 1/1'];
+                        break;
+                    case 'yesterday':
+                        $range = ['yesterday', 'today'];
+                        break;
+                    case 'last week':
+                        $range = ['last week 00:00:00', 'this week 00:00:00'];
+                        break;
+                    case 'last month':
+                        $range = ['first Day of last month 00:00:00', 'first Day of this month 00:00:00'];
+                        break;
+                    case 'last year':
+                        $range = ['last year 1/1', 'this year 1/1'];
+                        break;
+                    default:
+                        $range = $op;
+                }
             }
             }
             $op = is_array($range) ? 'between' : '>';
             $op = is_array($range) ? 'between' : '>';
         }
         }
@@ -1735,7 +1877,7 @@ class Query
                 $schema = $guid;
                 $schema = $guid;
             }
             }
             // 读取缓存
             // 读取缓存
-            if (is_file(RUNTIME_PATH . 'schema/' . $schema . '.php')) {
+            if (!App::$debug && is_file(RUNTIME_PATH . 'schema/' . $schema . '.php')) {
                 $info = include RUNTIME_PATH . 'schema/' . $schema . '.php';
                 $info = include RUNTIME_PATH . 'schema/' . $schema . '.php';
             } else {
             } else {
                 $info = $this->connection->getFields($guid);
                 $info = $this->connection->getFields($guid);
@@ -1810,7 +1952,9 @@ class Query
      */
      */
     protected function getFieldBindType($type)
     protected function getFieldBindType($type)
     {
     {
-        if (preg_match('/(int|double|float|decimal|real|numeric|serial|bit)/is', $type)) {
+        if (0 === strpos($type, 'set') || 0 === strpos($type, 'enum')) {
+            $bind = PDO::PARAM_STR;
+        } elseif (preg_match('/(int|double|float|decimal|real|numeric|serial|bit)/is', $type)) {
             $bind = PDO::PARAM_INT;
             $bind = PDO::PARAM_INT;
         } elseif (preg_match('/bool/is', $type)) {
         } elseif (preg_match('/bool/is', $type)) {
             $bind = PDO::PARAM_BOOL;
             $bind = PDO::PARAM_BOOL;
@@ -1892,11 +2036,10 @@ class Query
             $with = explode(',', $with);
             $with = explode(',', $with);
         }
         }
 
 
-        $first        = true;
-        $currentModel = $this->model;
+        $first = true;
 
 
         /** @var Model $class */
         /** @var Model $class */
-        $class = new $currentModel;
+        $class = $this->model;
         foreach ($with as $key => $relation) {
         foreach ($with as $key => $relation) {
             $subRelation = '';
             $subRelation = '';
             $closure     = false;
             $closure     = false;
@@ -1955,7 +2098,7 @@ class Query
                     $relation = $key;
                     $relation = $key;
                 }
                 }
                 $relation = Loader::parseName($relation, 1, false);
                 $relation = Loader::parseName($relation, 1, false);
-                $count    = '(' . (new $this->model)->$relation()->getRelationCountQuery($closure) . ')';
+                $count    = '(' . $this->model->$relation()->getRelationCountQuery($closure) . ')';
                 $this->field([$count => Loader::parseName($relation) . '_count']);
                 $this->field([$count => Loader::parseName($relation) . '_count']);
             }
             }
         }
         }
@@ -2082,7 +2225,7 @@ class Query
         }
         }
 
 
         // 执行操作
         // 执行操作
-        $result = 0 === $sql ? 0 : $this->execute($sql, $bind);
+        $result = 0 === $sql ? 0 : $this->execute($sql, $bind, $this);
         if ($result) {
         if ($result) {
             $sequence  = $sequence ?: (isset($options['sequence']) ? $options['sequence'] : null);
             $sequence  = $sequence ?: (isset($options['sequence']) ? $options['sequence'] : null);
             $lastInsId = $this->getLastInsID($sequence);
             $lastInsId = $this->getLastInsID($sequence);
@@ -2118,27 +2261,40 @@ class Query
     /**
     /**
      * 批量插入记录
      * 批量插入记录
      * @access public
      * @access public
-     * @param mixed $dataSet 数据集
-     * @param boolean $replace  是否replace
+     * @param mixed     $dataSet 数据集
+     * @param boolean   $replace  是否replace
+     * @param integer   $limit   每次写入数据限制
      * @return integer|string
      * @return integer|string
      */
      */
-    public function insertAll(array $dataSet, $replace = false)
+    public function insertAll(array $dataSet, $replace = false, $limit = null)
     {
     {
         // 分析查询表达式
         // 分析查询表达式
         $options = $this->parseExpress();
         $options = $this->parseExpress();
         if (!is_array(reset($dataSet))) {
         if (!is_array(reset($dataSet))) {
             return false;
             return false;
         }
         }
+
         // 生成SQL语句
         // 生成SQL语句
-        $sql = $this->builder->insertAll($dataSet, $options, $replace);
+        if (is_null($limit)) {
+            $sql = $this->builder->insertAll($dataSet, $options, $replace);
+        } else {
+            $array = array_chunk($dataSet, $limit, true);
+            foreach ($array as $item) {
+                $sql[] = $this->builder->insertAll($item, $options, $replace);
+            }
+        }
+
         // 获取参数绑定
         // 获取参数绑定
         $bind = $this->getBind();
         $bind = $this->getBind();
         if ($options['fetch_sql']) {
         if ($options['fetch_sql']) {
             // 获取实际执行的SQL语句
             // 获取实际执行的SQL语句
             return $this->connection->getRealSql($sql, $bind);
             return $this->connection->getRealSql($sql, $bind);
+        } elseif (is_array($sql)) {
+            // 执行操作
+            return $this->batchQuery($sql, $bind, $this);
         } else {
         } else {
             // 执行操作
             // 执行操作
-            return $this->execute($sql, $bind);
+            return $this->execute($sql, $bind, $this);
         }
         }
     }
     }
 
 
@@ -2164,7 +2320,7 @@ class Query
             return $this->connection->getRealSql($sql, $bind);
             return $this->connection->getRealSql($sql, $bind);
         } else {
         } else {
             // 执行操作
             // 执行操作
-            return $this->execute($sql, $bind);
+            return $this->execute($sql, $bind, $this);
         }
         }
     }
     }
 
 
@@ -2231,7 +2387,7 @@ class Query
                 Cache::clear($options['cache']['tag']);
                 Cache::clear($options['cache']['tag']);
             }
             }
             // 执行操作
             // 执行操作
-            $result = '' == $sql ? 0 : $this->execute($sql, $bind);
+            $result = '' == $sql ? 0 : $this->execute($sql, $bind, $this);
             if ($result) {
             if ($result) {
                 if (is_string($pk) && isset($where[$pk])) {
                 if (is_string($pk) && isset($where[$pk])) {
                     $data[$pk] = $where[$pk];
                     $data[$pk] = $where[$pk];
@@ -2300,7 +2456,7 @@ class Query
             // 判断查询缓存
             // 判断查询缓存
             $cache = $options['cache'];
             $cache = $options['cache'];
             unset($options['cache']);
             unset($options['cache']);
-            $key       = is_string($cache['key']) ? $cache['key'] : md5(serialize($options) . serialize($this->bind));
+            $key       = is_string($cache['key']) ? $cache['key'] : md5($this->connection->getConfig('database') . '.' . serialize($options) . serialize($this->bind));
             $resultSet = Cache::get($key);
             $resultSet = Cache::get($key);
         }
         }
         if (false === $resultSet) {
         if (false === $resultSet) {
@@ -2334,11 +2490,10 @@ class Query
         // 数据列表读取后的处理
         // 数据列表读取后的处理
         if (!empty($this->model)) {
         if (!empty($this->model)) {
             // 生成模型对象
             // 生成模型对象
-            $modelName = $this->model;
             if (count($resultSet) > 0) {
             if (count($resultSet) > 0) {
                 foreach ($resultSet as $key => $result) {
                 foreach ($resultSet as $key => $result) {
                     /** @var Model $model */
                     /** @var Model $model */
-                    $model = new $modelName($result);
+                    $model = $this->model->newInstance($result);
                     $model->isUpdate(true);
                     $model->isUpdate(true);
 
 
                     // 关联查询
                     // 关联查询
@@ -2358,7 +2513,7 @@ class Query
                 // 模型数据集转换
                 // 模型数据集转换
                 $resultSet = $model->toCollection($resultSet);
                 $resultSet = $model->toCollection($resultSet);
             } else {
             } else {
-                $resultSet = (new $modelName)->toCollection($resultSet);
+                $resultSet = $this->model->toCollection($resultSet);
             }
             }
         } elseif ('collection' == $this->connection->getConfig('resultset_type')) {
         } elseif ('collection' == $this->connection->getConfig('resultset_type')) {
             // 返回Collection对象
             // 返回Collection对象
@@ -2402,10 +2557,16 @@ class Query
         } elseif (is_array($value) && is_string($value[0]) && 'eq' == strtolower($value[0])) {
         } elseif (is_array($value) && is_string($value[0]) && 'eq' == strtolower($value[0])) {
             $data = $value[1];
             $data = $value[1];
         }
         }
+        $prefix = $this->connection->getConfig('database') . '.';
+
         if (isset($data)) {
         if (isset($data)) {
-            return 'think:' . (is_array($options['table']) ? key($options['table']) : $options['table']) . '|' . $data;
-        } else {
-            return md5(serialize($options) . serialize($bind));
+            return 'think:' . $prefix . (is_array($options['table']) ? key($options['table']) : $options['table']) . '|' . $data;
+        }
+
+        try {
+            return md5($prefix . serialize($options) . serialize($bind));
+        } catch (\Exception $e) {
+            throw new Exception('closure not support cache(true)');
         }
         }
     }
     }
 
 
@@ -2442,11 +2603,11 @@ class Query
             // 判断查询缓存
             // 判断查询缓存
             $cache = $options['cache'];
             $cache = $options['cache'];
             if (true === $cache['key'] && !is_null($data) && !is_array($data)) {
             if (true === $cache['key'] && !is_null($data) && !is_array($data)) {
-                $key = 'think:' . (is_array($options['table']) ? key($options['table']) : $options['table']) . '|' . $data;
+                $key = 'think:' . $this->connection->getConfig('database') . '.' . (is_array($options['table']) ? key($options['table']) : $options['table']) . '|' . $data;
             } elseif (is_string($cache['key'])) {
             } elseif (is_string($cache['key'])) {
                 $key = $cache['key'];
                 $key = $cache['key'];
             } elseif (!isset($key)) {
             } elseif (!isset($key)) {
-                $key = md5(serialize($options) . serialize($this->bind));
+                $key = md5($this->connection->getConfig('database') . '.' . serialize($options) . serialize($this->bind));
             }
             }
             $result = Cache::get($key);
             $result = Cache::get($key);
         }
         }
@@ -2484,7 +2645,7 @@ class Query
                 $result = isset($resultSet[0]) ? $resultSet[0] : null;
                 $result = isset($resultSet[0]) ? $resultSet[0] : null;
             }
             }
 
 
-            if (isset($cache) && false !== $result) {
+            if (isset($cache) && $result) {
                 // 缓存数据
                 // 缓存数据
                 $this->cacheData($key, $result, $cache);
                 $this->cacheData($key, $result, $cache);
             }
             }
@@ -2494,8 +2655,7 @@ class Query
         if (!empty($result)) {
         if (!empty($result)) {
             if (!empty($this->model)) {
             if (!empty($this->model)) {
                 // 返回模型对象
                 // 返回模型对象
-                $model  = $this->model;
-                $result = new $model($result);
+                $result = $this->model->newInstance($result);
                 $result->isUpdate(true, isset($options['where']['AND']) ? $options['where']['AND'] : null);
                 $result->isUpdate(true, isset($options['where']['AND']) ? $options['where']['AND'] : null);
                 // 关联查询
                 // 关联查询
                 if (!empty($options['relation'])) {
                 if (!empty($options['relation'])) {
@@ -2526,7 +2686,8 @@ class Query
     protected function throwNotFound($options = [])
     protected function throwNotFound($options = [])
     {
     {
         if (!empty($this->model)) {
         if (!empty($this->model)) {
-            throw new ModelNotFoundException('model data Not Found:' . $this->model, $this->model, $options);
+            $class = get_class($this->model);
+            throw new ModelNotFoundException('model data Not Found:' . $class, $class, $options);
         } else {
         } else {
             $table = is_array($options['table']) ? key($options['table']) : $options['table'];
             $table = is_array($options['table']) ? key($options['table']) : $options['table'];
             throw new DataNotFoundException('table data not Found:' . $table, $table, $options);
             throw new DataNotFoundException('table data not Found:' . $table, $table, $options);
@@ -2574,48 +2735,54 @@ class Query
     public function chunk($count, $callback, $column = null, $order = 'asc')
     public function chunk($count, $callback, $column = null, $order = 'asc')
     {
     {
         $options = $this->getOptions();
         $options = $this->getOptions();
-        if (isset($options['table'])) {
-            $table = is_array($options['table']) ? key($options['table']) : $options['table'];
-        } else {
-            $table = '';
-        }
-        $column = $column ?: $this->getPk($table);
-        if (is_array($column)) {
-            $column = $column[0];
+        if (empty($options['table'])) {
+            $options['table'] = $this->getTable();
         }
         }
+        $column = $column ?: $this->getPk($options);
+
         if (isset($options['order'])) {
         if (isset($options['order'])) {
             if (App::$debug) {
             if (App::$debug) {
                 throw new \LogicException('chunk not support call order');
                 throw new \LogicException('chunk not support call order');
             }
             }
             unset($options['order']);
             unset($options['order']);
         }
         }
-        $bind      = $this->bind;
-        $resultSet = $this->options($options)->limit($count)->order($column, $order)->select();
-        if (strpos($column, '.')) {
-            list($alias, $key) = explode('.', $column);
+        $bind = $this->bind;
+        if (is_array($column)) {
+            $times = 1;
+            $query = $this->options($options)->page($times, $count);
         } else {
         } else {
-            $key = $column;
-        }
-        if ($resultSet instanceof Collection) {
-            $resultSet = $resultSet->all();
+            if (strpos($column, '.')) {
+                list($alias, $key) = explode('.', $column);
+            } else {
+                $key = $column;
+            }
+            $query = $this->options($options)->limit($count);
         }
         }
+        $resultSet = $query->order($column, $order)->select();
+
+        while (count($resultSet) > 0) {
+            if ($resultSet instanceof Collection) {
+                $resultSet = $resultSet->all();
+            }
 
 
-        while (!empty($resultSet)) {
             if (false === call_user_func($callback, $resultSet)) {
             if (false === call_user_func($callback, $resultSet)) {
                 return false;
                 return false;
             }
             }
-            $end       = end($resultSet);
-            $lastId    = is_array($end) ? $end[$key] : $end->$key;
-            $resultSet = $this->options($options)
-                ->limit($count)
-                ->bind($bind)
-                ->where($column, 'asc' == strtolower($order) ? '>' : '<', $lastId)
-                ->order($column, $order)
-                ->select();
-            if ($resultSet instanceof Collection) {
-                $resultSet = $resultSet->all();
+
+            if (is_array($column)) {
+                $times++;
+                $query = $this->options($options)->page($times, $count);
+            } else {
+                $end    = end($resultSet);
+                $lastId = is_array($end) ? $end[$key] : $end->getData($key);
+                $query  = $this->options($options)
+                    ->limit($count)
+                    ->where($column, 'asc' == strtolower($order) ? '>' : '<', $lastId);
             }
             }
+
+            $resultSet = $query->bind($bind)->order($column, $order)->select();
         }
         }
+
         return true;
         return true;
     }
     }
 
 
@@ -2692,7 +2859,7 @@ class Query
             Cache::clear($options['cache']['tag']);
             Cache::clear($options['cache']['tag']);
         }
         }
         // 执行操作
         // 执行操作
-        $result = $this->execute($sql, $bind);
+        $result = $this->execute($sql, $bind, $this);
         if ($result) {
         if ($result) {
             if (!is_array($data) && is_string($pk) && isset($key) && strpos($key, '|')) {
             if (!is_array($data) && is_string($pk) && isset($key) && strpos($key, '|')) {
                 list($a, $val) = explode('|', $key);
                 list($a, $val) = explode('|', $key);
@@ -2777,6 +2944,10 @@ class Query
             }
             }
         }
         }
 
 
+        if (isset(static::$readMaster['*']) || (is_string($options['table']) && isset(static::$readMaster[$options['table']]))) {
+            $options['master'] = true;
+        }
+
         foreach (['join', 'union', 'group', 'having', 'limit', 'order', 'force', 'comment'] as $name) {
         foreach (['join', 'union', 'group', 'having', 'limit', 'order', 'force', 'comment'] as $name) {
             if (!isset($options[$name])) {
             if (!isset($options[$name])) {
                 $options[$name] = '';
                 $options[$name] = '';

+ 72 - 6
thinkphp/library/think/db/builder/Mysql.php

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
-// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
@@ -12,28 +12,93 @@
 namespace think\db\builder;
 namespace think\db\builder;
 
 
 use think\db\Builder;
 use think\db\Builder;
+use think\Exception;
 
 
 /**
 /**
  * mysql数据库驱动
  * mysql数据库驱动
  */
  */
 class Mysql extends Builder
 class Mysql extends Builder
 {
 {
-    protected $updateSql = 'UPDATE %TABLE% %JOIN% SET %SET% %WHERE% %ORDER%%LIMIT% %LOCK%%COMMENT%';
+
+    protected $insertAllSql = '%INSERT% INTO %TABLE% (%FIELD%) VALUES %DATA% %COMMENT%';
+    protected $updateSql    = 'UPDATE %TABLE% %JOIN% SET %SET% %WHERE% %ORDER%%LIMIT% %LOCK%%COMMENT%';
+
+    /**
+     * 生成insertall SQL
+     * @access public
+     * @param array     $dataSet 数据集
+     * @param array     $options 表达式
+     * @param bool      $replace 是否replace
+     * @return string
+     * @throws Exception
+     */
+    public function insertAll($dataSet, $options = [], $replace = false)
+    {
+        // 获取合法的字段
+        if ('*' == $options['field']) {
+            $fields = array_keys($this->query->getFieldsType($options['table']));
+        } else {
+            $fields = $options['field'];
+        }
+
+        foreach ($dataSet as $data) {
+            foreach ($data as $key => $val) {
+                if (!in_array($key, $fields, true)) {
+                    if ($options['strict']) {
+                        throw new Exception('fields not exists:[' . $key . ']');
+                    }
+                    unset($data[$key]);
+                } elseif (is_null($val)) {
+                    $data[$key] = 'NULL';
+                } elseif (is_scalar($val)) {
+                    $data[$key] = $this->parseValue($val, $key);
+                } elseif (is_object($val) && method_exists($val, '__toString')) {
+                    // 对象数据写入
+                    $data[$key] = $val->__toString();
+                } else {
+                    // 过滤掉非标量数据
+                    unset($data[$key]);
+                }
+            }
+            $value    = array_values($data);
+            $values[] = '( ' . implode(',', $value) . ' )';
+
+            if (!isset($insertFields)) {
+                $insertFields = array_map([$this, 'parseKey'], array_keys($data));
+            }
+        }
+
+        return str_replace(
+            ['%INSERT%', '%TABLE%', '%FIELD%', '%DATA%', '%COMMENT%'],
+            [
+                $replace ? 'REPLACE' : 'INSERT',
+                $this->parseTable($options['table'], $options),
+                implode(' , ', $insertFields),
+                implode(' , ', $values),
+                $this->parseComment($options['comment']),
+            ], $this->insertAllSql);
+    }
 
 
     /**
     /**
      * 字段和表名处理
      * 字段和表名处理
      * @access protected
      * @access protected
-     * @param string $key
+     * @param mixed  $key
      * @param array  $options
      * @param array  $options
      * @return string
      * @return string
      */
      */
-    protected function parseKey($key, $options = [])
+    protected function parseKey($key, $options = [], $strict = false)
     {
     {
+        if (is_numeric($key)) {
+            return $key;
+        } elseif ($key instanceof Expression) {
+            return $key->getValue();
+        }
+
         $key = trim($key);
         $key = trim($key);
         if (strpos($key, '$.') && false === strpos($key, '(')) {
         if (strpos($key, '$.') && false === strpos($key, '(')) {
             // JSON字段支持
             // JSON字段支持
             list($field, $name) = explode('$.', $key);
             list($field, $name) = explode('$.', $key);
-            $key                = 'json_extract(' . $field . ', \'$.' . $name . '\')';
+            return 'json_extract(' . $field . ', \'$.' . $name . '\')';
         } elseif (strpos($key, '.') && !preg_match('/[,\'\"\(\)`\s]/', $key)) {
         } elseif (strpos($key, '.') && !preg_match('/[,\'\"\(\)`\s]/', $key)) {
             list($table, $key) = explode('.', $key, 2);
             list($table, $key) = explode('.', $key, 2);
             if ('__TABLE__' == $table) {
             if ('__TABLE__' == $table) {
@@ -43,7 +108,8 @@ class Mysql extends Builder
                 $table = $options['alias'][$table];
                 $table = $options['alias'][$table];
             }
             }
         }
         }
-        if (!preg_match('/[,\'\"\*\(\)`.\s]/', $key)) {
+
+        if ('*' != $key && ($strict || !preg_match('/[,\'\"\*\(\)`.\s]/', $key))) {
             $key = '`' . $key . '`';
             $key = '`' . $key . '`';
         }
         }
         if (isset($table)) {
         if (isset($table)) {

+ 9 - 3
thinkphp/library/think/db/builder/Pgsql.php

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
-// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
@@ -44,12 +44,18 @@ class Pgsql extends Builder
     /**
     /**
      * 字段和表名处理
      * 字段和表名处理
      * @access protected
      * @access protected
-     * @param string $key
+     * @param mixed  $key
      * @param array  $options
      * @param array  $options
      * @return string
      * @return string
      */
      */
-    protected function parseKey($key, $options = [])
+    protected function parseKey($key, $options = [], $strict = false)
     {
     {
+        if (is_numeric($key)) {
+            return $key;
+        } elseif ($key instanceof Expression) {
+            return $key->getValue();
+        }
+
         $key = trim($key);
         $key = trim($key);
         if (strpos($key, '$.') && false === strpos($key, '(')) {
         if (strpos($key, '$.') && false === strpos($key, '(')) {
             // JSON字段支持
             // JSON字段支持

+ 9 - 3
thinkphp/library/think/db/builder/Sqlite.php

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
-// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
@@ -52,12 +52,18 @@ class Sqlite extends Builder
     /**
     /**
      * 字段和表名处理
      * 字段和表名处理
      * @access protected
      * @access protected
-     * @param string $key
+     * @param mixed  $key
      * @param array  $options
      * @param array  $options
      * @return string
      * @return string
      */
      */
-    protected function parseKey($key, $options = [])
+    protected function parseKey($key, $options = [], $strict = false)
     {
     {
+        if (is_numeric($key)) {
+            return $key;
+        } elseif ($key instanceof Expression) {
+            return $key->getValue();
+        }
+
         $key = trim($key);
         $key = trim($key);
         if (strpos($key, '.')) {
         if (strpos($key, '.')) {
             list($table, $key) = explode('.', $key, 2);
             list($table, $key) = explode('.', $key, 2);

+ 28 - 18
thinkphp/library/think/db/builder/Sqlsrv.php

@@ -12,6 +12,7 @@
 namespace think\db\builder;
 namespace think\db\builder;
 
 
 use think\db\Builder;
 use think\db\Builder;
+use think\db\Expression;
 
 
 /**
 /**
  * Sqlsrv数据库驱动
  * Sqlsrv数据库驱动
@@ -34,25 +35,29 @@ class Sqlsrv extends Builder
      */
      */
     protected function parseOrder($order, $options = [])
     protected function parseOrder($order, $options = [])
     {
     {
-        if (is_array($order)) {
-            $array = [];
-            foreach ($order as $key => $val) {
-                if (is_numeric($key)) {
-                    if (false === strpos($val, '(')) {
-                        $array[] = $this->parseKey($val, $options);
-                    } elseif ('[rand]' == $val) {
-                        $array[] = $this->parseRand();
-                    } else {
-                        $array[] = $val;
-                    }
+        if (empty($order)) {
+            return ' ORDER BY rand()';
+        }
+
+        $array = [];
+        foreach ($order as $key => $val) {
+            if ($val instanceof Expression) {
+                $array[] = $val->getValue();
+            } elseif (is_numeric($key)) {
+                if (false === strpos($val, '(')) {
+                    $array[] = $this->parseKey($val, $options);
+                } elseif ('[rand]' == $val) {
+                    $array[] = $this->parseRand();
                 } else {
                 } else {
-                    $sort    = in_array(strtolower(trim($val)), ['asc', 'desc']) ? ' ' . $val : '';
-                    $array[] = $this->parseKey($key, $options) . ' ' . $sort;
+                    $array[] = $val;
                 }
                 }
+            } else {
+                $sort    = in_array(strtolower(trim($val)), ['asc', 'desc'], true) ? ' ' . $val : '';
+                $array[] = $this->parseKey($key, $options, true) . ' ' . $sort;
             }
             }
-            $order = implode(',', $array);
         }
         }
-        return !empty($order) ? ' ORDER BY ' . $order : ' ORDER BY rand()';
+
+        return ' ORDER BY ' . implode(',', $array);
     }
     }
 
 
     /**
     /**
@@ -68,12 +73,17 @@ class Sqlsrv extends Builder
     /**
     /**
      * 字段和表名处理
      * 字段和表名处理
      * @access protected
      * @access protected
-     * @param string $key
+     * @param mixed  $key
      * @param array  $options
      * @param array  $options
      * @return string
      * @return string
      */
      */
-    protected function parseKey($key, $options = [])
+    protected function parseKey($key, $options = [], $strict = false)
     {
     {
+        if (is_numeric($key)) {
+            return $key;
+        } elseif ($key instanceof Expression) {
+            return $key->getValue();
+        }
         $key = trim($key);
         $key = trim($key);
         if (strpos($key, '.') && !preg_match('/[,\'\"\(\)\[\s]/', $key)) {
         if (strpos($key, '.') && !preg_match('/[,\'\"\(\)\[\s]/', $key)) {
             list($table, $key) = explode('.', $key, 2);
             list($table, $key) = explode('.', $key, 2);
@@ -84,7 +94,7 @@ class Sqlsrv extends Builder
                 $table = $options['alias'][$table];
                 $table = $options['alias'][$table];
             }
             }
         }
         }
-        if (!is_numeric($key) && !preg_match('/[,\'\"\*\(\)\[.\s]/', $key)) {
+        if ('*' != $key && ($strict || !preg_match('/[,\'\"\*\(\)\[.\s]/', $key))) {
             $key = '[' . $key . ']';
             $key = '[' . $key . ']';
         }
         }
         if (isset($table)) {
         if (isset($table)) {

+ 1 - 1
thinkphp/library/think/db/connector/Mysql.php

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
-// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------

+ 1 - 1
thinkphp/library/think/db/connector/Pgsql.php

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
-// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------

+ 1 - 1
thinkphp/library/think/db/connector/Sqlite.php

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
-// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------

+ 1 - 1
thinkphp/library/think/db/exception/BindParamException.php

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
-// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------

+ 1 - 1
thinkphp/library/think/db/exception/DataNotFoundException.php

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
-// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------

+ 1 - 1
thinkphp/library/think/db/exception/ModelNotFoundException.php

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
-// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
+// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 // +----------------------------------------------------------------------
 // +----------------------------------------------------------------------

+ 1 - 1
view/crmebN/pages/orders-con/orders-con.js

@@ -66,7 +66,7 @@ Page({
               })
               })
               setTimeout(function () {
               setTimeout(function () {
                 wx.navigateTo({ //跳转至指定页面并关闭其他打开的所有页面(这个最好用在返回至首页的的时候)
                 wx.navigateTo({ //跳转至指定页面并关闭其他打开的所有页面(这个最好用在返回至首页的的时候)
-                  url: '/pages/orders-con/orders-con?order_id=' + data.result.orderId
+                  url: '/pages/orders-con/orders-con?order_id=' + data.result.order_id
                 })
                 })
               }, 1200)
               }, 1200)
             },
             },

+ 1 - 1
view/crmebN/pages/product-con/index.wxml

@@ -78,7 +78,7 @@
       <view class='txt-msg'>{{reply.comment}}</view>
       <view class='txt-msg'>{{reply.comment}}</view>
       <view class='time-bar'>{{reply.add_time}}</view>
       <view class='time-bar'>{{reply.add_time}}</view>
     </view>
     </view>
-    <view>
+    <view wx:if="{{reply.merchant_reply_content != null}}">
        <view>管理员回复:</view>
        <view>管理员回复:</view>
       <view class='txt-msg'>{{reply.merchant_reply_content}}</view>
       <view class='txt-msg'>{{reply.merchant_reply_content}}</view>
       <view class='time-bar'>{{reply.merchant_reply_time}}</view>
       <view class='time-bar'>{{reply.merchant_reply_time}}</view>