!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 ($Fields['fields'] as $index => $field) {
if($key == $field["title"]){
if($param == "" || count($param) == 0)
// if($param == "" || count($param) == 0)
if($param == "")
return Json::fail($field["name"]."不能为空!");
else{
$value[$key]["type"] = $field["type"];

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -27,25 +27,24 @@ class WechatService
{
private static $instance = null;
/**获取微信配置参数
* @return array
*/
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']);
$config = [
'app_id'=>isset($wechat['wechat_appid']) ? trim($wechat['wechat_appid']):'',
'secret'=>isset($wechat['wechat_appsecret']) ? trim($wechat['wechat_appsecret']):'',
'token'=>isset($wechat['wechat_token']) ? trim($wechat['wechat_token']):'',
'app_id'=>isset($wechat['wechat_appid']) ? $wechat['wechat_appid']:'',
'secret'=>isset($wechat['wechat_appsecret']) ? $wechat['wechat_appsecret']:'',
'token'=>isset($wechat['wechat_token']) ? $wechat['wechat_token']:'',
'guzzle' => [
'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){
$config['payment'] = [
'merchant_id'=>trim($payment['pay_weixin_mchid']),
'key'=>trim($payment['pay_weixin_key']),
'merchant_id'=>$payment['pay_weixin_mchid'],
'key'=>$payment['pay_weixin_key'],
'cert_path'=>realpath('.'.$payment['pay_weixin_client_cert']),
'key_path'=>realpath('.'.$payment['pay_weixin_client_key']),
'notify_url'=>SystemConfigService::get('site_url').Url::build('wap/Wechat/notify')
@ -62,9 +61,6 @@ class WechatService
return self::$instance;
}
/**
* 微信接口
*/
public static function serve()
{
$wechat = self::application(true);
@ -133,6 +129,7 @@ class WechatService
$response = HookService::resultListen('wechat_message_other',$message,null,true,$behavior);
break;
}
return $response;
});
}
@ -370,11 +367,6 @@ class WechatService
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)
{
if(!isset($opt['pay_price'])) exception('缺少pay_price');
@ -420,10 +412,6 @@ class WechatService
return self::application()->js;
}
/** jsSdk
* @param string $url
* @return array|string
*/
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'];

View File

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

View File

@ -2,7 +2,7 @@
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
@ -11,7 +11,6 @@
namespace think\db;
use BadMethodCallException;
use PDO;
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'];
// 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 $insertAllSql = '%INSERT% INTO %TABLE% (%FIELD%) %DATA% %COMMENT%';
protected $updateSql = 'UPDATE %TABLE% SET %SET% %JOIN% %WHERE% %ORDER%%LIMIT% %LOCK%%COMMENT%';
@ -99,8 +98,11 @@ abstract class Builder
$result = [];
foreach ($data as $key => $val) {
$item = $this->parseKey($key, $options);
if (is_object($val) && method_exists($val, '__toString')) {
$item = $this->parseKey($key, $options, true);
if ($val instanceof Expression) {
$result[$item] = $val->getValue();
continue;
} elseif (is_object($val) && method_exists($val, '__toString')) {
// 对象数据写入
$val = $val->__toString();
}
@ -110,8 +112,25 @@ abstract class Builder
}
} elseif (is_null($val)) {
$result[$item] = 'NULL';
} elseif (isset($val[0]) && 'exp' == $val[0]) {
$result[$item] = $val[1];
} elseif (is_array($val) && !empty($val)) {
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)) {
// 过滤非标量数据
if (0 === strpos($val, ':') && $this->query->isBind(substr($val, 1))) {
@ -133,7 +152,7 @@ abstract class Builder
* @param array $options
* @return string
*/
protected function parseKey($key, $options = [])
protected function parseKey($key, $options = [], $strict = false)
{
return $key;
}
@ -174,8 +193,10 @@ abstract class Builder
// 支持 'field1'=>'field2' 这样的字段别名定义
$array = [];
foreach ($fields as $key => $field) {
if (!is_numeric($key)) {
$array[] = $this->parseKey($key, $options) . ' AS ' . $this->parseKey($field, $options);
if ($field instanceof Expression) {
$array[] = $field->getValue();
} elseif (!is_numeric($key)) {
$array[] = $this->parseKey($key, $options) . ' AS ' . $this->parseKey($field, $options, true);
} else {
$array[] = $this->parseKey($field, $options);
}
@ -197,9 +218,6 @@ abstract class Builder
$item = [];
foreach ((array) $tables as $key => $table) {
if (!is_numeric($key)) {
if (strpos($key, '@think')) {
$key = strstr($key, '@think', true);
}
$key = $this->parseSqlTable($key);
$item[] = $this->parseKey($key) . ' ' . (isset($options['alias'][$table]) ? $this->parseKey($options['alias'][$table]) : $this->parseKey($table));
} else {
@ -257,7 +275,9 @@ abstract class Builder
foreach ($where as $key => $val) {
$str = [];
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);
call_user_func_array($value, [ & $query]);
@ -298,7 +318,7 @@ abstract class Builder
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)) {
@ -331,13 +351,15 @@ abstract class Builder
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)) {
// 处理带非单词字符的字段名
$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();
}
@ -374,7 +396,11 @@ abstract class Builder
}
} 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'])) {
// NULL 查询
$whereStr .= $key . ' IS ' . $exp;
@ -492,6 +518,11 @@ abstract class Builder
}
}
$bindName = $bindName ?: $key;
if ($this->query->isBind($bindName)) {
$bindName .= '_' . str_replace('.', '_', uniqid('', true));
}
$this->query->bind($bindName, $value, $bindType);
return ':' . $bindName;
}
@ -522,7 +553,9 @@ abstract class Builder
list($table, $type, $on) = $item;
$condition = [];
foreach ((array) $on as $val) {
if (strpos($val, '=')) {
if ($val instanceof Expression) {
$condition[] = $val->getValue();
} elseif (strpos($val, '=')) {
list($val1, $val2) = explode('=', $val, 2);
$condition[] = $this->parseKey($val1, $options) . '=' . $this->parseKey($val2, $options);
} else {
@ -546,28 +579,29 @@ abstract class Builder
*/
protected function parseOrder($order, $options = [])
{
if (is_array($order)) {
if (empty($order)) {
return '';
}
$array = [];
foreach ($order as $key => $val) {
if (is_numeric($key)) {
if ('[rand]' == $val) {
if (method_exists($this, 'parseRand')) {
if ($val instanceof Expression) {
$array[] = $val->getValue();
} elseif ('[rand]' == $val) {
$array[] = $this->parseRand();
} else {
throw new BadMethodCallException('method not exists:' . get_class($this) . '-> parseRand');
}
} elseif (false === strpos($val, '(')) {
$array[] = $this->parseKey($val, $options);
if (is_numeric($key)) {
list($key, $sort) = explode(' ', strpos($val, ' ') ? $val : $val . ' ');
} else {
$array[] = $val;
$sort = $val;
}
} else {
$sort = in_array(strtolower(trim($val)), ['asc', 'desc']) ? ' ' . $val : '';
$array[] = $this->parseKey($key, $options) . ' ' . $sort;
$sort = strtoupper($sort);
$sort = in_array($sort, ['ASC', 'DESC'], true) ? ' ' . $sort : '';
$array[] = $this->parseKey($key, $options, true) . $sort;
}
}
$order = implode(',', $array);
}
return !empty($order) ? ' ORDER BY ' . $order : '';
}
@ -601,6 +635,9 @@ abstract class Builder
*/
protected function parseComment($comment)
{
if (false !== strpos($comment, '*/')) {
$comment = strstr($comment, '*/', true);
}
return !empty($comment) ? ' /* ' . $comment . ' */' : '';
}
@ -630,12 +667,12 @@ abstract class Builder
unset($union['type']);
foreach ($union as $u) {
if ($u instanceof \Closure) {
$sql[] = $type . ' ' . $this->parseClosure($u, false);
$sql[] = $type . ' ' . $this->parseClosure($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 '';
}
if (is_array($index)) {
$index = join(",", $index);
}
return sprintf(" FORCE INDEX ( %s ) ", $index);
return sprintf(" FORCE INDEX ( %s ) ", is_array($index) ? implode(',', $index) : $index);
}
/**
@ -749,7 +782,7 @@ abstract class Builder
$fields = $options['field'];
}
foreach ($dataSet as &$data) {
foreach ($dataSet as $data) {
foreach ($data as $key => $val) {
if (!in_array($key, $fields, true)) {
if ($options['strict']) {
@ -770,19 +803,25 @@ abstract class Builder
}
$value = array_values($data);
$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%'],
[
$replace ? 'REPLACE' : 'INSERT',
$this->parseTable($options['table'], $options),
implode(' , ', $fields),
implode(' , ', $insertFields),
implode(' UNION ALL ', $values),
$this->parseComment($options['comment']),
], $this->insertAllSql);
return $sql;
}
/**

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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