作者 jinglong

新增加入购物车等接口

<?php
namespace app\admin\controller;
use app\common\controller\Backend;
/**
* 品牌分类轮播图管理
*
* @icon fa fa-circle-o
*/
class Btbanner extends Backend
{
/**
* Btbanner模型对象
* @var \app\admin\model\Btbanner
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\Btbanner;
}
/**
* 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
* 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
* 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
*/
/**
* 查看
*/
public function index()
{
//当前是否为关联查询
$this->relationSearch = false;
//设置过滤方法
$this->request->filter(['strip_tags', 'trim']);
if ($this->request->isAjax())
{
//如果发送的来源是Selectpage,则转发到Selectpage
if ($this->request->request('keyField'))
{
return $this->selectpage();
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$total = $this->model
->where($where)
->order($sort, $order)
->count();
$list = $this->model
->where($where)
->order($sort, $order)
->limit($offset, $limit)
->select();
foreach ($list as $row) {
$row->visible(['id','image','createtime']);
}
$list = collection($list)->toArray();
$result = array("total" => $total, "rows" => $list);
return json($result);
}
return $this->view->fetch();
}
}
... ...
... ... @@ -33,11 +33,8 @@ class Ggoods extends Backend
}
$this->assign('gtype',$arr);
//设计师
$this->assign('is_design',['否','是']);
//推荐
$this->assign('is_recommend',['否','是']);
//商品标识
$this->assign('flag',['普通','推荐','设计师作品','新人特惠']);
}
/**
... ...
... ... @@ -33,11 +33,8 @@ class Goods extends Backend
}
$this->assign('btype',$arr);
//设计师
$this->assign('is_design',['否','是']);
//推荐
$this->assign('is_recommend',['否','是']);
//商品标识
$this->assign('flag',['普通','推荐','设计师作品','新人特惠']);
}
/**
... ...
<?php
return [
'Id' => 'ID',
'Image' => '轮播图',
'Createtime' => '创建时间',
'Updatetime' => '更新时间'
];
... ...
... ... @@ -2,7 +2,7 @@
return [
'Id' => 'ID',
'Is_design' => '设计师作品',
'Flag' => '商品标识',
'T_id' => '品类分类',
'File' => '商品视频',
'Name' => '商品名称',
... ... @@ -16,7 +16,6 @@ return [
'Tag' => '商品标签',
'Stock' => '商品库存',
'Sort' => '排序',
'Is_recommend' => '推荐',
'Introduce' => '商品简介',
'Detail' => '商品详情',
'Createtime' => '创建时间',
... ...
... ... @@ -2,7 +2,7 @@
return [
'Id' => 'ID',
'Is_design' => '设计师作品',
'Flag' => '商品标识',
'T_id' => '品牌分类',
'File' => '商品视频',
'Name' => '商品名称',
... ... @@ -16,7 +16,6 @@ return [
'Tag' => '商品标签',
'Stock' => '商品库存',
'Sort' => '排序',
'Is_recommend' => '推荐',
'Introduce' => '商品简介',
'Detail' => '商品详情',
'Createtime' => '创建时间',
... ...
<?php
namespace app\admin\model;
use think\Model;
class Btbanner extends Model
{
// 表名
protected $name = 'btbanner';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
protected $deleteTime = false;
// 追加属性
protected $append = [
];
}
... ...
<?php
namespace app\admin\model;
use think\Model;
class Car extends Model
{
// 表名
protected $name = 'car';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
protected $deleteTime = false;
// 追加属性
protected $append = [
];
}
... ...
<?php
namespace app\admin\validate;
use think\Validate;
class Btbanner extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}
... ...
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group">
<input id="c-image" data-rule="required" class="form-control" size="50" name="row[image]" type="text">
<div class="input-group-addon no-border no-padding">
<span><button type="button" id="plupload-image" class="btn btn-danger plupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
</div>
<span class="msg-box n-right" for="c-image"></span>
</div>
<ul class="row list-inline plupload-preview" id="p-image"></ul>
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
... ...
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group">
<input id="c-image" data-rule="required" class="form-control" size="50" name="row[image]" type="text" value="{$row.image|htmlentities}">
<div class="input-group-addon no-border no-padding">
<span><button type="button" id="plupload-image" class="btn btn-danger plupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
</div>
<span class="msg-box n-right" for="c-image"></span>
</div>
<ul class="row list-inline plupload-preview" id="p-image"></ul>
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
... ...
<div class="panel panel-default panel-intro">
{:build_heading()}
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
<a href="javascript:;" class="btn btn-success btn-add {:$auth->check('btbanner/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
<a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('btbanner/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('btbanner/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
<!--<a href="javascript:;" class="btn btn-danger btn-import {:$auth->check('btbanner/import')?'':'hide'}" title="{:__('Import')}" id="btn-import-file" data-url="ajax/upload" data-mimetype="csv,xls,xlsx" data-multiple="false"><i class="fa fa-upload"></i> {:__('Import')}</a>-->
<!--<div class="dropdown btn-group {:$auth->check('btbanner/multi')?'':'hide'}">-->
<!--<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>-->
<!--<ul class="dropdown-menu text-left" role="menu">-->
<!--<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> {:__('Set to normal')}</a></li>-->
<!--<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li>-->
<!--</ul>-->
<!--</div>-->
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
data-operate-edit="{:$auth->check('btbanner/edit')}"
data-operate-del="{:$auth->check('btbanner/del')}"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>
... ...
... ... @@ -7,15 +7,9 @@
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Is_design')}:</label>
<label class="control-label col-xs-12 col-sm-2">{:__('Flag')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[is_design]', $is_design, null, ['class'=>'form-control', 'required'=>''])}
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Is_recommend')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[is_recommend]', $is_recommend, null, ['class'=>'form-control', 'required'=>''])}
{:build_select('row[flag]', $flag, null, ['class'=>'form-control', 'required'=>''])}
</div>
</div>
<div class="form-group">
... ...
... ... @@ -7,15 +7,9 @@
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Is_design')}:</label>
<label class="control-label col-xs-12 col-sm-2">{:__('Flag')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[is_design]', $is_design, $row.is_design, ['class'=>'form-control', 'required'=>''])}
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Is_recommend')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[is_recommend]', $is_recommend, $row.is_recommend, ['class'=>'form-control', 'required'=>''])}
{:build_select('row[flag]', $flag, $row.flag, ['class'=>'form-control', 'required'=>''])}
</div>
</div>
<div class="form-group">
... ...
... ... @@ -7,15 +7,9 @@
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Is_design')}:</label>
<label class="control-label col-xs-12 col-sm-2">{:__('Flag')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[is_design]', $is_design, null, ['class'=>'form-control', 'required'=>''])}
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Is_recommend')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[is_recommend]', $is_recommend, null, ['class'=>'form-control', 'required'=>''])}
{:build_select('row[flag]', $flag, null, ['class'=>'form-control', 'required'=>''])}
</div>
</div>
<div class="form-group">
... ...
... ... @@ -7,15 +7,9 @@
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Is_design')}:</label>
<label class="control-label col-xs-12 col-sm-2">{:__('Flag')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[is_design]', $is_design, $row.is_design, ['class'=>'form-control', 'required'=>''])}
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Is_recommend')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[is_recommend]', $is_recommend, $row.is_recommend, ['class'=>'form-control', 'required'=>''])}
{:build_select('row[flag]', $flag, $row.flag, ['class'=>'form-control', 'required'=>''])}
</div>
</div>
<div class="form-group">
... ...
... ... @@ -58,11 +58,13 @@ class Brand extends Api
$value['image'] = $this->auth->absolutionUrlOne($value['image']);
}
$arr['data'] = $res;
//品牌专区轮播图(暂时写死)
$arr['images'] = [
"http://jinglong.springchunjia.cn/uploads/20191127/febfea9a34c918cb2f100f669ede2547.png",
"http://jinglong.springchunjia.cn/uploads/20191127/042a3256122af7b10e26efb5e7649904.png"
];
//品牌专区轮播图
$res1 = Common::selectData('btbanner','id,image');
$images = [];
foreach ($res1 as $value1){
array_push($images,$this->auth->absolutionUrlOne($value1['image']));
}
$arr['images'] = $images;
$this->success('成功',$arr);
}else{
$this->error('请求方式错误');
... ...
<?php
namespace app\api\controller;
use app\admin\model\Car;
use app\common\controller\Api;
use think\Validate;
use think\Db;
/**
* 购物车接口
*/
class Cars extends Api
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
protected $uid = '';
public function _initialize()
{
parent::_initialize();
$this->uid = $this->auth->getUserId();
}
/**
* @ApiTitle (加入购物车)
* @ApiSummary (加入购物车)
* @ApiMethod (POST)
* @ApiRoute (/api/cars/addCar)
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
*
* @ApiParams (name="goods_id", type="inter", required=true, description="商品id")
* @ApiParams (name="style", type="string", required=true, description="商品款式")
* @ApiParams (name="price", type="inter", required=true, description="商品价格(新人价格或销售价)")
* @ApiParams (name="goods_number", type="inter", required=true, description="商品数量")
*
* @ApiReturn({
"code": 1,
"msg": "成功",
"time": "1575103466",
"data": null
})
*/
public function addCar(){
if($this->request->isPost()){
$data = $this->request->post();
$rule = config('verify.add_car');
$validate = new Validate($rule['rule'],$rule['msg']);
if (!$validate->check($data)) {
$this->error($validate->getError());
}
//检测库存
$stock = Common::findSoftWhereData('goods',['id'=>$data['goods_id']],'id,stock');
if($stock){
if(($stock['stock'] <=> $data['goods_number']) == -1){
$this->error('库存不足');
}
}
//查询有无记录
$where = [
'uid'=>$this->uid,
'g_id'=>$data['goods_id'],
'style'=>$data['style'],
'goods_number'=>$data['goods_number']
];
$res = Common::findWhereData('car',$where,'id,g_id');
$carModel = new Car();
if($res){
$carModel->where($where)->setInc('goods_number',$data['goods_number']);
}else{
$data['g_id'] = $data['goods_id'];
$data['uid'] = $this->uid;
unset($data['goods_id']);
$carModel->create($data);
}
$this->success('成功');
}else{
$this->error('请求方式错误');
}
}
/**
* @ApiTitle (购物车列表)
* @ApiSummary (购物车列表)
* @ApiMethod (GET)
* @ApiRoute (/api/cars/carList)
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
*
* @ApiReturn({
"code": 1,
"msg": "成功",
"time": "1575102913",
"data": {
"data": [
{
"id": 1,//购物车id
"image": "http://jinglong.springchunjia.cn/uploads/20191127/287ca016a4d41a239ec77c91d982309d.png",//商品图片
"price": 100,//商品价格
"goods_id": 1,//商品id
"goods_number": 2,//商品数量
"name": "MONENT 动感系列动感系列动感系列",//商品名称
"introduce": "轻波款,为客厅缀上霞光淡雾"//商品简介
},
{
"id": 2,
"price": 100,
"goods_id": 2,
"goods_number": 1,
"name": "MONENT 动感系列动感系列",
"introduce": "轻波款,为客厅缀上霞光淡雾"
}
],
"total_price": 300
}
})
*/
public function carList(){
if($this->request->isGet()){
$res = Db::name('car')
->alias('c')
->join('goods g','c.g_id = g.id','LEFT')
->where(['c.uid'=>$this->uid])
->field('c.id,c.g_id goods_id,c.price,c.goods_number,g.name,g.image,g.introduce')
->useSoftDelete('g.deletetime')
->select();
$total_price = 0;
foreach ($res as &$value){
$value['image'] = $this->auth->absolutionUrlOne($value['image']);
$total_price += $value['price'] * $value['goods_number'];
}
// $total_price = array_sum(array_map(function ($product_row) {
// return $product_row['price'] * $product_row['goods_number'];
// }, $res));
$arr['data'] = $res;
$arr['total_price'] = $total_price;
$this->success('成功',$arr);
}else{
$this->error('请求方式错误');
}
}
/**
* @ApiTitle (删除购物车)
* @ApiSummary (删除购物车)
* @ApiMethod (GET)
* @ApiRoute (/api/cars/deleteCar)
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
*
* @ApiParams (name="car_id", type="inter", required=true, description="购物车id")
*
* @ApiReturn({
"code": 1,
"msg": "成功",
"time": "1575103466",
"data": null
})
*/
public function deleteCar(){
if($this->request->isGet()){
$car_id = $this->request->get('car_id');
$rule = config('verify.delete_car');
$validate = new Validate($rule['rule'],$rule['msg']);
if (!$validate->check(['car_id'=>$car_id])) {
$this->error($validate->getError());
}
$carModel = new Car();
$res = $carModel->where(['id'=>$car_id,'uid'=>$this->uid])->delete();
if($res){
$this->success('成功');
}else{
$this->error('失败');
}
}else{
$this->error('请求方式错误');
}
}
/**
* @ApiTitle (商品结算)
* @ApiSummary (商品结算)
* @ApiMethod (GET)
* @ApiRoute (/api/cars/settleGoods)
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
*
* @ApiParams (name="goods_id", type="string", required=true, description="商品id(多个以逗号隔开,如:1,3,4)")
* @ApiParams (name="price", type="string", required=true, description="商品价格(多个以逗号隔开,如:100,10,200)")
* @ApiParams (name="goods_number", type="string", required=true, description="商品数量(多个以逗号隔开,如:10,10,10)")
*
* @ApiReturn({
"code": 1,
"msg": "成功",
"time": "1575106933",
"data": {
"data": [
{
"id": 2,//商品id
"name": "MONENT 动感系列动感系列",//商品名称
"image": "http://jinglong.springchunjia.cn/uploads/20191128/8a677f5a0418059bf1b974c50026af13.png",//商品图片路径
"introduce": "轻波款,为客厅缀上霞光淡雾",//商品简介
"price": "250",//商品价格
"goods_number": "5"//商品数量
},
{
"id": 1,
"name": "MONENT 动感系列动感系列动感系列",
"image": "http://jinglong.springchunjia.cn/uploads/20191128/93971e55b83d1a09c1831f8197514305.png",
"introduce": "轻波款,为客厅缀上霞光淡雾",
"price": "100",
"goods_number": "3"
}
],
"total_goods_price": 1550,//商品总金额
"total_expense_price": 10,//运费总金额
"total_price": 1560//总金额(商品总金额+运费总金额)
}
})
*/
public function settleGoods(){
if($this->request->isPost()){
$goods_id = $this->request->post('goods_id');
$price = $this->request->post('price');
$goods_number = $this->request->post('goods_number');
$rule = config('verify.settle_goods');
$validate = new Validate($rule['rule'],$rule['msg']);
if (!$validate->check(['goods_id'=>$goods_id,'price'=>$price,'goods_number'=>$goods_number])) {
$this->error($validate->getError());
}
$goods_id_s = explode(',',$goods_id);
$price_s = explode(',',$price);
$goods_number_s = explode(',',$goods_number);
//合并数组
$key = ['goods_id','price','goods_number'];
$res_goods = Common::array_merge_more($key,$goods_id_s,$price_s,$goods_number_s);
//查询商品
$res = Common::selectSoftWhereData('goods',['id'=>['in',$goods_id_s]],'id,name,image,expense_price,introduce');
$total_price = 0;//总商品费用(不含运费)
$total_expense_price = 0;//总运费
foreach ($res as &$value){
$value['image'] = $this->auth->absolutionUrlOne($value['image']);
foreach($res_goods as $g_value){
if($value['id'] == $g_value['goods_id']){
$value['price'] = $g_value['price'];//商品价格
$value['goods_number'] = $g_value['goods_number'];//商品数量
$total_price += $g_value['price'] * $g_value['goods_number'];
break;
}
}
$total_expense_price += $value['expense_price'];
unset($value['expense_price']);
}
$arr['data'] = $res;
$arr['total_goods_price'] = $total_price;
$arr['total_expense_price'] = $total_expense_price;
$arr['total_price'] = $total_price + $total_expense_price;
$this->success('成功',$arr);
}else{
$this->error('请求方式错误');
}
}
}
... ...
... ... @@ -69,6 +69,20 @@ class Common
}
/**
* 查找多条数据
* @ApiInternal
*/
public static function selectSoftWhereData($table,$where,$field,$order='id desc'){
$res = Db::name($table)
->where($where)
->field($field)
->order($order)
->useSoftDelete('deletetime')
->select();
return $res;
}
/**
* 查找多条数据(软删除,分页)
* @ApiInternal
*/
... ... @@ -118,32 +132,6 @@ class Common
}
/**
* 查找多条数据(限制条数)
* @ApiInternal
*/
public static function selectLimitData($table,$field,$limit){
$res = Db::name($table)
->field($field)
->limit($limit)
->select();
return $res;
}
/**
* 查找多条数据(有限制条数)
* @ApiInternal
*/
public static function selectWhereLimitData($table,$where,$field,$limit,$order='id desc'){
$res = Db::name($table)
->where($where)
->field($field)
->limit($limit)
->order($order)
->select();
return $res;
}
/**
* 查询总条数
* @ApiInternal
*/
... ... @@ -193,13 +181,13 @@ class Common
$arr = [];
$limit = config('verify.limit');
$res = Db::name('goods')
->field('LOCATE("'.$keyword.'",type_name) as tNameIndex,LOCATE("'.$keyword.'",name) as nameIndex,id,image,name,tag,new_price,sale_price,expense_price')//获取关键字的位置:LOCATE(关键字,字段) 返回索引位置
->field('LOCATE("'.$keyword.'",name) as nameIndex,id,image,name,tag,new_price,sale_price,expense_price')//获取关键字的位置:LOCATE(关键字,字段) 返回索引位置
->where($where)//多字段条件查询
->page($page,$limit)
->order('nameIndex, tNameIndex')//按tIndex 值排序
->order('nameIndex')//按tIndex 值排序
->select();
//$res = Common::selectSoftWherePageData('goods',$where,'id,image,name,tag,new_price,sale_price,expense_price',$page,$limit,$order);
foreach ($res as &$value){
$value['name'] = str_replace($keyword,'<a href="javascript:void(0);" style="color:red;">'.$keyword.'</a>',$value['name']);
$value['image'] = self::absolutionUrlOne($value['image']);
$value['tag'] = explode('|',$value['tag']);
}
... ... @@ -222,4 +210,37 @@ class Common
return $url;
}
/**
* 合并数组
* @ApiInternal
*/
public static function array_merge_more($keys, ...$arrs){
// 检查参数是否正确
if(!$keys || !is_array($keys) || !$arrs || !is_array($arrs) || count($keys)!=count($arrs)){
return array();
}
// 一维数组中最大长度
$max_len = 0;
// 整理数据,把所有一维数组转重新索引
for($i=0,$len=count($arrs); $i<$len; $i++){
$arrs[$i] = array_values($arrs[$i]);
if(count($arrs[$i])>$max_len){
$max_len = count($arrs[$i]);
}
}
// 合拼数据
$result = array();
for($i=0; $i<$max_len; $i++){
$tmp = array();
foreach($keys as $k=>$v){
if(isset($arrs[$k][$i])){
$tmp[$v] = $arrs[$k][$i];
}
}
$result[] = $tmp;
}
return $result;
}
}
... ...
... ... @@ -12,10 +12,12 @@ class Index extends Api
protected $noNeedLogin = ['*'];
protected $noNeedRight = ['*'];
protected $uid = '';
protected $flag = '';
public function _initialize()
{
parent::_initialize();
$this->uid = $this->auth->getUserId();
$this->flag = config('verify.flag');
}
/**
... ... @@ -108,7 +110,7 @@ class Index extends Api
$arr['res_advert'] = $res_advert;
//设计师作品
$res_design = Common::selectSoftWhereLimitData('goods',['is_design'=>1],'id,name,introduce,sale_price,file','sort desc');
$res_design = Common::selectSoftWhereLimitData('goods',['flag'=>$this->flag[2]],'id,name,introduce,sale_price,file','sort desc');
foreach ($res_design as &$d_value){
//获取视频帧
$d_value['image'] = $this->auth->absolutionUrlOneFrame($d_value['file'],2);
... ... @@ -217,7 +219,7 @@ class Index extends Api
$this->error($validate->getError());
}
$where = ['is_recommend'=>1];
$where = ['flag'=>$this->flag[1]];
$arr = Common::goodsList($where,$page);
$this->success('成功',$arr);
}else{
... ...
<?php
namespace app\api\controller;
use app\admin\model\Record;
use app\common\controller\Api;
use think\Validate;
/**
* 新人特惠接口
*/
class News extends Api
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
protected $uid = '';
public function _initialize()
{
parent::_initialize();
}
/**
* @ApiTitle (新人特惠商品列表)
* @ApiSummary (新人特惠商品列表)
* @ApiMethod (GET)
* @ApiRoute (/api/news/newsGoodsList)
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
*
* @ApiParams (name="page", type="inter", required=true, description="分页页码")
*
* @ApiReturn({
"code": 1,
"msg": "成功",
"time": "1574941706",
"data": {
"data": [
{
"id": 7,//商品id
"image": "http://jinglong.springchunjia.cn/uploads/20191128/8a677f5a0418059bf1b974c50026af13.png",//图片路径
"name": "MONENT 动感系列",//商品名称
"tag": [//商品标签
"日式简约",
"隐秘乡奢",
"家庭情侣"
],
"new_price": 2199,//新人价格(未登录,未购买记录(个人中心返是否有购买记录),显示该字段,另加“新人价”标签)
"sale_price": 2299//销售价格
"expense_price": //运费(0:显示包运费标签)
},
{
"id": 4,
"image": "http://jinglong.springchunjia.cn/uploads/20191128/93971e55b83d1a09c1831f8197514305.png",
"name": "MONENT 动感系列",
"tag": [
"AB级",
"ABX级",
"ABN级"
],
"new_price": 2499,
"sale_price": 2599
},
],
"total_page": 1
}
})
*/
public function newsGoodsList(){
if($this->request->isGet()){
$page = $this->request->get('page');
$rule = config('verify.page');
$validate = new Validate($rule['rule'],$rule['msg']);
if (!$validate->check(['page'=>$page])) {
$this->error($validate->getError());
}
$flag = config('verify.flag');
$where = ['flag'=>$flag[3]];
$limit = config('verify.goods_limit');
$arr = Common::goodsList($where,$page,$limit);
$this->success('成功',$arr);
}else{
$this->error('请求方式错误');
}
}
}
... ...
<?php
namespace app\api\controller;
use app\admin\model\PayMember;
use app\admin\model\ToBalance;
use app\common\controller\Api;
use EasyWeChat\Factory;
use function GuzzleHttp\Promise\inspect;
use think\Db;
use app\admin\model\User;
use think\Log;
use fast\Http;
use think\Validate;
use Exception;
use function EasyWeChat\Kernel\Support\generate_sign;
/**
* 支付接口
*/
class Pay extends Api
{
protected $noNeedLogin = ['payMemberNotify','paySecurityNotify','payOrderNotify'];
protected $noNeedRight = ['*'];
protected $uid = '';//token存贮uid
protected $order_status = [];//订单状态
public function _initialize()
{
parent::_initialize();
$this->uid = $this->auth->getUserId();
}
/**
* @ApiTitle (购买会员/支付订单)
* @ApiSummary (购买会员)
* @ApiMethod (POST)
* @ApiRoute (/api/pay/pay)
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
*
* @ApiParams (name="openid", type="string", required=true, description="小程序openid")
* @ApiParams (name="order_sn", type="inter", required=false, description="支付订单号")
*
*/
public function pay(){
if($this->request->isPost()){
$openid = $this->request->post('openid');
$order_sn = $this->request->post('order_sn');
$rule = config('verify.pay_member');
$validate = new Validate($rule['rule'],$rule['msg']);
if (!$validate->check(['openid'=>$openid])) {
$this->error($validate->getError());
}
$hotel_url = config('verify.hotel_url');
if($order_sn){
//支付订单
$res = Db::name('order')->where(['order_sn'=>$order_sn,'uid'=>$this->uid])->find();
if($res){
if($res['status'] == 0){
//判断该房间是否已被预订
$res2 = $this->auth->getHouseDetailId(['house_id'=>$res['house_id']]);
$full_time = [];
foreach($res2 as $r_value){
if($res['book_count'] <= $r_value['book_count']){
//满房时间
array_push($full_time,$r_value['book_time']);
}
}
if(in_array($res['start_time'],$full_time)){
$this->error('该房屋已被预订');
}
$pay_order = $order_sn;
$notify_url = $hotel_url.'/api/pay/payOrderNotify';
$total_fee = $res['security_price'];
}else{
$this->error('该订单已支付过了');
}
}else{
$this->error('无效的订单');
}
}else{
//购买会员
$pay_order = $this->auth->genPayOrderSn('pay');//支付订单号
$notify_url = $hotel_url.'/api/pay/payMemberNotify';
$total_fee = 0.01;//会员价格暂为0.01元
}
//创建支付对象
$config = config('verify.wx_pay');
$app = Factory::payment($config);
$result = $app->order->unify([
'body' => '佛山市理想中网络科技有限公司',
'out_trade_no' => $pay_order,//支付订单号
'total_fee' => $total_fee*100,//单位分
'notify_url' => $notify_url, // 支付结果通知网址,如果不设置则会使用配置里的默认地址
'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
'openid' => $openid,
]);
if($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS'){
$params = [
'appId' => $config['app_id'],
'timeStamp' => time(),
'nonceStr' => $result['nonce_str'], // 统一下单返回的随机字符串
'package' => 'prepay_id='.$result['prepay_id'], // 统一下单Id
'signType' => 'MD5', // 签名方法
];
// 注意这里用的是商户平台的Key进行二次签名
$params['paySign'] = generate_sign($params, $config['key']);
$this->success('成功',$params);
}
$this->error($result['err_code_des']);
}else{
$this->error('请求方式错误');
}
}
//购买会员回调通知(无需调用)
public function payMemberNotify(){
$config = config('verify.wx_pay');
$app = Factory::payment($config);
Log::info('会员');
$response = $app->handlePaidNotify(function($message, $fail){
//return_code 表示通信状态
Log::info($message);
if ($message['return_code'] === 'SUCCESS') {
if ($message['result_code'] === 'SUCCESS') {
//支付成功
//更新成为会员
$userModel = new User();
$userModel->where('openid',$message['openid'])->update(['member'=>1]);
//增加记录
$payMemberModel = new PayMember();
$payMemberModel->create(['openid'=>$message['openid'],'pay_order'=>$message['out_trade_no']]);
}elseif($message['result_code'] === 'FAIL') {
//支付失败
}
} else {
return $fail('通信失败,请稍后再通知我');
}
return true; // 返回处理完成
});
$response->send();
}
//支付订单(无需调用)
public function payOrderNotify(){
$config = config('verify.wx_pay');
$app = Factory::payment($config);
$response = $app->handlePaidNotify(function($message, $fail){
//return_code 表示通信状态
if ($message['return_code'] === 'SUCCESS') {
if ($message['result_code'] === 'SUCCESS') {
//支付成功,更新订单状态
$orderModel = new \app\admin\model\Order();
$orderModel->where(['order_sn'=>$message['out_trade_no']])->update(['status'=>1]);
//创建订房记录
$this->auth->createHouseRecord($message['out_trade_no']);
//发送(预订成功)验证码
$this->auth->sendCodeBook($message['out_trade_no']);
}elseif($message['result_code'] === 'FAIL') {
//支付失败
}
} else {
return $fail('通信失败,请稍后再通知我');
}
return true; // 返回处理完成
});
$response->send();
}
/**
* @ApiTitle (支付保证金)
* @ApiSummary (支付保证金)
* @ApiMethod (POST)
* @ApiRoute (/api/pay/paySecurityPrice)
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
*
* @ApiParams (name="openid", type="string", required=true, description="小程序openid")
* @ApiParams (name="house_id", type="inter", required=true, description="房屋id")
* @ApiParams (name="date_range", type="string", required=true, description="预定日期范围(2019-10-11,2019-10-12或者2019-10-11,2019-10-13)")
* @ApiParams (name="security_price", type="inter", required=true, description="保证金")
*/
public function paySecurityPrice(){
if($this->request->isPost()){
$data = $this->request->post();
$rule = config('verify.pay_security');
$validate = new Validate($rule['rule'],$rule['msg']);
if (!$validate->check($data)) {
$this->error($validate->getError());
}
//创建支付对象
$config = config('verify.wx_pay');
$app = Factory::payment($config);
$pay_order = $this->auth->genPayOrderSn('pay');//支付订单号
$hotel_url = config('verify.hotel_url');
$result = $app->order->unify([
'body' => '佛山市理想中网络科技有限公司',
'out_trade_no' => $pay_order,//支付订单号
'total_fee' => $data['security_price']*100,//单位分
'notify_url' => $hotel_url.'/api/pay/paySecurityNotify', // 支付结果通知网址,如果不设置则会使用配置里的默认地址
'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
'openid' => $data['openid'],
]);
if($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS'){
$params = [
'appId' => $config['app_id'],
'timeStamp' => time(),
'nonceStr' => $result['nonce_str'], // 统一下单返回的随机字符串
'package' => 'prepay_id='.$result['prepay_id'], // 统一下单Id
'signType' => 'MD5', // 签名方法
];
// 注意这里用的是商户平台的Key进行二次签名
$params['paySign'] = generate_sign($params, $config['key']);
//写入订单
$res = $this->auth->createOrder($data['house_id'],$data['date_range'],$pay_order);
if($res){
$this->success('成功',['data'=>$params,'order_sn'=>$pay_order,'order_id'=>$res['order_id']]);
}
$this->error('创建订单失败');
}
$this->error($result['err_code_des']);
}else{
$this->error('请求方式错误');
}
}
//支付保证金回调(无需调用)
public function paySecurityNotify(){
$config = config('verify.wx_pay');
$app = Factory::payment($config);
$response = $app->handlePaidNotify(function($message, $fail){
//return_code 表示通信状态
if ($message['return_code'] === 'SUCCESS') {
if ($message['result_code'] === 'SUCCESS') {
//支付成功
//更新成为待出行状态
$orderModel = new \app\admin\model\Order();
$orderModel->where(['order_sn'=>$message['out_trade_no']])->update(['status'=>1]);
//创建订房记录
$this->auth->createHouseRecord($message['out_trade_no']);
//发送(预订成功)验证码
$this->auth->sendCodeBook($message['out_trade_no']);
}elseif($message['result_code'] === 'FAIL') {
//支付失败,好像有问题
}
} else {
return $fail('通信失败,请稍后再通知我');
}
return true; // 返回处理完成
});
$response->send();
}
/**
* @ApiTitle (更新订单号(支付订单失败后调用))
* @ApiSummary (更新订单号(支付订单失败后调用))
* @ApiMethod (POST)
* @ApiRoute (/api/pay/updateOrder)
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
*
* @ApiParams (name="order_sn", type="inter", required=false, description="支付订单号")
*
* @ApiReturn({
"code": 1,
"msg": "成功",
"time": "1571812329",
"data": null
})
*/
public function updateOrder(){
if($this->request->isPost()){
$order_sn = $this->request->post('order_sn');
$rule = config('verify.order_sn');
$validate = new Validate($rule['rule'],$rule['msg']);
if (!$validate->check(['order_sn'=>$order_sn])) {
$this->error($validate->getError());
}
$orderModel = new \app\admin\model\Order();
$pay_order = $this->auth->genPayOrderSn('pay');//支付订单号
$res = $orderModel->where(['order_sn'=>$order_sn,'uid'=>$this->uid])->update(['order_sn'=>$pay_order]);
if($res){
$this->success('成功');
}else{
$this->error('失败');
}
}else{
$this->error('请求方式错误');
}
}
/**
* @ApiTitle (提现到微信零钱)
* @ApiSummary (提现到微信零钱)
* @ApiMethod (POST)
* @ApiRoute (/api/pay/payBalance)
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
*
* @ApiParams (name="openid", type="string", required=true, description="小程序openid")
* @ApiParams (name="price", type="inter", required=true, description="提现金额")
*/
public function payBalance(){
if($this->request->isPost()){
$price = $this->request->post('price');
$openid = $this->request->post('openid');
$rule = config('verify.to_balance');
$validate = new Validate($rule['rule'],$rule['msg']);
if (!$validate->check(['price'=>$price,'openid'=>$openid])) {
$this->error($validate->getError());
}
if($price < 0.3){
$this->error('提现金额不能低于0.3元');
}
//每天提现次数不超过三次
$count = Db::name('to_balance')->where('uid',$this->uid)->whereTime('createtime','today')->count();
if($count >= 3){
$this->error('每天提现次数不能超过3次');
}
//查询该用户钱包金额
$userModel = new User();
$user = $userModel->where(['id'=>$this->uid])->field('id,money,nickname')->find();
if($price > $user['money']){
$this->error('钱包金额不足');
}
//创建支付对象
$config = config('verify.wx_pay');
$app = Factory::payment($config);
$balance_order = $this->auth->genPayOrderSn('balance');//提现单号
$result = $app->transfer->toBalance([
'partner_trade_no' => $balance_order, // 商户订单号,需保持唯一性(只能是字母或者数字,不能包含有符号)
'openid' => $openid,
'check_name' => 'NO_CHECK', // NO_CHECK:不校验真实姓名, FORCE_CHECK:强校验真实姓名
're_user_name' => '', // 如果 check_name 设置为FORCE_CHECK,则必填用户真实姓名
'amount' => $price*100, // 企业付款金额,单位为分
'desc' => '提现到零钱', // 企业付款操作说明信息。必填
]);
if($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS'){
//创建提现记录
$balanceRecordModel = new ToBalance();
$data['uid'] = $this->uid;
$data['openid'] = $openid;
$data['price'] = $price;
$data['to_order'] = $result['partner_trade_no'];
$balanceRecordModel->create($data);
//更新余额表
$userModel = new User();
$userModel->where(['id'=>$this->uid])->setDec('money',$price);
$this->success('成功');
}
$this->error($result['err_code_des']);
}else{
$this->error('请求方式错误');
}
}
}
... ...
... ... @@ -76,6 +76,7 @@ class Search extends Api
}
$where = ['type_name|name'=>['like','%'.$keyword.'%']];
//暂时
$arr = Common::searchGoodsList($keyword,$where,$page);
//写入检索记录
// $record = Common::findWhereData('record',['uid'=>$this->uid,'keyword'=>$keyword],'id,keyword');
... ...
... ... @@ -131,13 +131,13 @@ class Api
$this->auth->init($token);
//检测是否登录
if (!$this->auth->isLogin()) {
$this->error(__('Please login first'), null, 401);
$this->error(__('Please login first') );
}
// 判断是否需要验证权限
if (!$this->auth->match($this->noNeedRight)) {
// 判断控制器和方法判断是否有对应权限
if (!$this->auth->check($path)) {
$this->error(__('You have no permission'), null, 403);
$this->error(__('You have no permission'));
}
}
} else {
... ...
... ... @@ -19,6 +19,8 @@ return [
],
//七牛云域名
'host' => 'http://jinglong.springchunjia.cn',
//商品标识
'flag' => [0,1,2,3],//0:普通,1:推荐,2:设计师作品,3:新人特惠
//分页数
'limit' => 10,
//商品分页
... ... @@ -114,4 +116,45 @@ return [
'page.number' => '分页页码必须为数字',
]
],
//加入购物车
'add_car' => [
'rule' => [
'goods_id' => 'require|number',
'style' => 'require',
'price' => 'require|number',
'goods_number' => 'require|number',
],
'msg' => [
'goods_id.require' => '商品id不能为空',
'goods_id.number' => '商品id必须为数字',
'style.require' => '商品规格不能为空',
'price.require' => '商品价格不能为空',
'price.number' => '商品价格必须为数字',
'goods_number.require' => '商品数量不能为空',
'goods_number.number' => '商品数量必须为数字',
]
],
//删除购物车
'delete_car' => [
'rule' => [
'car_id' => 'require|number',
],
'msg' => [
'car_id.require' => '购物车id不能为空',
'car_id.number' => '购物车id必须为数字',
]
],
//商品结算
'settle_goods' => [
'rule' => [
'goods_id' => 'require',
'price' => 'require',
'goods_number' => 'require',
],
'msg' => [
'goods_id.require' => '商品id不能为空',
'price.require' => '商品价格不能为空',
'goods_number.require' => '商品数量不能为空',
]
],
];
\ No newline at end of file
... ...
此 diff 太大无法显示。
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: function () {
// 初始化表格参数配置
Table.api.init({
extend: {
index_url: 'btbanner/index' + location.search,
add_url: 'btbanner/add',
edit_url: 'btbanner/edit',
del_url: 'btbanner/del',
multi_url: 'btbanner/multi',
table: 'btbanner',
}
});
var table = $("#table");
// 初始化表格
table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'id',
columns: [
[
{checkbox: true},
{field: 'id', title: __('Id')},
{field: 'image', title: __('Image'), events: Table.api.events.image, formatter: Table.api.formatter.image},
{field: 'createtime', title: __('Createtime'), operate:'RANGE', addclass:'datetimerange', formatter: Table.api.formatter.datetime},
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
]
]
});
// 为表格绑定事件
Table.api.bindevent(table);
},
add: function () {
Controller.api.bindevent();
},
edit: function () {
Controller.api.bindevent();
},
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
}
}
};
return Controller;
});
\ No newline at end of file
... ...
... ... @@ -31,12 +31,27 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
{field: 'name', title: __('Name')},//商品名称
{field: 'name_en', title: __('Name_en')},//商品名称(英文)
{field: 'image', title: __('Image'),events: Table.api.events.image, formatter: Table.api.formatter.image},//商品图
{field: 'is_design', title: __('Is_design'),formatter: Table.api.formatter.label, searchList: {0: __('否'), 1: __('是')}},//是否设计师作品
{field: 'flag', title: __('Flag'),searchList: {0: __('普通'), 1: __('推荐'),2: __('设计师作品'), 3: __('新人特惠')},formatter:
function(value,row,index){
if (row.flag === 0)
{
return '<span style="color:green">普通</span>';
}else if (row.flag === 1)
{
return '<span style="color:red">推荐</span>';
}else if (row.flag === 2)
{
return '<span style="color:purple">设计师作品</span>';
}else if (row.flag === 3)
{
return '<span style="color:blue">新人特惠</span>';
}
}
},//商品标识
{field: 'new_price', title: __('New_price'), operate:'BETWEEN'},//新人价格
{field: 'sale_price', title: __('Sale_price'), operate:'BETWEEN'},//销售价格
{field: 'market_price', title: __('Market_price'), operate:'BETWEEN'},//市场价格
{field: 'expense_price', title: __('Expense_price'), operate:'BETWEEN'},//运费
{field: 'is_recommend', title: __('Is_recommend'),formatter: Table.api.formatter.label, searchList: {0: __('否'), 1: __('是')}},//是否推荐
{field: 'sort', title: __('Sort')},//排序
{field: 'createtime', title: __('Createtime'), operate:'RANGE', addclass:'datetimerange', formatter: Table.api.formatter.datetime},
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
... ...
... ... @@ -32,12 +32,27 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
{field: 'name', title: __('Name')},//商品名称
{field: 'name_en', title: __('Name_en')},//商品名称(英文)
{field: 'image', title: __('Image'),events: Table.api.events.image, formatter: Table.api.formatter.image},//商品图
{field: 'is_design', title: __('Is_design'),formatter: Table.api.formatter.label, searchList: {0: __('否'), 1: __('是')}},//是否设计师作品
{field: 'flag', title: __('Flag'),searchList: {0: __('普通'), 1: __('推荐'),2: __('设计师作品'), 3: __('新人特惠')},formatter:
function(value,row,index){
if (row.flag === 0)
{
return '<span style="color:green">普通</span>';
}else if (row.flag === 1)
{
return '<span style="color:red">推荐</span>';
}else if (row.flag === 2)
{
return '<span style="color:purple">设计师作品</span>';
}else if (row.flag === 3)
{
return '<span style="color:blue">新人特惠</span>';
}
}
},//商品标识
{field: 'new_price', title: __('New_price'), operate:'BETWEEN'},//新人价格
{field: 'sale_price', title: __('Sale_price'), operate:'BETWEEN'},//销售价格
{field: 'market_price', title: __('Market_price'), operate:'BETWEEN'},//市场价格
{field: 'expense_price', title: __('Expense_price'), operate:'BETWEEN'},//运费
{field: 'is_recommend', title: __('Is_recommend'),formatter: Table.api.formatter.label, searchList: {0: __('否'), 1: __('是')}},//是否推荐
{field: 'sort', title: __('Sort')},//排序
{field: 'createtime', title: __('Createtime'), operate:'RANGE', addclass:'datetimerange', formatter: Table.api.formatter.datetime},
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
... ...