!16 更新一些bug

Merge pull request !16 from 聆听/develop
This commit is contained in:
聆听 2018-12-22 12:58:56 +08:00
commit a9fa1ee8bd
35 changed files with 1077 additions and 539 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -27,25 +27,24 @@ class WechatService
{ {
private static $instance = null; private static $instance = null;
/**获取微信配置参数
* @return array
*/
public static function options() public static function options()
{ {
$wechat = SystemConfigService::more(['wechat_appid','wechat_appsecret','wechat_token']); $wechat = SystemConfigService::more(['wechat_appid','wechat_appsecret','wechat_token','wechat_encodingaeskey','wechat_encode']);
$payment = SystemConfigService::more(['pay_weixin_mchid','pay_weixin_client_cert','pay_weixin_client_key','pay_weixin_key','pay_weixin_open']); $payment = SystemConfigService::more(['pay_weixin_mchid','pay_weixin_client_cert','pay_weixin_client_key','pay_weixin_key','pay_weixin_open']);
$config = [ $config = [
'app_id'=>isset($wechat['wechat_appid']) ? trim($wechat['wechat_appid']):'', 'app_id'=>isset($wechat['wechat_appid']) ? $wechat['wechat_appid']:'',
'secret'=>isset($wechat['wechat_appsecret']) ? trim($wechat['wechat_appsecret']):'', 'secret'=>isset($wechat['wechat_appsecret']) ? $wechat['wechat_appsecret']:'',
'token'=>isset($wechat['wechat_token']) ? trim($wechat['wechat_token']):'', 'token'=>isset($wechat['wechat_token']) ? $wechat['wechat_token']:'',
'guzzle' => [ 'guzzle' => [
'timeout' => 10.0, // 超时时间(秒) 'timeout' => 10.0, // 超时时间(秒)
], ],
]; ];
if((int)$wechat['wechat_encode']>0 && isset($wechat['wechat_encodingaeskey']) && !empty($wechat['wechat_encodingaeskey']))
$config['aes_key'] = $wechat['wechat_encodingaeskey'];
if(isset($payment['pay_weixin_open']) && $payment['pay_weixin_open'] == 1){ if(isset($payment['pay_weixin_open']) && $payment['pay_weixin_open'] == 1){
$config['payment'] = [ $config['payment'] = [
'merchant_id'=>trim($payment['pay_weixin_mchid']), 'merchant_id'=>$payment['pay_weixin_mchid'],
'key'=>trim($payment['pay_weixin_key']), 'key'=>$payment['pay_weixin_key'],
'cert_path'=>realpath('.'.$payment['pay_weixin_client_cert']), 'cert_path'=>realpath('.'.$payment['pay_weixin_client_cert']),
'key_path'=>realpath('.'.$payment['pay_weixin_client_key']), 'key_path'=>realpath('.'.$payment['pay_weixin_client_key']),
'notify_url'=>SystemConfigService::get('site_url').Url::build('wap/Wechat/notify') 'notify_url'=>SystemConfigService::get('site_url').Url::build('wap/Wechat/notify')
@ -62,9 +61,6 @@ class WechatService
return self::$instance; return self::$instance;
} }
/**
* 微信接口
*/
public static function serve() public static function serve()
{ {
$wechat = self::application(true); $wechat = self::application(true);
@ -133,6 +129,7 @@ class WechatService
$response = HookService::resultListen('wechat_message_other',$message,null,true,$behavior); $response = HookService::resultListen('wechat_message_other',$message,null,true,$behavior);
break; break;
} }
return $response; return $response;
}); });
} }
@ -370,11 +367,6 @@ class WechatService
return self::paymentService()->refund($orderNo,$refundNo,$totalFee,$refundFee,$opUserId,$type,$refundAccount,$refundReason); return self::paymentService()->refund($orderNo,$refundNo,$totalFee,$refundFee,$opUserId,$type,$refundAccount,$refundReason);
} }
/**订单退款
* @param $orderNo
* @param array $opt
* @return bool
*/
public static function payOrderRefund($orderNo, array $opt) public static function payOrderRefund($orderNo, array $opt)
{ {
if(!isset($opt['pay_price'])) exception('缺少pay_price'); if(!isset($opt['pay_price'])) exception('缺少pay_price');
@ -420,10 +412,6 @@ class WechatService
return self::application()->js; return self::application()->js;
} }
/** jsSdk
* @param string $url
* @return array|string
*/
public static function jsSdk($url = '') public static function jsSdk($url = '')
{ {
$apiList = ['onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone', 'startRecord', 'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'onVoicePlayEnd', 'uploadVoice', 'downloadVoice', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'translateVoice', 'getNetworkType', 'openLocation', 'getLocation', 'hideOptionMenu', 'showOptionMenu', 'hideMenuItems', 'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem', 'closeWindow', 'scanQRCode', 'chooseWXPay', 'openProductSpecificView', 'addCard', 'chooseCard', 'openCard']; $apiList = ['onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone', 'startRecord', 'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'onVoicePlayEnd', 'uploadVoice', 'downloadVoice', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'translateVoice', 'getNetworkType', 'openLocation', 'getLocation', 'hideOptionMenu', 'showOptionMenu', 'hideMenuItems', 'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem', 'closeWindow', 'scanQRCode', 'chooseWXPay', 'openProductSpecificView', 'addCard', 'chooseCard', 'openCard'];

View File

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

View File

@ -2,7 +2,7 @@
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ] // | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved. // | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
@ -11,7 +11,6 @@
namespace think\db; namespace think\db;
use BadMethodCallException;
use PDO; use PDO;
use think\Exception; use think\Exception;
@ -26,7 +25,7 @@ abstract class Builder
protected $exp = ['eq' => '=', 'neq' => '<>', 'gt' => '>', 'egt' => '>=', 'lt' => '<', 'elt' => '<=', 'notlike' => 'NOT LIKE', 'not like' => 'NOT LIKE', 'like' => 'LIKE', 'in' => 'IN', 'exp' => 'EXP', 'notin' => 'NOT IN', 'not in' => 'NOT IN', 'between' => 'BETWEEN', 'not between' => 'NOT BETWEEN', 'notbetween' => 'NOT BETWEEN', 'exists' => 'EXISTS', 'notexists' => 'NOT EXISTS', 'not exists' => 'NOT EXISTS', 'null' => 'NULL', 'notnull' => 'NOT NULL', 'not null' => 'NOT NULL', '> time' => '> TIME', '< time' => '< TIME', '>= time' => '>= TIME', '<= time' => '<= TIME', 'between time' => 'BETWEEN TIME', 'not between time' => 'NOT BETWEEN TIME', 'notbetween time' => 'NOT BETWEEN TIME']; protected $exp = ['eq' => '=', 'neq' => '<>', 'gt' => '>', 'egt' => '>=', 'lt' => '<', 'elt' => '<=', 'notlike' => 'NOT LIKE', 'not like' => 'NOT LIKE', 'like' => 'LIKE', 'in' => 'IN', 'exp' => 'EXP', 'notin' => 'NOT IN', 'not in' => 'NOT IN', 'between' => 'BETWEEN', 'not between' => 'NOT BETWEEN', 'notbetween' => 'NOT BETWEEN', 'exists' => 'EXISTS', 'notexists' => 'NOT EXISTS', 'not exists' => 'NOT EXISTS', 'null' => 'NULL', 'notnull' => 'NOT NULL', 'not null' => 'NOT NULL', '> time' => '> TIME', '< time' => '< TIME', '>= time' => '>= TIME', '<= time' => '<= TIME', 'between time' => 'BETWEEN TIME', 'not between time' => 'NOT BETWEEN TIME', 'notbetween time' => 'NOT BETWEEN TIME'];
// SQL表达式 // SQL表达式
protected $selectSql = 'SELECT%DISTINCT% %FIELD% FROM %TABLE%%FORCE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%LOCK%%COMMENT%'; protected $selectSql = 'SELECT%DISTINCT% %FIELD% FROM %TABLE%%FORCE%%JOIN%%WHERE%%GROUP%%HAVING%%UNION%%ORDER%%LIMIT%%LOCK%%COMMENT%';
protected $insertSql = '%INSERT% INTO %TABLE% (%FIELD%) VALUES (%DATA%) %COMMENT%'; protected $insertSql = '%INSERT% INTO %TABLE% (%FIELD%) VALUES (%DATA%) %COMMENT%';
protected $insertAllSql = '%INSERT% INTO %TABLE% (%FIELD%) %DATA% %COMMENT%'; protected $insertAllSql = '%INSERT% INTO %TABLE% (%FIELD%) %DATA% %COMMENT%';
protected $updateSql = 'UPDATE %TABLE% SET %SET% %JOIN% %WHERE% %ORDER%%LIMIT% %LOCK%%COMMENT%'; protected $updateSql = 'UPDATE %TABLE% SET %SET% %JOIN% %WHERE% %ORDER%%LIMIT% %LOCK%%COMMENT%';
@ -99,8 +98,11 @@ abstract class Builder
$result = []; $result = [];
foreach ($data as $key => $val) { foreach ($data as $key => $val) {
$item = $this->parseKey($key, $options); $item = $this->parseKey($key, $options, true);
if (is_object($val) && method_exists($val, '__toString')) { if ($val instanceof Expression) {
$result[$item] = $val->getValue();
continue;
} elseif (is_object($val) && method_exists($val, '__toString')) {
// 对象数据写入 // 对象数据写入
$val = $val->__toString(); $val = $val->__toString();
} }
@ -110,8 +112,25 @@ abstract class Builder
} }
} elseif (is_null($val)) { } elseif (is_null($val)) {
$result[$item] = 'NULL'; $result[$item] = 'NULL';
} elseif (isset($val[0]) && 'exp' == $val[0]) { } elseif (is_array($val) && !empty($val)) {
$result[$item] = $val[1]; switch (strtolower($val[0])) {
case 'inc':
// $result[$item] = $item . '+' . floatval($val[1]);
if ($key == $val[1]) {
$result[$item] = $this->parseKey($val[1]) . '+' . floatval($val[2]);
}
break;
case 'dec':
// $result[$item] = $item . '-' . floatval($val[1]);
if ($key == $val[1]) {
$result[$item] = $this->parseKey($val[1]) . '-' . floatval($val[2]);
}
break;
case 'exp':
throw new Exception('not support data:[' . $val[0] . ']');
}
} elseif (is_scalar($val)) { } elseif (is_scalar($val)) {
// 过滤非标量数据 // 过滤非标量数据
if (0 === strpos($val, ':') && $this->query->isBind(substr($val, 1))) { if (0 === strpos($val, ':') && $this->query->isBind(substr($val, 1))) {
@ -133,7 +152,7 @@ abstract class Builder
* @param array $options * @param array $options
* @return string * @return string
*/ */
protected function parseKey($key, $options = []) protected function parseKey($key, $options = [], $strict = false)
{ {
return $key; return $key;
} }
@ -174,8 +193,10 @@ abstract class Builder
// 支持 'field1'=>'field2' 这样的字段别名定义 // 支持 'field1'=>'field2' 这样的字段别名定义
$array = []; $array = [];
foreach ($fields as $key => $field) { foreach ($fields as $key => $field) {
if (!is_numeric($key)) { if ($field instanceof Expression) {
$array[] = $this->parseKey($key, $options) . ' AS ' . $this->parseKey($field, $options); $array[] = $field->getValue();
} elseif (!is_numeric($key)) {
$array[] = $this->parseKey($key, $options) . ' AS ' . $this->parseKey($field, $options, true);
} else { } else {
$array[] = $this->parseKey($field, $options); $array[] = $this->parseKey($field, $options);
} }
@ -197,9 +218,6 @@ abstract class Builder
$item = []; $item = [];
foreach ((array) $tables as $key => $table) { foreach ((array) $tables as $key => $table) {
if (!is_numeric($key)) { if (!is_numeric($key)) {
if (strpos($key, '@think')) {
$key = strstr($key, '@think', true);
}
$key = $this->parseSqlTable($key); $key = $this->parseSqlTable($key);
$item[] = $this->parseKey($key) . ' ' . (isset($options['alias'][$table]) ? $this->parseKey($options['alias'][$table]) : $this->parseKey($table)); $item[] = $this->parseKey($key) . ' ' . (isset($options['alias'][$table]) ? $this->parseKey($options['alias'][$table]) : $this->parseKey($table));
} else { } else {
@ -257,7 +275,9 @@ abstract class Builder
foreach ($where as $key => $val) { foreach ($where as $key => $val) {
$str = []; $str = [];
foreach ($val as $field => $value) { foreach ($val as $field => $value) {
if ($value instanceof \Closure) { if ($value instanceof Expression) {
$str[] = ' ' . $key . ' ( ' . $value->getValue() . ' )';
} elseif ($value instanceof \Closure) {
// 使用闭包查询 // 使用闭包查询
$query = new Query($this->connection); $query = new Query($this->connection);
call_user_func_array($value, [ & $query]); call_user_func_array($value, [ & $query]);
@ -298,7 +318,7 @@ abstract class Builder
protected function parseWhereItem($field, $val, $rule = '', $options = [], $binds = [], $bindName = null) protected function parseWhereItem($field, $val, $rule = '', $options = [], $binds = [], $bindName = null)
{ {
// 字段分析 // 字段分析
$key = $field ? $this->parseKey($field, $options) : ''; $key = $field ? $this->parseKey($field, $options, true) : '';
// 查询规则和条件 // 查询规则和条件
if (!is_array($val)) { if (!is_array($val)) {
@ -331,13 +351,15 @@ abstract class Builder
throw new Exception('where express error:' . $exp); throw new Exception('where express error:' . $exp);
} }
} }
$bindName = $bindName ?: 'where_' . str_replace(['.', '-'], '_', $field); $bindName = $bindName ?: 'where_' . $rule . '_' . str_replace(['.', '-'], '_', $field);
if (preg_match('/\W/', $bindName)) { if (preg_match('/\W/', $bindName)) {
// 处理带非单词字符的字段名 // 处理带非单词字符的字段名
$bindName = md5($bindName); $bindName = md5($bindName);
} }
if (is_object($value) && method_exists($value, '__toString')) { if ($value instanceof Expression) {
} elseif (is_object($value) && method_exists($value, '__toString')) {
// 对象数据写入 // 对象数据写入
$value = $value->__toString(); $value = $value->__toString();
} }
@ -374,7 +396,11 @@ abstract class Builder
} }
} elseif ('EXP' == $exp) { } elseif ('EXP' == $exp) {
// 表达式查询 // 表达式查询
$whereStr .= '( ' . $key . ' ' . $value . ' )'; if ($value instanceof Expression) {
$whereStr .= '( ' . $key . ' ' . $value->getValue() . ' )';
} else {
throw new Exception('where express error:' . $exp);
}
} elseif (in_array($exp, ['NOT NULL', 'NULL'])) { } elseif (in_array($exp, ['NOT NULL', 'NULL'])) {
// NULL 查询 // NULL 查询
$whereStr .= $key . ' IS ' . $exp; $whereStr .= $key . ' IS ' . $exp;
@ -492,6 +518,11 @@ abstract class Builder
} }
} }
$bindName = $bindName ?: $key; $bindName = $bindName ?: $key;
if ($this->query->isBind($bindName)) {
$bindName .= '_' . str_replace('.', '_', uniqid('', true));
}
$this->query->bind($bindName, $value, $bindType); $this->query->bind($bindName, $value, $bindType);
return ':' . $bindName; return ':' . $bindName;
} }
@ -522,7 +553,9 @@ abstract class Builder
list($table, $type, $on) = $item; list($table, $type, $on) = $item;
$condition = []; $condition = [];
foreach ((array) $on as $val) { foreach ((array) $on as $val) {
if (strpos($val, '=')) { if ($val instanceof Expression) {
$condition[] = $val->getValue();
} elseif (strpos($val, '=')) {
list($val1, $val2) = explode('=', $val, 2); list($val1, $val2) = explode('=', $val, 2);
$condition[] = $this->parseKey($val1, $options) . '=' . $this->parseKey($val2, $options); $condition[] = $this->parseKey($val1, $options) . '=' . $this->parseKey($val2, $options);
} else { } else {
@ -546,28 +579,29 @@ abstract class Builder
*/ */
protected function parseOrder($order, $options = []) protected function parseOrder($order, $options = [])
{ {
if (is_array($order)) { if (empty($order)) {
return '';
}
$array = []; $array = [];
foreach ($order as $key => $val) { foreach ($order as $key => $val) {
if (is_numeric($key)) { if ($val instanceof Expression) {
if ('[rand]' == $val) { $array[] = $val->getValue();
if (method_exists($this, 'parseRand')) { } elseif ('[rand]' == $val) {
$array[] = $this->parseRand(); $array[] = $this->parseRand();
} else { } else {
throw new BadMethodCallException('method not exists:' . get_class($this) . '-> parseRand'); if (is_numeric($key)) {
} list($key, $sort) = explode(' ', strpos($val, ' ') ? $val : $val . ' ');
} elseif (false === strpos($val, '(')) {
$array[] = $this->parseKey($val, $options);
} else { } else {
$array[] = $val; $sort = $val;
} }
} else { $sort = strtoupper($sort);
$sort = in_array(strtolower(trim($val)), ['asc', 'desc']) ? ' ' . $val : ''; $sort = in_array($sort, ['ASC', 'DESC'], true) ? ' ' . $sort : '';
$array[] = $this->parseKey($key, $options) . ' ' . $sort; $array[] = $this->parseKey($key, $options, true) . $sort;
} }
} }
$order = implode(',', $array); $order = implode(',', $array);
}
return !empty($order) ? ' ORDER BY ' . $order : ''; return !empty($order) ? ' ORDER BY ' . $order : '';
} }
@ -601,6 +635,9 @@ abstract class Builder
*/ */
protected function parseComment($comment) protected function parseComment($comment)
{ {
if (false !== strpos($comment, '*/')) {
$comment = strstr($comment, '*/', true);
}
return !empty($comment) ? ' /* ' . $comment . ' */' : ''; return !empty($comment) ? ' /* ' . $comment . ' */' : '';
} }
@ -630,12 +667,12 @@ abstract class Builder
unset($union['type']); unset($union['type']);
foreach ($union as $u) { foreach ($union as $u) {
if ($u instanceof \Closure) { if ($u instanceof \Closure) {
$sql[] = $type . ' ' . $this->parseClosure($u, false); $sql[] = $type . ' ' . $this->parseClosure($u);
} elseif (is_string($u)) { } elseif (is_string($u)) {
$sql[] = $type . ' ' . $this->parseSqlTable($u); $sql[] = $type . ' ( ' . $this->parseSqlTable($u) . ' )';
} }
} }
return implode(' ', $sql); return ' ' . implode(' ', $sql);
} }
/** /**
@ -650,11 +687,7 @@ abstract class Builder
return ''; return '';
} }
if (is_array($index)) { return sprintf(" FORCE INDEX ( %s ) ", is_array($index) ? implode(',', $index) : $index);
$index = join(",", $index);
}
return sprintf(" FORCE INDEX ( %s ) ", $index);
} }
/** /**
@ -749,7 +782,7 @@ abstract class Builder
$fields = $options['field']; $fields = $options['field'];
} }
foreach ($dataSet as &$data) { foreach ($dataSet as $data) {
foreach ($data as $key => $val) { foreach ($data as $key => $val) {
if (!in_array($key, $fields, true)) { if (!in_array($key, $fields, true)) {
if ($options['strict']) { if ($options['strict']) {
@ -770,19 +803,25 @@ abstract class Builder
} }
$value = array_values($data); $value = array_values($data);
$values[] = 'SELECT ' . implode(',', $value); $values[] = 'SELECT ' . implode(',', $value);
if (!isset($insertFields)) {
$insertFields = array_keys($data);
} }
$fields = array_map([$this, 'parseKey'], array_keys(reset($dataSet))); }
$sql = str_replace(
foreach ($insertFields as $field) {
$fields[] = $this->parseKey($field, $options, true);
}
return str_replace(
['%INSERT%', '%TABLE%', '%FIELD%', '%DATA%', '%COMMENT%'], ['%INSERT%', '%TABLE%', '%FIELD%', '%DATA%', '%COMMENT%'],
[ [
$replace ? 'REPLACE' : 'INSERT', $replace ? 'REPLACE' : 'INSERT',
$this->parseTable($options['table'], $options), $this->parseTable($options['table'], $options),
implode(' , ', $fields), implode(' , ', $insertFields),
implode(' UNION ALL ', $values), implode(' UNION ALL ', $values),
$this->parseComment($options['comment']), $this->parseComment($options['comment']),
], $this->insertAllSql); ], $this->insertAllSql);
return $sql;
} }
/** /**

View File

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

View File

@ -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;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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