Pārlūkot izejas kodu

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

聆听 7 gadi atpakaļ
vecāks
revīzija
a9fa1ee8bd
35 mainītis faili ar 1068 papildinājumiem un 530 dzēšanām
  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 ($Fields['fields'] as $index => $field) {
                 if($key == $field["title"]){
-                    if($param == "" || count($param) == 0)
+//                    if($param == "" || count($param) == 0)
+                    if($param == "")
                         return Json::fail($field["name"]."不能为空!");
                     else{
                         $value[$key]["type"] = $field["type"];

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

@@ -1,5 +1,4 @@
 <?php
-
 namespace app\admin\controller\store;
 
 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];
                 }
                 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('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('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('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('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_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),

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

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

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

@@ -42,7 +42,7 @@ class StoreCoupon extends AuthController
     public function create()
     {
         $f = array();
-        $f[] = Form::input('title','优惠券名称');
+        $f[] = Form::input('title','优惠券名称')->required();
         $f[] = Form::number('coupon_price','优惠券面值',0)->min(0);
         $f[] = Form::number('use_min_price','优惠券最低消费')->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()
     {
         $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('cost','成本价')->min(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_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);
-        $form = Form::make_post_form('添加用户通知',$f,Url::build('save'));
+        $form = Form::make_post_form('开启秒杀',$f,Url::build('save'));
         $this->assign(compact('form'));
         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);
             }
             $item['_info'] = $_info;
+            $item['add_time'] = date('Y-m-d H:i:s',$item['add_time']);
             if($item['pink_id'] && $item['combination_id']){
                 $pinkStatus = StorePink::where('order_id_key',$item['id'])->value('status');
                 switch ($pinkStatus){
@@ -904,4 +905,21 @@ HTML;
           if(!$uid) return 0;
           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;
 
-
 use traits\ModelTrait;
 use basic\ModelBasic;
 use service\UtilService;
@@ -20,16 +19,39 @@ class StoreCategory extends ModelBasic
 {
     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
      * @return array
      */
-    public static function systemPage($where){
+    public static function systemPage($where,$isAjax=false){
         $model = new self;
         if($where['pid'] != '')  $model = $model->where('pid',$where['pid']);
         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['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){
             if($item['pid']){
                 $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){
-            ksort($value['detail'],SORT_STRING);
+            sort($value['detail'],SORT_STRING);
             $suk = implode(',',$value['detail']);
             $valueGroup[$suk] = [
                 '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>
                     <!--订单-->
                     <script type="text/html" id="order_id">
-                       <h4>{{d.order_id}}</h4>
+                       {{d.order_id}}
                        <span style="color: {{d.color}};">{{d.pink_name}}</span>  
                     </script>
                     <!--用户信息-->
@@ -112,32 +112,32 @@
                         {{#  if(item.cart_info.productInfo.attrInfo!=undefined){ }}
                         <p>
                             <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>{{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>
                         </p>
                         {{#  }else{ }}
                         <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>
                         </p>
                         {{# } }}
                         {{#  }); }}
                     </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">
                         {{#  if(d._status==1){ }}
                         <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">
+                            <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>
                                 <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>
                             </li>
                             <li>
@@ -156,6 +156,11 @@
                             <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>
                         <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>
                                 <a  href="javascript:void(0);" onclick="$eb.createModalFrame('去送货','{:Url('delivery')}?id={{d.id}}',{w:400,h:300})">
                                     <i class="fa fa-motorcycle"></i> 去送货
@@ -188,6 +193,11 @@
                         {{#  }else if(d._status==3){ }}
                         <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">
+                            <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>
                                 <a  href="javascript:void(0);" onclick="$eb.createModalFrame('去送货','{:Url('delivery')}?id={{d.id}}',{w:400,h:300})">
                                     <i class="fa fa-motorcycle"></i> 去送货
@@ -227,6 +237,11 @@
                             <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>
                         <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>
                                 <a lay-event='marke' href="javascript:void(0);" >
                                     <i class="fa fa-paste"></i> 订单备注
@@ -259,6 +274,11 @@
                         {{#  }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>
                         <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>
                                 <a lay-event='marke' href="javascript:void(0);" >
                                     <i class="fa fa-paste"></i> 订单备注
@@ -286,6 +306,11 @@
                         {{#  }else if(d._status==7){ }}
                         <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">
+                            <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>
                                 <a lay-event='marke' href="javascript:void(0);" >
                                     <i class="fa fa-paste"></i> 订单备注
@@ -318,13 +343,13 @@
 <script>
     layList.tableList('List',"{:Url('order_list',['real_name'=>$real_name])}",function (){
         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: 'info', title: '商品信息',templet:"#info",width:'36%'},
+            {field: 'info', title: '商品信息',templet:"#info"},
             {field: 'pay_price', title: '实际支付',width:'8%'},
             {field: 'paid', title: '支付状态',templet:'#paid',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%'},
         ];
     });

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

@@ -1,133 +1,172 @@
 {extend name="public/container"}
 {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 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 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>
-                {include file="public/inner_page"}
             </div>
         </div>
     </div>
 </div>
+<script src="{__ADMIN_PATH}js/layuiList.js"></script>
 {/block}
 {block name="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>
 {/block}

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

@@ -71,7 +71,7 @@
                     <div class="layui-btn-container">
                         {switch name='type'}
                             {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 value="2"}
                                 <button class="layui-btn layui-btn-sm" data-type="show">批量上架</button>
@@ -175,15 +175,15 @@
             case 2:
                 join=[
                     {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: '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%'},
                 ];
                 break;

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

@@ -135,8 +135,8 @@
     layList.tableList('combinationList',"{:Url('get_combination_list')}",function () {
         return [
             {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: 'price', title: '拼团价'},
             {field: 'stock', title: '库存'},

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

@@ -113,17 +113,17 @@
     layList.form.render();
     layList.tableList('seckillList',"{:Url('get_seckill_list')}",function () {
         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) {

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

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

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

@@ -64,7 +64,7 @@
                                 {/switch}
                             </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-warning btn-xs" data-url="{:Url('delete',array('id'=>$vo['id']))}" type="button"><i class="fa fa-warning"></i> 删除
                                 </button>

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

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

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 9 - 21
extend/service/WechatService.php


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

@@ -1,4 +1,11 @@
 @charset "UTF-8";
+.layui-btn {
+    background-color: #0092DC;
+}
+.layui-btn-primary:hover {
+    border-color: #0092DC;
+    color: #333;
+}
 .layui-table-box{
     overflow: initial;
 }
@@ -11,44 +18,14 @@
 .table-responsive{
     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-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{
     height: 20px;
     line-height: 20px;
@@ -58,6 +35,10 @@
     width: 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 {
     border-color: #0093DE;
     background-color: #0093DE;
@@ -73,23 +54,6 @@
 .layui-tab-title .layui-this:after{
     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{
     line-height: 30px;
@@ -99,11 +63,8 @@
 .back-f8{
     background-color: #F8F8F8;
 }
-.layui-input-block button{
-    border: 1px solid #C9C9C9;
-}
 .layui-card-body p.layuiadmin-big-font {
-    font-size: 36px;
+    font-size: 24px;
     color: #666;
     line-height: 36px;
     padding: 5px 0 10px;
@@ -184,3 +145,92 @@
 .layadmin-text-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;
+}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 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 ]
 // +----------------------------------------------------------------------
-// | 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 )
 // +----------------------------------------------------------------------
@@ -90,6 +90,8 @@ abstract class Connection
         'master_num'      => 1,
         // 指定从服务器序号
         'slave_no'        => '',
+        // 模型写入后自动读取主服务器
+        'read_master'     => false,
         // 是否严格检查字段是否存在
         'fields_strict'   => true,
         // 数据返回类型
@@ -354,15 +356,15 @@ abstract class Connection
             $this->bind = $bind;
         }
 
-        // 释放前次的查询结果
-        if (!empty($this->PDOStatement)) {
-            $this->free();
-        }
-
         Db::$queryTimes++;
         try {
             // 调试开始
             $this->debug(true);
+
+            // 释放前次的查询结果
+            if (!empty($this->PDOStatement)) {
+                $this->free();
+            }
             // 预处理
             if (empty($this->PDOStatement)) {
                 $this->PDOStatement = $this->linkID->prepare($sql);
@@ -378,7 +380,7 @@ abstract class Connection
             // 执行查询
             $this->PDOStatement->execute();
             // 调试结束
-            $this->debug(false);
+            $this->debug(false, '', $master);
             // 返回结果集
             return $this->getResult($pdo, $procedure);
         } catch (\PDOException $e) {
@@ -386,6 +388,11 @@ abstract class Connection
                 return $this->close()->query($sql, $bind, $master, $pdo);
             }
             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) {
             if ($this->isBreak($e)) {
                 return $this->close()->query($sql, $bind, $master, $pdo);
@@ -397,13 +404,14 @@ abstract class Connection
     /**
      * 执行语句
      * @access public
-     * @param string        $sql sql指令
-     * @param array         $bind 参数绑定
+     * @param  string        $sql sql指令
+     * @param  array         $bind 参数绑定
+     * @param  Query         $query 查询对象
      * @return int
      * @throws PDOException
      * @throws \Exception
      */
-    public function execute($sql, $bind = [])
+    public function execute($sql, $bind = [], Query $query = null)
     {
         $this->initConnect(true);
         if (!$this->linkID) {
@@ -416,15 +424,15 @@ abstract class Connection
             $this->bind = $bind;
         }
 
-        //释放前次的查询结果
-        if (!empty($this->PDOStatement) && $this->PDOStatement->queryString != $sql) {
-            $this->free();
-        }
-
         Db::$executeTimes++;
         try {
             // 调试开始
             $this->debug(true);
+
+            //释放前次的查询结果
+            if (!empty($this->PDOStatement) && $this->PDOStatement->queryString != $sql) {
+                $this->free();
+            }
             // 预处理
             if (empty($this->PDOStatement)) {
                 $this->PDOStatement = $this->linkID->prepare($sql);
@@ -440,18 +448,27 @@ abstract class Connection
             // 执行语句
             $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();
             return $this->numRows;
         } catch (\PDOException $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());
+        } catch (\Throwable $e) {
+            if ($this->isBreak($e)) {
+                return $this->close()->execute($sql, $bind, $query);
+            }
+            throw $e;
         } catch (\Exception $e) {
             if ($this->isBreak($e)) {
-                return $this->close()->execute($sql, $bind);
+                return $this->close()->execute($sql, $bind, $query);
             }
             throw $e;
         }
@@ -466,6 +483,10 @@ abstract class Connection
      */
     public function getRealSql($sql, array $bind = [])
     {
+        if (is_array($sql)) {
+            $sql = implode(';', $sql);
+        }
+
         foreach ($bind as $key => $val) {
             $value = is_array($val) ? $val[0] : $val;
             $type  = is_array($val) ? $val[1] : PDO::PARAM_STR;
@@ -478,8 +499,8 @@ abstract class Connection
             $sql = is_numeric($key) ?
             substr_replace($sql, $value, strpos($sql, '?'), 1) :
             str_replace(
-                [':' . $key . ')', ':' . $key . ',', ':' . $key . ' '],
-                [$value . ')', $value . ',', $value . ' '],
+                [':' . $key . ')', ':' . $key . ',', ':' . $key . ' ', ':' . $key . PHP_EOL],
+                [$value . ')', $value . ',', $value . ' ', $value . PHP_EOL],
                 $sql . ' ');
         }
         return rtrim($sql);
@@ -648,6 +669,11 @@ abstract class Connection
                 return $this->close()->startTrans();
             }
             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批处理指令
      * @return boolean
      */
-    public function batchQuery($sqlArray = [])
+    public function batchQuery($sqlArray = [], $bind = [], Query $query = null)
     {
         if (!is_array($sqlArray)) {
             return false;
@@ -734,7 +760,7 @@ abstract class Connection
         $this->startTrans();
         try {
             foreach ($sqlArray as $sql) {
-                $this->execute($sql);
+                $this->execute($sql, $bind, $query);
             }
             // 提交事务
             $this->commit();
@@ -742,6 +768,7 @@ abstract class Connection
             $this->rollback();
             throw $e;
         }
+
         return true;
     }
 
@@ -803,6 +830,7 @@ abstract class Connection
             'SSL connection has been closed unexpectedly',
             'Error writing data to the connection',
             'Resource deadlock avoided',
+            'failed with errno',
         ];
 
         $error = $e->getMessage();
@@ -883,9 +911,10 @@ abstract class Connection
      * @access protected
      * @param boolean $start 调试开始标记 true 开始 false 结束
      * @param string  $sql 执行的SQL语句 留空自动获取
+     * @param boolean $master 主从标记
      * @return void
      */
-    protected function debug($start, $sql = '')
+    protected function debug($start, $sql = '', $master = false)
     {
         if (!empty($this->config['debug'])) {
             // 开启数据库调试模式
@@ -902,7 +931,7 @@ abstract class Connection
                     $result = $this->getExplain($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 float     $runtime 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)) {
             foreach (self::$event as $callback) {
                 if (is_callable($callback)) {
-                    call_user_func_array($callback, [$sql, $runtime, $explain]);
+                    call_user_func_array($callback, [$sql, $runtime, $explain, $master]);
                 }
             }
         } 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)) {
                 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 ]
 // +----------------------------------------------------------------------
-// | 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 )
 // +----------------------------------------------------------------------
@@ -53,14 +53,16 @@ class Query
     protected static $info = [];
     // 回调事件
     private static $event = [];
+    // 读取主库
+    private static $readMaster = [];
 
     /**
      * 构造函数
      * @access public
      * @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->prefix     = $this->connection->getConfig('prefix');
@@ -131,15 +133,34 @@ class Query
     }
 
     /**
-     * 获取当前的模型对象
+     * 获取当前的模型对象实例
      * @access public
-     * @return string
+     * @return Model|null
      */
     public function getModel()
     {
         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实例对象
      * @access public
@@ -238,7 +259,7 @@ class Query
      */
     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批处理指令
      * @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'])) {
                 $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);
         }
         if (false === $result) {
@@ -420,7 +441,7 @@ class Query
                 $result += 0;
             }
 
-            if (isset($cache)) {
+            if (isset($cache) && false !== $result) {
                 // 缓存数据
                 $this->cacheData($key, $result, $cache);
             }
@@ -447,7 +468,7 @@ class Query
             if (empty($this->options['table'])) {
                 $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);
         }
         if (false === $result) {
@@ -534,22 +555,24 @@ class Query
      * MIN查询
      * @access public
      * @param string $field 字段名
+     * @param bool   $force   强制转为数字类型
      * @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查询
      * @access public
      * @param string $field 字段名
+     * @param bool   $force   强制转为数字类型
      * @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 $this->setField($field, ['exp', $field . '+' . $step]);
+        return $this->setField($field, ['inc', $step]);
     }
 
     /**
@@ -635,8 +658,9 @@ class Query
                 $this->options = [];
                 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)) {
-            list($table, $alias) = each($join);
+            $table = $join;
+            $alias = array_shift($join);
         } else {
             $join = trim($join);
             if (false !== strpos($join, '(')) {
@@ -725,13 +750,9 @@ class Query
                     $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;
     }
@@ -769,8 +790,15 @@ class Query
     {
         if (empty($field)) {
             return $this;
+        } elseif ($field instanceof Expression) {
+            $this->options['field'][] = $field;
+            return $this;
         }
+
         if (is_string($field)) {
+            if (preg_match('/[\<\'\"\(]/', $field)) {
+                return $this->fieldRaw($field);
+            }
             $field = array_map('trim', explode(',', $field));
         }
         if (true === $field) {
@@ -794,12 +822,30 @@ class Query
         }
 
         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);
         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
@@ -828,7 +874,7 @@ class Query
     {
         $fields = is_string($field) ? explode(',', $field) : $field;
         foreach ($fields as $field) {
-            $this->data($field, ['exp', $field . '+' . $step]);
+            $this->data($field, ['inc', $step]);
         }
         return $this;
     }
@@ -844,7 +890,7 @@ class Query
     {
         $fields = is_string($field) ? explode(',', $field) : $field;
         foreach ($fields as $field) {
-            $this->data($field, ['exp', $field . '-' . $step]);
+            $this->data($field, ['dec', $step]);
         }
         return $this;
     }
@@ -858,25 +904,36 @@ class Query
      */
     public function exp($field, $value)
     {
-        $this->data($field, ['exp', $value]);
+        $this->data($field, $this->raw($value));
         return $this;
     }
 
+    /**
+     * 使用表达式设置数据
+     * @access public
+     * @param  mixed $value 表达式
+     * @return Expression
+     */
+    public function raw($value)
+    {
+        return new Expression($value);
+    }
+
     /**
      * 指定JOIN查询字段
      * @access public
      * @param string|array $table 数据表
      * @param string|array $field 查询字段
-     * @param string|array $on    JOIN条件
+     * @param mixed        $on    JOIN条件
      * @param string       $type  JOIN类型
      * @return $this
      */
     public function view($join, $field = true, $on = null, $type = 'INNER')
     {
         $this->options['view'] = true;
-        if (is_array($join) && key($join) !== 0) {
+        if (is_array($join) && key($join) === 0) {
             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 {
             $fields = [];
@@ -975,6 +1032,37 @@ class Query
         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查询条件
      * @access public
@@ -984,7 +1072,7 @@ class Query
      */
     public function whereNull($field, $logic = 'AND')
     {
-        $this->parseWhereExp($logic, $field, 'null', null);
+        $this->parseWhereExp($logic, $field, 'null', null, [], true);
         return $this;
     }
 
@@ -997,7 +1085,7 @@ class Query
      */
     public function whereNotNull($field, $logic = 'AND')
     {
-        $this->parseWhereExp($logic, $field, 'notnull', null);
+        $this->parseWhereExp($logic, $field, 'notnull', null, [], true);
         return $this;
     }
 
@@ -1037,7 +1125,7 @@ class Query
      */
     public function whereIn($field, $condition, $logic = 'AND')
     {
-        $this->parseWhereExp($logic, $field, 'in', $condition);
+        $this->parseWhereExp($logic, $field, 'in', $condition, [], true);
         return $this;
     }
 
@@ -1051,7 +1139,7 @@ class Query
      */
     public function whereNotIn($field, $condition, $logic = 'AND')
     {
-        $this->parseWhereExp($logic, $field, 'not in', $condition);
+        $this->parseWhereExp($logic, $field, 'not in', $condition, [], true);
         return $this;
     }
 
@@ -1065,7 +1153,7 @@ class Query
      */
     public function whereLike($field, $condition, $logic = 'AND')
     {
-        $this->parseWhereExp($logic, $field, 'like', $condition);
+        $this->parseWhereExp($logic, $field, 'like', $condition, [], true);
         return $this;
     }
 
@@ -1079,7 +1167,7 @@ class Query
      */
     public function whereNotLike($field, $condition, $logic = 'AND')
     {
-        $this->parseWhereExp($logic, $field, 'not like', $condition);
+        $this->parseWhereExp($logic, $field, 'not like', $condition, [], true);
         return $this;
     }
 
@@ -1093,7 +1181,7 @@ class Query
      */
     public function whereBetween($field, $condition, $logic = 'AND')
     {
-        $this->parseWhereExp($logic, $field, 'between', $condition);
+        $this->parseWhereExp($logic, $field, 'between', $condition, [], true);
         return $this;
     }
 
@@ -1107,7 +1195,7 @@ class Query
      */
     public function whereNotBetween($field, $condition, $logic = 'AND')
     {
-        $this->parseWhereExp($logic, $field, 'not between', $condition);
+        $this->parseWhereExp($logic, $field, 'not between', $condition, [], true);
         return $this;
     }
 
@@ -1121,7 +1209,7 @@ class Query
      */
     public function whereExp($field, $condition, $logic = 'AND')
     {
-        $this->parseWhereExp($logic, $field, 'exp', $condition);
+        $this->parseWhereExp($logic, $field, 'exp', $this->raw($condition), [], true);
         return $this;
     }
 
@@ -1148,9 +1236,10 @@ class Query
      * @param mixed                 $op        查询表达式
      * @param mixed                 $condition 查询条件
      * @param array                 $param     查询参数
+     * @param  bool                 $strict    严格模式
      * @return void
      */
-    protected function parseWhereExp($logic, $field, $op, $condition, $param = [])
+    protected function parseWhereExp($logic, $field, $op, $condition, $param = [], $strict = false)
     {
         $logic = strtoupper($logic);
         if ($field instanceof \Closure) {
@@ -1161,8 +1250,17 @@ class Query
         if (is_string($field) && !empty($this->options['via']) && !strpos($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)) {
                 // 参数绑定
                 $this->bind($op);
@@ -1183,21 +1281,28 @@ class Query
             $where[$field] = $param;
         } elseif (in_array(strtolower($op), ['null', 'notnull', 'not null'])) {
             // null查询
-            $where[$field]                            = [$op, ''];
+            $where[$field] = [$op, ''];
+
             $this->options['multi'][$logic][$field][] = $where[$field];
         } elseif (is_null($condition)) {
             // 字段相等查询
-            $where[$field]                            = ['eq', $op];
+            $where[$field] = ['eq', $op];
+
             $this->options['multi'][$logic][$field][] = $where[$field];
         } 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];
         }
+
         if (!empty($where)) {
             if (!isset($this->options['where'][$logic])) {
                 $this->options['where'][$logic] = [];
@@ -1239,6 +1344,7 @@ class Query
         $logic = strtoupper($logic);
         if (isset($this->options['where'][$logic][$field])) {
             unset($this->options['where'][$logic][$field]);
+            unset($this->options['multi'][$logic][$field]);
         }
         return $this;
     }
@@ -1414,31 +1520,59 @@ class Query
      */
     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 {
-                $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;
     }
 
@@ -1523,7 +1657,12 @@ class Query
     {
         if (is_array($alias)) {
             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 {
             if (isset($this->options['table'])) {
@@ -1651,46 +1790,49 @@ class Query
      * 查询日期或者时间
      * @access public
      * @param string       $field 日期字段名
-     * @param string       $op    比较运算符或者表达式
+     * @param string|array $op    比较运算符或者表达式
      * @param string|array $range 比较范围
      * @return $this
      */
     public function whereTime($field, $op, $range = null)
     {
         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' : '>';
         }
@@ -1735,7 +1877,7 @@ class Query
                 $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';
             } else {
                 $info = $this->connection->getFields($guid);
@@ -1810,7 +1952,9 @@ class Query
      */
     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;
         } elseif (preg_match('/bool/is', $type)) {
             $bind = PDO::PARAM_BOOL;
@@ -1892,11 +2036,10 @@ class Query
             $with = explode(',', $with);
         }
 
-        $first        = true;
-        $currentModel = $this->model;
+        $first = true;
 
         /** @var Model $class */
-        $class = new $currentModel;
+        $class = $this->model;
         foreach ($with as $key => $relation) {
             $subRelation = '';
             $closure     = false;
@@ -1955,7 +2098,7 @@ class Query
                     $relation = $key;
                 }
                 $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']);
             }
         }
@@ -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) {
             $sequence  = $sequence ?: (isset($options['sequence']) ? $options['sequence'] : null);
             $lastInsId = $this->getLastInsID($sequence);
@@ -2118,27 +2261,40 @@ class Query
     /**
      * 批量插入记录
      * @access public
-     * @param mixed $dataSet 数据集
-     * @param boolean $replace  是否replace
+     * @param mixed     $dataSet 数据集
+     * @param boolean   $replace  是否replace
+     * @param integer   $limit   每次写入数据限制
      * @return integer|string
      */
-    public function insertAll(array $dataSet, $replace = false)
+    public function insertAll(array $dataSet, $replace = false, $limit = null)
     {
         // 分析查询表达式
         $options = $this->parseExpress();
         if (!is_array(reset($dataSet))) {
             return false;
         }
+
         // 生成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();
         if ($options['fetch_sql']) {
             // 获取实际执行的SQL语句
             return $this->connection->getRealSql($sql, $bind);
+        } elseif (is_array($sql)) {
+            // 执行操作
+            return $this->batchQuery($sql, $bind, $this);
         } else {
             // 执行操作
-            return $this->execute($sql, $bind);
+            return $this->execute($sql, $bind, $this);
         }
     }
 
@@ -2164,7 +2320,7 @@ class Query
             return $this->connection->getRealSql($sql, $bind);
         } else {
             // 执行操作
-            return $this->execute($sql, $bind);
+            return $this->execute($sql, $bind, $this);
         }
     }
 
@@ -2231,7 +2387,7 @@ class Query
                 Cache::clear($options['cache']['tag']);
             }
             // 执行操作
-            $result = '' == $sql ? 0 : $this->execute($sql, $bind);
+            $result = '' == $sql ? 0 : $this->execute($sql, $bind, $this);
             if ($result) {
                 if (is_string($pk) && isset($where[$pk])) {
                     $data[$pk] = $where[$pk];
@@ -2300,7 +2456,7 @@ class Query
             // 判断查询缓存
             $cache = $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);
         }
         if (false === $resultSet) {
@@ -2334,11 +2490,10 @@ class Query
         // 数据列表读取后的处理
         if (!empty($this->model)) {
             // 生成模型对象
-            $modelName = $this->model;
             if (count($resultSet) > 0) {
                 foreach ($resultSet as $key => $result) {
                     /** @var Model $model */
-                    $model = new $modelName($result);
+                    $model = $this->model->newInstance($result);
                     $model->isUpdate(true);
 
                     // 关联查询
@@ -2358,7 +2513,7 @@ class Query
                 // 模型数据集转换
                 $resultSet = $model->toCollection($resultSet);
             } else {
-                $resultSet = (new $modelName)->toCollection($resultSet);
+                $resultSet = $this->model->toCollection($resultSet);
             }
         } elseif ('collection' == $this->connection->getConfig('resultset_type')) {
             // 返回Collection对象
@@ -2402,10 +2557,16 @@ class Query
         } elseif (is_array($value) && is_string($value[0]) && 'eq' == strtolower($value[0])) {
             $data = $value[1];
         }
+        $prefix = $this->connection->getConfig('database') . '.';
+
         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'];
             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'])) {
                 $key = $cache['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);
         }
@@ -2484,7 +2645,7 @@ class Query
                 $result = isset($resultSet[0]) ? $resultSet[0] : null;
             }
 
-            if (isset($cache) && false !== $result) {
+            if (isset($cache) && $result) {
                 // 缓存数据
                 $this->cacheData($key, $result, $cache);
             }
@@ -2494,8 +2655,7 @@ class Query
         if (!empty($result)) {
             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);
                 // 关联查询
                 if (!empty($options['relation'])) {
@@ -2526,7 +2686,8 @@ class Query
     protected function throwNotFound($options = [])
     {
         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 {
             $table = is_array($options['table']) ? key($options['table']) : $options['table'];
             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')
     {
         $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 (App::$debug) {
                 throw new \LogicException('chunk not support call 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 {
-            $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)) {
                 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;
     }
 
@@ -2692,7 +2859,7 @@ class Query
             Cache::clear($options['cache']['tag']);
         }
         // 执行操作
-        $result = $this->execute($sql, $bind);
+        $result = $this->execute($sql, $bind, $this);
         if ($result) {
             if (!is_array($data) && is_string($pk) && isset($key) && strpos($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) {
             if (!isset($options[$name])) {
                 $options[$name] = '';

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

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // | 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 )
 // +----------------------------------------------------------------------
@@ -12,28 +12,93 @@
 namespace think\db\builder;
 
 use think\db\Builder;
+use think\Exception;
 
 /**
  * mysql数据库驱动
  */
 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
-     * @param string $key
+     * @param mixed  $key
      * @param array  $options
      * @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);
         if (strpos($key, '$.') && false === strpos($key, '(')) {
             // JSON字段支持
             list($field, $name) = explode('$.', $key);
-            $key                = 'json_extract(' . $field . ', \'$.' . $name . '\')';
+            return 'json_extract(' . $field . ', \'$.' . $name . '\')';
         } elseif (strpos($key, '.') && !preg_match('/[,\'\"\(\)`\s]/', $key)) {
             list($table, $key) = explode('.', $key, 2);
             if ('__TABLE__' == $table) {
@@ -43,7 +108,8 @@ class Mysql extends Builder
                 $table = $options['alias'][$table];
             }
         }
-        if (!preg_match('/[,\'\"\*\(\)`.\s]/', $key)) {
+
+        if ('*' != $key && ($strict || !preg_match('/[,\'\"\*\(\)`.\s]/', $key))) {
             $key = '`' . $key . '`';
         }
         if (isset($table)) {

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

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // | 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 )
 // +----------------------------------------------------------------------
@@ -44,12 +44,18 @@ class Pgsql extends Builder
     /**
      * 字段和表名处理
      * @access protected
-     * @param string $key
+     * @param mixed  $key
      * @param array  $options
      * @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);
         if (strpos($key, '$.') && false === strpos($key, '(')) {
             // JSON字段支持

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

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // | 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 )
 // +----------------------------------------------------------------------
@@ -52,12 +52,18 @@ class Sqlite extends Builder
     /**
      * 字段和表名处理
      * @access protected
-     * @param string $key
+     * @param mixed  $key
      * @param array  $options
      * @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);
         if (strpos($key, '.')) {
             list($table, $key) = explode('.', $key, 2);

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

@@ -12,6 +12,7 @@
 namespace think\db\builder;
 
 use think\db\Builder;
+use think\db\Expression;
 
 /**
  * Sqlsrv数据库驱动
@@ -34,25 +35,29 @@ class Sqlsrv extends Builder
      */
     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 {
-                    $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
-     * @param string $key
+     * @param mixed  $key
      * @param array  $options
      * @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);
         if (strpos($key, '.') && !preg_match('/[,\'\"\(\)\[\s]/', $key)) {
             list($table, $key) = explode('.', $key, 2);
@@ -84,7 +94,7 @@ class Sqlsrv extends Builder
                 $table = $options['alias'][$table];
             }
         }
-        if (!is_numeric($key) && !preg_match('/[,\'\"\*\(\)\[.\s]/', $key)) {
+        if ('*' != $key && ($strict || !preg_match('/[,\'\"\*\(\)\[.\s]/', $key))) {
             $key = '[' . $key . ']';
         }
         if (isset($table)) {

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

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // | 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 )
 // +----------------------------------------------------------------------

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

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // | 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 )
 // +----------------------------------------------------------------------

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

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // | 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 )
 // +----------------------------------------------------------------------

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

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // | 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 )
 // +----------------------------------------------------------------------

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

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // | 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 )
 // +----------------------------------------------------------------------

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

@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------
 // | 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 )
 // +----------------------------------------------------------------------

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

@@ -66,7 +66,7 @@ Page({
               })
               setTimeout(function () {
                 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)
             },

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

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