浏览代码

支付盒子init

zhengwentao 3 年之前
当前提交
6bdd697911
共有 100 个文件被更改,包括 11335 次插入0 次删除
  1. 8 0
      .gitignore
  2. 1 0
      application/.htaccess
  3. 108 0
      application/ais/common.php
  4. 11 0
      application/ais/config/admin.php
  5. 30 0
      application/ais/config/auth.php
  6. 78 0
      application/ais/config/menu.php
  7. 5 0
      application/ais/config/template.php
  8. 21 0
      application/ais/config/version.php
  9. 99 0
      application/ais/controller/Adwords.php
  10. 27 0
      application/ais/controller/Bank.php
  11. 180 0
      application/ais/controller/Command.php
  12. 37 0
      application/ais/controller/Common.php
  13. 130 0
      application/ais/controller/Fund.php
  14. 190 0
      application/ais/controller/Group.php
  15. 72 0
      application/ais/controller/Order.php
  16. 80 0
      application/ais/controller/Queen.php
  17. 171 0
      application/ais/controller/Setting.php
  18. 47 0
      application/ais/controller/Test.php
  19. 47 0
      application/ais/controller/admin/City.php
  20. 35 0
      application/ais/controller/api/Base.php
  21. 146 0
      application/ais/controller/api/v1/Config.php
  22. 104 0
      application/ais/controller/api/v1/Coupon.php
  23. 127 0
      application/ais/controller/api/v1/Couponuser.php
  24. 161 0
      application/ais/controller/api/v1/Gmcard.php
  25. 122 0
      application/ais/controller/api/v1/Gmcoupon.php
  26. 225 0
      application/ais/controller/api/v1/Gmgroup.php
  27. 148 0
      application/ais/controller/api/v1/Gmstore.php
  28. 35 0
      application/ais/controller/api/v1/Group.php
  29. 29 0
      application/ais/controller/api/v1/Index.php
  30. 271 0
      application/ais/controller/api/v1/Info.php
  31. 119 0
      application/ais/controller/api/v1/Infopay.php
  32. 376 0
      application/ais/controller/api/v1/Infosend.php
  33. 324 0
      application/ais/controller/api/v1/Notify.php
  34. 81 0
      application/ais/controller/api/v1/Pay.php
  35. 40 0
      application/ais/controller/api/v1/Ranking.php
  36. 241 0
      application/ais/controller/api/v1/Shop.php
  37. 154 0
      application/ais/controller/api/v1/Shoporder.php
  38. 142 0
      application/ais/controller/api/v1/Shoppay.php
  39. 144 0
      application/ais/controller/api/v1/Store.php
  40. 208 0
      application/ais/controller/api/v1/Storepay.php
  41. 140 0
      application/ais/controller/api/v1/User.php
  42. 102 0
      application/ais/controller/api/v1/Vip.php
  43. 265 0
      application/ais/controller/coupon/Index.php
  44. 320 0
      application/ais/controller/coupon/User.php
  45. 22 0
      application/ais/controller/home/Index.php
  46. 17 0
      application/ais/controller/home/Task.php
  47. 106 0
      application/ais/controller/info/Cate.php
  48. 158 0
      application/ais/controller/info/Index.php
  49. 157 0
      application/ais/controller/info/Mp.php
  50. 119 0
      application/ais/controller/info/Order.php
  51. 115 0
      application/ais/controller/info/Tpl.php
  52. 42 0
      application/ais/controller/manage/Index.php
  53. 94 0
      application/ais/controller/shop/Cate.php
  54. 195 0
      application/ais/controller/shop/Index.php
  55. 116 0
      application/ais/controller/shop/Order.php
  56. 350 0
      application/ais/controller/store/Card.php
  57. 131 0
      application/ais/controller/store/Cate.php
  58. 95 0
      application/ais/controller/store/Chain.php
  59. 186 0
      application/ais/controller/store/Group.php
  60. 356 0
      application/ais/controller/store/Index.php
  61. 81 0
      application/ais/controller/vip/Coupon.php
  62. 125 0
      application/ais/controller/vip/Index.php
  63. 152 0
      application/ais/controller/vip/User.php
  64. 28 0
      application/ais/event/City.php
  65. 206 0
      application/ais/event/Micro.php
  66. 808 0
      application/ais/install.sql
  67. 35 0
      application/ais/model/AisAdwords.php
  68. 86 0
      application/ais/model/AisBank.php
  69. 13 0
      application/ais/model/AisBankCash.php
  70. 29 0
      application/ais/model/AisBill.php
  71. 78 0
      application/ais/model/AisCard.php
  72. 27 0
      application/ais/model/AisCardOrder.php
  73. 43 0
      application/ais/model/AisCardUser.php
  74. 38 0
      application/ais/model/AisCity.php
  75. 61 0
      application/ais/model/AisConfig.php
  76. 47 0
      application/ais/model/AisCoupon.php
  77. 23 0
      application/ais/model/AisCouponSubsidize.php
  78. 74 0
      application/ais/model/AisCouponUser.php
  79. 56 0
      application/ais/model/AisFund.php
  80. 34 0
      application/ais/model/AisFundBill.php
  81. 33 0
      application/ais/model/AisIncome.php
  82. 147 0
      application/ais/model/AisInfo.php
  83. 69 0
      application/ais/model/AisInfoCate.php
  84. 15 0
      application/ais/model/AisInfoFollow.php
  85. 45 0
      application/ais/model/AisInfoMp.php
  86. 55 0
      application/ais/model/AisInfoOrder.php
  87. 47 0
      application/ais/model/AisInfoReply.php
  88. 56 0
      application/ais/model/AisInfoShare.php
  89. 103 0
      application/ais/model/AisInfoTpl.php
  90. 265 0
      application/ais/model/AisOrder.php
  91. 76 0
      application/ais/model/AisQueen.php
  92. 220 0
      application/ais/model/AisShop.php
  93. 56 0
      application/ais/model/AisShopCate.php
  94. 14 0
      application/ais/model/AisShopCoupon.php
  95. 182 0
      application/ais/model/AisShopOrder.php
  96. 109 0
      application/ais/model/AisStore.php
  97. 33 0
      application/ais/model/AisStoreBill.php
  98. 64 0
      application/ais/model/AisStoreCate.php
  99. 18 0
      application/ais/model/AisStoreChain.php
  100. 24 0
      application/ais/model/AisStoreGroup.php

+ 8 - 0
.gitignore

@@ -0,0 +1,8 @@
+### Composer template
+composer.phar
+
+# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control
+# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
+# composer.lock
+
+.idea

+ 1 - 0
application/.htaccess

@@ -0,0 +1 @@
+deny from all

+ 108 - 0
application/ais/common.php

@@ -0,0 +1,108 @@
+<?php
+/**
+* 随机红包的金额生产
+* @param total float 总金额
+* @param num float 数量
+* @param min float 每个人最少能收到0.01元  
+* @return float 随机钱
+**/
+function pocket($total, $num, $min = 0.01){
+    for ($i=1; $i<$num; $i++) {
+        $safe_total = ($total-($num-$i)*$min)/($num-$i);
+        $money = mt_rand($min*100,$safe_total*100)/100;
+        $total = $total-$money;
+        $arr['res'][$i] = [
+            'i'     => $i,
+            'money' => $money,
+            'total' =>  $total
+        ];
+    }
+    $arr['res'][$num] = array('i'=>$num,'money'=>$total,'total'=>0);
+    return $arr['res'][rand(1,$num)]['money'];
+}
+
+/**
+* 数组转中文日期
+* @param array days [0,1,3,4,5,6,7]
+**/
+function weekdays(array $days){
+    $weekarray = array("星期日","星期一","星期二","星期三","星期四","星期五","星期六");
+    $week = [];
+    foreach ($days as $value) {
+        $week[] = $weekarray[$value];
+    }
+    return $week;
+}
+
+/**
+ * 百度地图---->腾讯地图
+ * @param double $lat 纬度
+ * @param double $lng 经度
+ * @return array();
+ */
+function bdMap_to_txMap($lat,$lng){
+    $x_pi = 3.14159265358979324 * 3000.0 / 180.0;
+    $x = $lng - 0.0065;
+    $y = $lat - 0.006;
+    $z = sqrt($x * $x + $y * $y) - 0.00002 * sin($y * $x_pi);
+    $theta = atan2($y, $x) - 0.000003 * cos($x * $x_pi);
+    $lng = $z * cos($theta);
+    $lat = $z * sin($theta);
+    return array('lng'=>$lng,'lat'=>$lat);
+}
+ 
+/**
+ * 腾讯地图---->百度地图
+ * @param double $lat 纬度
+ * @param double $lng 经度
+ */
+function txMap_to_bdMap($lat,$lng){
+    $x_pi = 3.14159265358979324 * 3000.0 / 180.0;
+    $x = $lng;
+    $y = $lat;
+    $z =sqrt($x * $x + $y * $y) + 0.00002 * sin($y * $x_pi);
+    $theta = atan2($y, $x) + 0.000003 * cos($x * $x_pi);
+    $lng = $z * cos($theta) + 0.0065;
+    $lat = $z * sin($theta) + 0.006;
+    return array('lng'=>$lng,'lat'=>$lat);
+}
+
+/**
+ * 根据经纬度算距离,返回结果单位是公里,先纬度,后经度
+ * @param $lat1
+ * @param $lng1
+ * @param $lat2
+ * @param $lng2
+ * @return float|int
+ */
+function getDistance($lng1,$lat1,$lng2,$lat2){
+    $earthRadius = 6367000;
+    $lat1 = deg2rad($lat1);
+    $lng1 = deg2rad($lng1);
+    $lat2 = deg2rad($lat2);
+    $lng2 = deg2rad($lng2);
+    $calcLongitude = $lng2 - $lng1; 
+    $calcLatitude = $lat2 - $lat1; 
+    $stepOne = pow(sin($calcLatitude / 2), 2) + cos($lat1) * cos($lat2) * pow(sin($calcLongitude / 2), 2); 
+    $stepTwo = 2 * asin(min(1, sqrt($stepOne))); 
+    $calculatedDistance = $earthRadius * $stepTwo; 
+    $distance = round($calculatedDistance); 
+    if($distance <= 500){
+        return $distance.'m';
+    }else{
+        return round($distance/1000,1).'km';
+    }
+}
+
+/**
+ * @description:根据数据 
+ * @param {dataArr:需要分组的数据;keyStr:分组依据} 
+ * @return: 
+ */
+function dataGroup(array $dataArr,string $keyStr){
+    $newArr = [];
+    foreach ($dataArr as $val) { 
+        $newArr[$val[$keyStr]][] = $val;
+    }
+    return $newArr;
+}

+ 11 - 0
application/ais/config/admin.php

@@ -0,0 +1,11 @@
+<?php
+return [
+    [
+        'name' => '系统设置',
+        'icon' => 'setup_icon',
+        'menu' => [
+            ['name' => '城市列表','url' => url('ais/admin.city/index')],
+        ]
+    ]
+];
+

+ 30 - 0
application/ais/config/auth.php

@@ -0,0 +1,30 @@
+<?php
+/**
+ * 帐号权限配置
+ * 本配置仅针对集成common/controller/Manage.php有效
+ * 'auth' => 1, //权限值(多个数组必须唯一)
+ * 'name' => '权限名称一', //权限名称
+ * 'group' => ['控制器名称' => ['name' => '权限名称|可不设置','action' => ['方法','方法']]]   //如果控制器中 action 值为空,那控制器中所有方法都有权限
+ * 
+return [
+    [
+        'auth' => 1,
+        'name' => '权限组名称1',
+        'group' => [
+            '控制器1' => ['name' => '权限名称1','action' => ['方法','方法','方法']],
+            '控制器2' => ['name' => '权限名称2','action' => ['方法','方法','方法']],
+        ]
+    ], 
+    [
+        'auth' => 2,
+        'name' => '权限组名称2',
+        'group' => [
+            '控制器1' => ['name' => '权限名称1','action' => ['方法','方法','方法']],
+            '控制器2' => ['name' => '权限名称2','action' => ['方法','方法','方法']],
+        ]
+    ], 
+];
+ */
+return [
+   
+];

+ 78 - 0
application/ais/config/menu.php

@@ -0,0 +1,78 @@
+<?php
+return [
+    [
+        'name' => '商家管理',
+        'icon' => 'store_icon',
+        'menu' => [
+            ['name' => '商家列表','url' => url('ais/store.index/index')],
+            ['name' => '行业管理','url' => url('ais/store.cate/index')],
+            ['name' => '商圏列表','url' => url('ais/store.group/index')],
+        ]
+    ],
+    [
+        'name' => '运营管理',
+        'icon' => 'cuxiaohuodong',
+        'menu' => [
+            ['name' => '优惠券','url' => url('ais/coupon.index/index')],
+            ['name' => '商家储值','url' => url('ais/store.card/index')],
+        ]
+    ],
+    [
+        'name' => '优选商城',
+        'icon' => 'discount',
+        'menu' => [
+            ['name' => '商品列表','url' => url('ais/shop.index/index')],
+            ['name' => '优选专题','url' => url('ais/shop.cate/index')],
+            ['name' => '订单管理','url' => url('ais/shop.order/index')],
+        ]
+    ],
+    [
+        'name' => '城市号',
+        'icon' => 'calendar_icon',
+        'menu' => [
+            ['name' => '信息列表','url' => url('ais/info.index/index')],
+            ['name' => '订单列表','url' => url('ais/info.order/index')],
+            ['name' => '城市号列表','url' => url('ais/info.mp/index'),],
+            ['name' => '横幅广告','url' => url('ais/adwords/index',['group'=>'info'])],
+            ['name' => '主题模板','url' => url('ais/info.cate/index')], 
+        ]
+    ],
+    [
+        'name' => '会员管理',
+        'icon' => 'viphuiyuan',
+        'menu' => [
+            ['name' => '会员列表','url' => url('ais/vip.user/index')],
+            ['name' => '已领优惠','url' => url('ais/coupon.user/user')],
+            ['name' => '储值用户','url' => url('ais/store.card/user')]
+
+        ]
+    ],
+    [
+        'name' => '财务管理',
+        'icon' => 'chuzhijine',
+        'menu' => [
+            ['name' => '采购基金','url' => url('ais/fund/index')],
+            ['name' => '付款买单','url' => url('ais/order/index')],
+            ['name' => '分账队列','url' => url('ais/queen/index')],
+        ]
+    ],
+    [
+        'name' => '广告与图标',
+        'icon' => 'classify_icon',
+        'menu' => [
+            ['name' => '首页滑动','url' => url('ais/adwords/index',['group'=>'index'])],
+            ['name' => '首页导航','url' => url('ais/adwords/index',['group'=>'icon'])],
+            ['name' => '会员特权','url' => url('ais/adwords/index',['group'=>'vip'])],
+            ['name' => '会员服务','url' => url('ais/adwords/index',['group'=>'user'])],
+        ]
+    ],
+    [
+        'name' => '系统设置',
+        'icon' => 'setup_icon',
+        'menu' => [
+            ['name' => '会员等级','url' => url('ais/vip.index/index')],
+			['name' => '系统配置','url' => url('ais/setting/config')]
+        ]
+    ]
+];
+

+ 5 - 0
application/ais/config/template.php

@@ -0,0 +1,5 @@
+<?php
+return  [
+    'layout_on'     =>  true,
+    'layout_name'   =>  'layout',
+];

+ 21 - 0
application/ais/config/version.php

@@ -0,0 +1,21 @@
+<?php
+/**
+ * types 应用类型 参数:mp、mp_program_app、mp_program、app、program
+ * is_openapp 开发平台应用  0、1
+ * is_manage  启用总平台管理  0、1
+ * version    应用版本好  0、1
+ * is_wechat_pay 微信支付  0、1
+ * is_alipay_pay 支付宝支付  0、1
+ * name 应用名称
+ * describe 应用描述
+ */
+return [
+    'types'         => 'mp_program',  //mp、mp_program_app、mp_program、app、program
+    'version'       => '1.0.0',
+    'name'          => '享店联盟',
+    'describe'      => "享店联盟是一款以商带商商商互通、以商养商商商互利、以客带商商客互惠、以商养客人人创业的促进成绩量和客单价的商盟系统。",
+    'is_openapp'    => 0,
+    'is_manage'     => 1,
+    'is_wechat_pay' => 1,
+    'is_alipay_pay' => 0
+];

+ 99 - 0
application/ais/controller/Adwords.php

@@ -0,0 +1,99 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 应用扩展
+ */
+namespace app\ais\controller;
+use app\ais\model\AisAdwords;
+use app\common\facade\WechatProgram;
+use think\facade\Request;
+
+class Adwords extends Common{
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps', [['name'=>'广告管理','url'=>'javascript:;']]);
+    }
+
+    /**
+     * 列表
+     */
+    public function index($group){
+        $condition          = [];
+        $condition['group'] = $group;
+        $condition['member_miniapp_id'] = $this->member_miniapp_id;
+        $view['lists'] = AisAdwords::where($condition)->order('sort desc,id desc')->paginate(20);
+        $view['pathMaps']   = [['name'=>'广告管理','url'=>url("adwords/index",['group' => $group])]];
+        $view['group'] = $group;
+        return view('index',$view);
+    }
+  
+    //编辑
+    public function edit(){
+        if(request()->isAjax()){
+            $data = [
+                'id'                => Request::param('id/d',0),
+                'group'             => Request::param('group/s'),
+                'open_type'         => Request::param('open_type/s','','htmlspecialchars'),
+                'title'             => Request::param('title/s'),
+                'link'              => Request::param('link/s'),
+                'picture'           => Request::param('picture/s'),
+                'member_miniapp_id' => $this->member_miniapp_id,
+            ];
+            $validate = $this->validate($data,'adwords.edit');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $result =  AisAdwords::edit($data);
+            if($result){
+                return json(['code'=>200,'url'=>url('adwords/index',['group' => $data['group']]),'msg'=>'操作成功']);
+            }else{
+                return json(['code'=>0,'msg'=>'操作失败']);
+            }
+        }else{
+            $view['info']  = AisAdwords::where($this->mini_program)->where(['id' => Request::param('id/d', 0)])->find();
+            if($this->member_miniapp->miniapp->is_openapp == 0){
+                $list = WechatProgram::isTypes($this->member_miniapp_id)->code->getPage();
+            }else{
+                $list = ['errcode' => 1];
+            }
+            $view['list']   = $list;
+            $view['group'] = Request::param('group');
+            return view()->assign($view);
+        }
+    }
+
+    //删除
+    public function delete(int $id){
+        $result = AisAdwords::where($this->mini_program)->where(['id' => $id])->delete();
+        if($result){
+            return enjson(200);
+        }else{
+            return enjson(0,'删除失败');
+        } 
+    }
+    
+    /**
+     * 排序
+     */
+    public function sort(){
+        if(request()->isAjax()){
+            $data = [
+                'sort' => $this->request->param('sort/d'),
+                'id'   => $this->request->param('id/d'),
+            ];
+            $validate = $this->validate($data,'Category.sort');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $result = AisAdwords::update(['sort'=>$data['sort']],['member_miniapp_id' => $this->member_miniapp_id,'id' =>$data['id']]);
+            if($result){
+                return enjson(200);
+            }else{
+                return enjson(0);
+            } 
+        }
+    }
+}

+ 27 - 0
application/ais/controller/Bank.php

@@ -0,0 +1,27 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 客户收益管理
+ */
+namespace app\ais\controller;
+use app\ais\model\AisBill;
+
+class Bank extends Common{
+
+
+    public function initialize(){
+        parent::initialize();
+        $this->assign('pathMaps', [['name'=>'账号管理','url'=>url("bank/bill")]]);
+    }
+
+    /**
+     * 客户收益记录
+     * @return void
+     */
+    public function bill(int $uid){
+        $view['list']     = AisBill::where(['uid' => $uid])->order('id desc')->paginate(15,false,['query'=>['uid' =>$uid]]);
+        return view()->assign($view);
+    } 
+}

+ 180 - 0
application/ais/controller/Command.php

@@ -0,0 +1,180 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 定时任务与命令目录
+ */
+namespace app\ais\controller;
+use think\Controller;
+use app\ais\model\MchId;
+use app\ais\model\MchIdQueen;
+use app\ais\model\MchIdUser;
+use app\ais\model\Coupon;
+use app\ais\model\CouponUser;
+use app\ais\widget\Inform;
+use app\common\facade\WechatPay;
+
+use think\helper\Time;
+
+class Command extends Controller {
+
+    /**
+     * 微信优惠券定时检测
+     */  
+    public function coupon(){
+        //定时检测用户优惠券状态
+        $couponuser = CouponUser::where('user_size','<=',0)->whereOr('endtime','<=',Time::today()[0])->update(['is_end' => 1]);
+        //定时检测商家优惠券状态
+        $coupon     = Coupon::whereOr('endtime','<=',Time::today()[0])->update(['is_end' => 1]);
+        if($coupon || $couponuser){
+            return 'SUCCESS';
+        }else{
+            return 'FINISH';
+        }
+    }
+
+    /**
+     * 微信分账定时任务
+     */   
+    public function queen(){
+        $queen = MchidQueen::where(['is_finish' => 0])->order('id asc')->find();
+        if(empty($queen)){
+            return 'ALL';
+        }
+        $transaction_id    = $queen->transaction_id;
+        $member_miniapp_id = $queen->member_miniapp_id;
+        //读取配置并判断商户模式
+        $setting = model('AisConfig')->getConfig($member_miniapp_id);
+        $sub_mchid = NULL;
+        if($setting->is_psp){
+            if($queen->store->mch_id){
+                $mchid = model('MchId')->getMch($queen->store['mch_id']);
+            }else{
+                $mchid = model('MchId')->getMch(0,$member_miniapp_id);
+            }
+            if(empty($mchid)){
+                return 'FAIL';
+            }
+            $sub_mchid = $mchid->mchid;
+        }
+        $doPay = WechatPay::doPay($member_miniapp_id,false,$sub_mchid);
+        //如果金额小于直接结束当前分账
+        if($queen->amount <= 0){
+            $params['transaction_id'] = $transaction_id;
+            $params['out_order_no']   = $queen->out_order_no;
+            $params['description']    = '分账已完成';
+            $markOrder = $doPay->profit_sharing->markOrderAsFinished($params);
+            if($markOrder['return_code'] == 'SUCCESS' && $markOrder['result_code'] == 'SUCCESS'){
+                $queen->is_finish = 2;
+                $queen->order_id  = $queen->out_order_no;
+                $queen->sms       = '成功';
+                $queen->save();
+            }
+            return 'FAIL';
+        }
+        //读取分账接收方
+        $where['member_miniapp_id'] = $member_miniapp_id;
+        $where['store_id']          = $queen->store->id;
+        if($queen->types == 1){
+            $where['mch_id'] = $queen->mch_id;
+        }else{
+            $where['uid'] = $queen->uid;
+        }
+        $queen_user = MchIdUser::where($where)->find();
+        $data      = [];
+        $receivers = [];
+        if(empty($queen_user)){
+            $data['member_miniapp_id']   = $queen->member_miniapp_id;
+            $data['store_id']            = $queen->store->id;
+            if($queen->types == 1){
+                $mch  = MchId::getMch($queen->mch_id);
+                $data['mch_id']                    = $queen->mch_id;
+                $data['openid']                    = $mch->mchid;
+                $data['receiver']['type']          = 'MERCHANT_ID';
+                $data['receiver']['account']       = (string)$mch->mchid;
+                $data['receiver']['name']          = $mch->store_name;
+                $data['receiver']['relation_type'] = 'STORE_OWNER';
+            }else{
+                $data['uid']                       = $queen->uid;
+                $data['openid']                    = $queen->user['miniapp_uid'];
+                $data['receiver']['type']          = $setting->is_psp ? 'PERSONAL_SUB_OPENID': 'PERSONAL_OPENID';
+                $data['receiver']['account']       = (string)$queen->user['miniapp_uid'];
+                $data['receiver']['relation_type'] = 'USER';
+            }
+            if($queen->types == 1 && $setting->is_psp){
+                if($mchid->mchid == $mch->mchid){
+                    $receivers = $data['receiver'];
+                    $data['receiver'] = json_encode($receivers);
+                    MchIdUser::insert($data);
+                    $data['receiver'] = [];
+                }
+            }
+            if(!empty($data['receiver'])){
+                $rel = $doPay->profit_sharing->addReceiver($data['receiver']);
+                if($rel['return_code'] == 'SUCCESS' && $rel['result_code'] == 'SUCCESS'){
+                    $data['receiver'] = $rel['receiver'];
+                    MchIdUser::insert($data);
+                    $receivers = json_decode($rel['receiver'],true);
+                }else{
+                    $queen->is_finish = 1;
+                    $queen->sms       = empty($rel['return_msg']) ? $rel['err_code_des'] : $rel['return_msg'];
+                    $queen->save();
+                    return 'FAIL';
+                }
+            }
+        }else{
+            $receivers = json_decode($queen_user->receiver,true);
+        }
+        if(empty($receivers)){
+            return 'FAIL';
+        }
+        //读取上次分账单号
+        $order_no = MchidQueen::where(['member_miniapp_id' => $member_miniapp_id,'transaction_id' => $transaction_id,'is_finish' => 2])->order('id desc')->find();
+        $out_order_no = empty($order_no) ? $queen->out_order_no : $order_no->order_id;  //分账订单号
+        //开始分账
+        $receivers['amount']      = $queen->amount;
+        $receivers['description'] = $queen->msg;
+        $order[] = $receivers;
+        $payrel = $doPay->profit_sharing->multiShare($transaction_id,$out_order_no,$order);
+        if($payrel['return_code'] == 'SUCCESS'){
+            if($payrel['result_code'] == 'SUCCESS'){
+                $out_order_no =  $payrel['order_id'];
+                $queen->is_finish = 2;
+                $queen->order_id  = $out_order_no;
+                $queen->sms       = '成功';
+            }else{
+                if($payrel['err_code'] == 'FREQUENCY_LIMITED' || $payrel['err_code'] == 'ORDER_NOT_READY'){
+                    $queen->is_finish = 0;
+                }else{
+                    $queen->is_finish = 1;
+                }
+                $queen->sms = $payrel['err_code_des'];
+            }
+        }else{
+            $queen->is_finish = 1;
+            $queen->sms     = $payrel['return_msg'];
+        }
+        $sms = $queen->sms;
+        $queen->update_time  =  time();
+        $queen->save();
+        //查询并结束分账
+        $is_end = MchidQueen::where(['member_miniapp_id' => $member_miniapp_id,'transaction_id' => $transaction_id,'is_finish' => 0])->count();
+        if($is_end <= 0){
+            $params['transaction_id'] = $transaction_id;
+            $params['out_order_no']   = $out_order_no;
+            $params['description']    = '分账已完成';
+            $doPay->profit_sharing->markOrderAsFinished($params);
+            return 'END';
+        }
+        return $sms;
+    }
+
+    /**
+     * 微信定时模板消息
+     */   
+    public function inform(){
+        $rel = Inform::smsQueue();
+        return $rel ? 'SUCCESS' : 'FAIL';
+    }
+}

+ 37 - 0
application/ais/controller/Common.php

@@ -0,0 +1,37 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 用户公共调用模块
+ */
+namespace app\ais\controller;
+use app\common\controller\Manage;
+use app\ais\model\MemberUser;
+use app\ais\event\City;
+class Common extends Manage{
+
+    public $mini_program   = []; 
+
+    /**
+     * 初始化当前应用管理员是不是联盟城市账户
+     * @return void
+     */
+    public function initialize() {
+        parent::initialize();
+        $this->view->engine->layout('layout');
+        $this->mini_program = ['member_miniapp_id' => $this->member_miniapp_id];
+    }
+
+   /**
+     * 查看城市编码
+     * @param integer $id 用户ID
+     */
+    public function cityCode(){
+        $city = City::read();
+        if($city){
+            return enjson(200,'成功',$city);
+        }
+        return enjson(0);
+    }
+}

+ 130 - 0
application/ais/controller/Fund.php

@@ -0,0 +1,130 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 采购基金
+ */
+namespace app\ais\controller;
+use app\ais\model\AisFund;
+use app\ais\model\AisFundBill;
+use app\ais\model\AisCouponSubsidize;
+use app\ais\model\AisCoupon;
+use app\ais\model\AisOrder;
+use filter\Filter;
+
+class Fund extends Common{
+
+    public $mini_program   = []; 
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps',[['name'=>'采购基金','url'=>url("fund/index")]]);
+    }
+
+    /**
+     * 采购基金
+     * @return void
+     */
+    public function index(int $types = 0){
+        $fund = AisFund::where($this->mini_program)->find();
+        $counts = [];
+        if(empty($fund)){
+            $counts['balance']       = 0;
+            $counts['subsidize']     = 0;
+            $counts['subsidize_num'] = 0;
+        }else{
+            $counts['balance'] = $fund->balance;
+            $counts['subsidize'] = $fund->subsidize;
+            $counts['subsidize_num'] = $fund->subsidize_num;
+        }
+        $view['fund']  = $counts;
+        if($types <= 1){
+            $view['bill']  = AisFundBill::where($this->mini_program)->where(['types' => $types])->order('id desc')->paginate(10,false,['query'=>['types' => $types]]);
+        }else{
+
+            $view['bill']  = AisCouponSubsidize::with('coupon')->where($this->mini_program)->order('id desc')->paginate(10,false,['query'=>['types' => $types]]);
+        }
+        $view['types'] = $types;
+        return view()->assign($view);
+    }
+
+    /**
+     * 删除关联
+     * @return void
+     */
+    public function delAisCoupon(int $id){
+        $result = AisCouponSubsidize::where($this->mini_program)->where(['id' => $id])->delete();
+        if($result){
+            return json(['code'=>200,'msg'=>'操作成功']);
+        }else{
+            return json(['code'=>403,'msg'=>'删除失败']);
+        }
+    }  
+    
+    /**
+     * 关联优惠券
+     * @return void
+     */
+    public function winCoupon(){
+        if(request()->isAjax()){
+            $ids = input('post.ids/s');
+            if(empty($ids)){
+                return json(['code'=>0,'msg'=>'请选择要关联的优惠券']);
+            }
+            $ida = ids($ids,true);
+            $data = [];
+            foreach ($ida as $key => $value) {
+                $data[$key]['member_miniapp_id'] = $this->member_miniapp_id;
+                $data[$key]['coupon_id']         = $value;
+                $data[$key]['how_much']          = 0;
+            }
+            $result = AisCouponSubsidize::insertAll($data);
+            if($result){
+                return json(['code'=>302,'msg'=>'关联补贴优惠券成功','data' =>[]]);
+            }else{
+                return json(['code'=>0,'msg'=>'关联补贴优惠券失败']);
+            }
+        }else{
+            $coupon = AisCouponSubsidize::where($this->mini_program)->field('coupon_id')->select()->toArray();
+            $coupon_ids  = [];
+            if(!empty($coupon)){
+                $coupon_ids = array_column($coupon,'coupon_id');
+            }
+            $view['lists']  = AisCoupon::where($this->mini_program)->whereNotIn('id',$coupon_ids)->order('id desc')->paginate(10);
+            return view()->assign($view);
+        }
+    } 
+    
+    /**
+     * 排序
+     */
+    public function howmuch(){
+        if(request()->isAjax()){
+            $data = [
+                'sort' => input('post.sort/f'),
+                'id'   => input('post.id/d'),
+            ];
+            $result = AisCouponSubsidize::where($this->mini_program)->where(['id' =>$data['id']])->update(['how_much' => $data['sort']]);
+            if($result){
+                return json(['code'=>200,'msg'=>'操作成功']);
+            }else{
+                return json(['code'=>0,'msg'=>'操作失败']);
+            }
+        }
+    }
+
+
+    /**
+     * 重置分账队列
+     * @return void
+     */
+    public function reset(string $order_no){
+        $result = AisOrder::where(['state' => 1,'order_no' => Filter::filter_escape(substr($order_no, 0, -2))])->find();
+        if($result && AisOrder::subsidy($result)){
+            return enjson(200);
+        }else{
+            return enjson(0);
+        }
+    }
+}

+ 190 - 0
application/ais/controller/Group.php

@@ -0,0 +1,190 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 行业分类
+ */
+namespace app\ais\controller;
+use app\ais\model\AisConfig;
+use app\ais\model\AisOrder;
+use app\ais\model\AisStoreGroup;
+use app\ais\model\AisStore;
+use app\ais\model\AisStoreUnion;
+use think\Db;
+use think\facade\Request;
+use think\helper\Time;
+
+class Group extends Common{
+
+    /**
+     * 列表
+     */
+    public function index(){
+        $view['lists']    = AisStoreGroup::where(['member_miniapp_id' => $this->member_miniapp_id])->order('id desc')->paginate(20);
+        $view['pathMaps'] = [['name'=>'商圏管理','url'=> url("group/index")]];
+        return $this->fetch()->assign($view);
+    }
+
+    /**
+     * 已绑定商圏列表
+     */
+    public function storeIndex(int $id){
+        $view['quan_id']  = $id;
+        $view['lists']    = AisStore::where($this->mini_program)->whereIn('id',AisStoreUnion::where($this->mini_program)->where(['group_id' => $id])->column('store_id'))->order('id desc')->paginate(20);
+        $view['pathMaps'] = [['name'=>'商圏管理','url'=> url("group/index")],['name'=>'商圈商户','url'=> url("group/storeindex",['id' => $id])]];
+        return $this->fetch()->assign($view);
+    }
+
+    /**
+     * 商圏列表
+     */
+    public function select(int $quan_id){
+        $condition   = [];
+        $condition[] = ['member_miniapp_id', '=', $this->member_miniapp_id];
+        if(request()->isAjax()){
+            $ids     = $this->request->param('ids');
+            if(empty($ids)){
+                return json(['code'=>0,'msg'=>'请选择要入住商圏的好店']);
+            }
+            $list = AisStore::where($condition)->whereIn('id',$ids)->whereNotIn('id',AisStoreUnion::where($this->mini_program)->where(['group_id'=>$quan_id,'type' => 0])->whereIn('store_id',$ids)->column('store_id'))->select();
+            foreach ($list as $info){
+                $config = AisConfig::getConfig($this->member_miniapp_id);
+                $member = AisStoreUnion::where(['member_miniapp_id' => $this->member_miniapp_id,'group_id' => $quan_id,'type' => 0])->select();
+                if(!empty($config->group_member) && count($member) >=$config->group_member){
+                    return enjson(403,'商圈只能有'.$config->group_member.'个成员');
+                }
+                $size = AisStoreUnion::where(['member_miniapp_id' => $this->member_miniapp_id,'store_id' => $info->id,'type' => 0])->select();
+                if(!empty($config->group_join) && count($size) >=$config->group_join){
+                    return enjson(403,'只能加入'.$config->group_join.'个商圈');
+                }
+                $union = AisStoreUnion::where(['member_miniapp_id'=>$this->member_miniapp_id,'store_id' => $info->id,'group_id' => $quan_id,'type' => 1])->find();
+                if($union){
+                    $union->delete();
+                }
+                AisStoreUnion::create(['member_miniapp_id'=>$this->member_miniapp_id,'store_id' => $info->id,'group_id' => $quan_id,'type' => 0,'create_time' => time(),'update_time' => time()]);
+            }
+            return json(['code'=>200,'msg'=>'好店入住商圏成功','data' =>[]]);
+        }else{
+            $keyword  = $this->request->param('keyword');
+            if(!empty($keyword)) {
+                $condition[] = ['name', 'like', '%' . $keyword . '%'];
+            }
+            $view['lists']   = AisStore::where($condition)->whereNotIn('id',AisStoreUnion::where($this->mini_program)->where(['group_id'=>$quan_id,'type' => 0])->column('store_id'))->order('id desc')->paginate(20);
+            $view['keyword'] = $keyword;
+            $view['quan_id'] = $quan_id;
+            return $this->fetch()->assign($view);
+        }
+    }
+
+    //编辑
+    public function edit(){
+        if(request()->isAjax()){
+            $param = [
+                'id'      => $this->request->param('id/d', 0),
+                'title'   => $this->request->param('title/s'),
+                'content' => $this->request->param('content/s'),
+                'uid'     => $this->request->param('uid/d'),
+            ];
+            $validate = $this->validate($param,'Group.edit');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $result =  AisStoreGroup::where(['member_miniapp_id' => $this->member_miniapp_id,'id' =>  $param['id']])->find();
+            if($result){
+                $result->title   = $param['title'];
+                $result->content = $param['content'];
+                $result->uid     = $param['uid'];
+                $result->save();
+            }else{
+                $info =  AisStoreGroup::where(['member_miniapp_id' => $this->member_miniapp_id,'uid' =>  $param['uid']])->find();
+                if($info){
+                    return json(['code'=>403,'msg'=>'只能管理一个商圈']);
+                }
+                $param['member_miniapp_id'] = $this->member_miniapp_id;
+                AisStoreGroup::create($param);
+            }
+            return json(['code'=>200,'url'=>url('group/index'),'msg'=>'操作成功']);
+        }else{
+            $view['info']= AisStoreGroup::where(['id' => $this->request->param('id/d',0),'member_miniapp_id' => $this->member_miniapp_id])->find();
+            return $this->fetch()->assign($view);
+        }
+    }
+
+    //删除商圈
+    public function delete(int $id){
+        $store = AisStoreGroup::where(['member_miniapp_id' => $this->member_miniapp_id])->whereIn('id',AisStoreUnion::where($this->mini_program)->where(['group_id' => $id,'type' => 0])->column('group_id'))->find();
+        if($store){
+            return json(['code'=>403,'msg'=>'删除失败,商圏中还包含店铺']);
+        }
+        $result = AisStoreGroup::destroy($id);
+        if($result){
+            return json(['code'=>200,'msg'=>'操作成功']);
+        }else{
+            return json(['code'=>403,'msg'=>'删除失败']);
+        } 
+    }
+
+    //从商圏中删除好店
+    public function deleteStore(int $id,$quan_id){
+        $result = AisStoreUnion::destroy(['store_id' => $id,'group_id' => $quan_id]);
+        if($result){
+            return json(['code'=>200,'msg'=>'操作成功']);
+        }
+        return json(['code'=>403,'msg'=>'删除失败']);
+    }
+
+    /**
+     * 商圏用户订单
+     * @access public
+     */
+    public function order(int $state = 1,int $group_id){
+        $condition   = [];
+        $condition[] = ['member_miniapp_id', '=', $this->member_miniapp_id];
+        $condition[] = ['group_id', '=', $group_id];
+        $store_id    = Request::param('store_id/d', '');
+        $store_name  = Request::param('store_name');
+        if ($store_id) {
+            $condition[] = ['store_id', '=', $store_id];
+        }
+        $time = Request::param('time/d',0);
+        if($time){
+            switch ($time) {
+                case 2:
+                    list($start, $end) = Time::yesterday();
+                    break;
+                case 30:
+                    list($start, $end) = Time::month();
+                    break;
+                case 60:
+                    list($start, $end) = Time::lastMonth();
+                    break;
+                default:
+                    list($start, $end) = Time::today();
+                    break;
+            }
+            $condition[] = ['paid_time','>=',$start];
+            $condition[] = ['paid_time','<=',$end];
+        }
+        $starttime = Request::param('starttime/s');
+        $endtime   = Request::param('endtime/s');
+        if($starttime){
+            $condition[] = ['paid_time','>=',strtotime($starttime)];
+        }
+        if($endtime){
+            $condition[] = ['paid_time','<=',strtotime($endtime)];
+        }
+        $view['orders']          = AisOrder::where(['state' => $state ? 1 : 0])->whereIn('store_id',AisStoreUnion::where($condition)->column('store_id'))->order('id desc')->paginate(20, false, ['query' => ['store_id' => $store_id, 'store_name' => $store_name, 'time' => $time, 'starttime' => $starttime, 'endtime' => $endtime, 'group_id' => $group_id]]);
+        $view['order_num']       = AisOrder::where(['state' => 1])->whereIn('store_id',AisStoreUnion::where($condition)->column('store_id'))->count();
+        $view['user_amount']     = AisOrder::where(['state' => 1])->whereIn('store_id',AisStoreUnion::where($condition)->column('store_id'))->sum('amount');
+        $view['order_amount']    = AisOrder::where(['state' => 1])->whereIn('store_id',AisStoreUnion::where($condition)->column('store_id'))->sum('price');
+        $view['coupon_price']    = money($view['user_amount'] - $view['order_amount']);
+        $view['time']            = $time;
+        $view['starttime']       = $starttime;
+        $view['endtime']         = $endtime;
+        $view['store_id']        = $store_id;
+        $view['group_id']        = $group_id;
+        $view['store_name']      = $store_name;
+        return view()->assign($view);
+    }
+}

+ 72 - 0
application/ais/controller/Order.php

@@ -0,0 +1,72 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 订单管理
+ */
+namespace app\ais\controller;
+use app\ais\controller\Common;
+use app\ais\model\AisOrder;
+use think\facade\Request;
+use think\helper\Time;
+
+class Order extends Common{
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps', [['name'=>'买单帐单','url'=>url("order/index")]]);
+    }
+
+    /**
+     * 用户订单
+     * @access public
+     */
+    public function Index(int $state = 1){
+        $condition   = [];
+        $condition[] = ['member_miniapp_id', '=', $this->member_miniapp_id];
+        $store_id    = Request::param('store_id/d', '');
+        $store_name  = Request::param('store_name');
+        if ($store_id) {
+            $condition[] = ['store_id', '=', $store_id];
+        }
+        $time = Request::param('time/d',0);
+        if($time){
+            switch ($time) {
+                case 2:
+                    list($start, $end) = Time::yesterday();
+                    break;
+                case 30:
+                    list($start, $end) = Time::month();
+                    break;
+                case 60:
+                    list($start, $end) = Time::lastMonth();
+                    break;
+                default:
+                    list($start, $end) = Time::today();
+                    break;
+            }
+            $condition[] = ['paid_time','>=',$start];
+            $condition[] = ['paid_time','<=',$end];
+        }
+        $starttime = Request::param('starttime/s');
+        $endtime   = Request::param('endtime/s');
+        if($starttime){
+            $condition[] = ['paid_time','>=',strtotime($starttime)];
+        }
+        if($endtime){
+            $condition[] = ['paid_time','<=',strtotime($endtime)];
+        }
+        $view['orders']          = AisOrder::where($condition)->where(['state' => $state ? 1 : 0])->order('id desc')->paginate(20, false, ['query' => ['store_id' => $store_id, 'store_name' => $store_name, 'time' => $time, 'starttime' => $starttime, 'endtime' => $endtime]]);
+        $view['order_num']       = AisOrder::where($condition)->where(['state' => 1])->count();
+        $view['user_amount']     = AisOrder::where($condition)->where(['state' => 1])->sum('amount');
+        $view['order_amount']    = AisOrder::where($condition)->where(['state' => 1])->sum('price');
+        $view['coupon_price']    = money($view['user_amount'] - $view['order_amount']);
+        $view['time']            = $time;
+        $view['starttime']       = $starttime;
+        $view['endtime']         = $endtime;
+        $view['store_id']        = $store_id;
+        $view['store_name']      = $store_name;
+        return view()->assign($view);
+    }    
+}

+ 80 - 0
application/ais/controller/Queen.php

@@ -0,0 +1,80 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 商店管理
+ */
+namespace app\ais\controller;
+use app\ais\model\AisQueen;
+use app\ais\controller\Common;
+use filter\Filter;
+use think\facade\Request;
+
+class Queen extends Common{
+
+    public function initialize(){
+        parent::initialize();
+        $this->assign('pathMaps',[['name'=>'分帐列表','url'=>url("ais/queen/index")]]);
+    }
+
+    /**
+     * 微信分账队列
+     * @return void
+     */
+    public function index(int $types = 0,string $order = ''){
+        $condition = [];
+        if(!empty($order)){
+            $condition['out_order_no'] = Filter::filter_escape(trim($order));
+        }
+        $store_id  = Request::param('store_id',0);
+        $store_name  = Request::param('store_name');
+        if($store_id){
+            $condition['store_id'] = $store_id;
+        }
+        $view['amount_quree']   = AisQueen::where($this->mini_program)->where($condition)->where(['is_finish' => 0])->sum('amount');
+        $view['amount_success'] = AisQueen::where($this->mini_program)->where($condition)->where(['is_finish' => 2])->sum('amount');
+        $view['amount_fail']    = AisQueen::where($this->mini_program)->where($condition)->where(['is_finish' => 1])->sum('amount');
+        if($types){
+            switch ($types) {
+                case 2:
+                    $is_finish = 2;
+                    break;
+                case 3:
+                    $is_finish = 1;
+                    break;
+                default:
+                    $is_finish = 0;
+                    break;
+            }
+            $condition['is_finish'] = $is_finish;
+        }
+        $orderby = $types == 1 ? 'id asc':'id desc';
+        $view['lists'] = AisQueen::where($this->mini_program)->where($condition)->order($orderby)->paginate(10,false,[
+            'query' => ['types' => $types,'store_id' => $store_id,'store_name' => $store_name],
+        ]);
+        $view['types'] = $types;
+        $view['order'] = $order;
+        $view['store_id']   = $store_id;
+        $view['store_name'] = $store_name;
+        $view['pathMaps'] = [['name'=>'结算队列','url'=>url("store/queen")]];
+        return view()->assign($view);
+    }
+
+
+    /**
+     * 重置分账队列
+     * @return void
+     */
+    public function resetQueen(string $order){
+        $condition = [];
+        $condition['out_order_no'] = Filter::filter_escape(trim($order));
+        $condition['is_finish']    = 1;
+        $rueen = AisQueen::where($this->mini_program)->where($condition)->update(['is_finish' => 0]);
+        if($rueen){
+            return json(['code'=>200,'message'=>'成功']);
+        }else{
+            return json(['code'=>0,'message'=>'失败,只有分账失败的才允许重置队列']);
+        }
+    }
+}

+ 171 - 0
application/ais/controller/Setting.php

@@ -0,0 +1,171 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 应用配置
+ */
+namespace app\ais\controller;
+use app\ais\model\AisConfig;
+
+class Setting extends Common{
+
+    /**
+     *  应用配置
+     * @return void
+     */
+    public function config(){
+        if(request()->isAjax()){
+            $data = [
+                'service_telephone'  => $this->request->param('service_telephone/s'),
+                'city_only_price'    => $this->request->param('city_only_price/f', 0),
+                'city_sharing_price' => $this->request->param('city_sharing_price/f', 0),
+                'coupon_is_pay_open' => $this->request->param('coupon_is_pay_open/d', 0),
+                'coupon_longtime'    => $this->request->param('coupon_longtime/d', 0),
+                'group_join'         => $this->request->param('group_join/d', 0),
+                'group_member'       => $this->request->param('group_member/d', 0),
+                'group_profit'       => $this->request->param('group_profit/d', 0),
+                'mchid'              => $this->request->param('mchid/d',0),
+                'charge'             => $this->request->param('charge/d',0),
+            ];
+            $validate = $this->validate($data,'Config.save');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $result =  AisConfig::configs($data,$this->member_miniapp_id);
+            if($result){
+                return json(['code'=>200,'data' => ['url' => url('setting/config')],'msg'=>'操作成功']);
+            }else{
+                return json(['code'=>0,'msg'=>'操作失败']);
+            }
+        }else{
+            $view['pathMaps'] = [['name' =>' 系统配置','url' => url("setting/config")]];
+            $view['tabs']     = [
+                ['name' =>'系统配置','url' =>url('setting/config'),'action' => 1],
+                ['name' =>'服务协议','url' =>url('setting/sla')],
+                ['name' =>'应用接口','url' =>url('setting/api')],
+                ['name' =>'应用文案','url' =>url('setting/writer')],
+            ];
+            $view['info']     = AisConfig::getConfig($this->member_miniapp_id);
+            return view()->assign($view);
+
+        }
+    }
+
+    //文案配置
+    public function writer(){
+        $info =  AisConfig::where(['member_miniapp_id' => $this->member_miniapp_id])->find();
+        if(request()->isAjax()){
+            $data = [
+                'shore_img'  => $this->request->param('shore_img/s'),
+                'shore_text' => $this->request->param('shore_text/s'),
+                'mch_text'   => $this->request->param('mch_text/s'),
+                'mch_qrcode' => $this->request->param('mch_qrcode/s'),
+            ];
+            $validate = $this->validate($data,'Config.writer');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $config['writer'] = json_encode($data);
+            $result = AisConfig::configs($config,$this->member_miniapp_id);
+            if($result){
+                return enjson(200,'操作成功',['url' => url('setting/writer')]);
+            }else{
+                return json(['code'=>0,'msg'=>'操作失败']);
+                return enjson(0,'操作失败');
+            }
+        }else{
+            $view['pathMaps'] = [['name' =>' 文案配置','url' => url("setting/writer")]];
+            $view['tabs']     = [
+                ['name' =>'系统配置','url' =>url('setting/config')],
+                ['name' =>'服务协议','url' =>url('setting/sla')],
+                ['name' =>'应用接口','url' =>url('setting/api')],
+                ['name' =>'应用文案','url' =>url('setting/writer'),'action' => 1],
+            ];
+            $view['article'] = empty($info->writer) ? '' : json_decode($info->writer,true);
+            return view()->assign($view);
+        }
+    }
+    /**
+     * 模板消息配置
+     */
+    public function api(){
+        if(request()->isAjax()){
+            $data = [
+                'qq_lbs_key'    => $this->request->param('qq_lbs_key/s'),
+            ];
+            $result =  AisConfig::configs($data,$this->member_miniapp_id);
+            if($result){
+                return json(['code'=>200,'data' => ['url' => url('setting/api')],'msg'=>'操作成功']);
+            }else{
+                return json(['code'=>0,'msg'=>'操作失败']);
+            }
+        }else{
+            $view['config'] = AisConfig::getConfig($this->member_miniapp_id);
+            $view['pathMaps'] = [['name' =>' 模板消息','url' => url("setting/api")]];
+            $view['tabs']     = [
+                ['name' =>'系统配置','url' =>url('setting/config')],
+                ['name' =>'服务协议','url' =>url('setting/sla')],
+                ['name' =>'应用接口','url' =>url('setting/api'),'action' => 1],
+                ['name' =>'应用文案','url' =>url('setting/writer')],
+            ];
+            return view()->assign($view);
+        }
+    }
+
+    /**
+     * 增加会员制度
+     * @return void
+     */
+    public function sla(){
+        if(request()->isAjax()){
+            $data['sla'] = $this->request->param('sla/s');
+            $result =  AisConfig::configs($data,$this->member_miniapp_id);
+            if($result){
+                return json(['code'=>200,'url' => url('setting/sla'),'msg'=>'操作成功']);
+            }else{
+                return json(['code'=>0,'msg'=>'操作失败']);
+            }
+        }else{
+            $view['pathMaps'] = [['name' =>' 服务协议','url' => url("setting/sla")]];
+            $view['tabs']     = [
+                ['name' =>'系统配置','url' =>url('setting/config')],
+                ['name' =>'服务协议','url' =>url('setting/sla'),'action' => 1],
+                ['name' =>'应用接口','url' =>url('setting/api')],
+                ['name' =>'应用文案','url' =>url('setting/writer')]
+            ];
+            $view['config']  = AisConfig::where(['member_miniapp_id' => $this->member_miniapp_id])->find();
+            return view()->assign($view);
+        }
+    }
+
+    /**
+     *  同城信息配置
+     * @return void
+     */
+    public function info(){
+        if(request()->isAjax()){
+            $param['info'] = $this->request->param('info/a');
+            $validate = $this->validate($param,'Config.info');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=> $validate]);
+            }
+            $result =  AisConfig::info($param,$this->member_miniapp_id);
+            if($result){
+                return enjson(200,['url' => url('setting/info')]);
+            }else{
+                return enjson(0);
+            }
+        }else{
+            $view['pathMaps'] = [['name' =>'推广设置','url' => url("setting/info")]];
+            $view['tabs']     = [
+                ['name' =>'主题管理','url' =>url('info.cate/index')],
+                ['name' =>'模板库','url' =>url('info.tpl/index')],
+                ['name' =>'推广设置','url' =>url('setting/info'),'action' => 1],
+            ];
+            $config  = AisConfig::getConfig($this->member_miniapp_id);
+            $view['info'] = empty($config->info) ? [] : json_decode($config->info,true);
+            return view()->assign($view);
+        }
+    }
+}

+ 47 - 0
application/ais/controller/Test.php

@@ -0,0 +1,47 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 采购基金
+ */
+namespace app\ais\controller;
+use app\ais\controller\api\Base;
+use app\common\facade\WechatProgram;
+use app\ais\model\AisBank;
+use app\ais\model\AisBill;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisOrder;
+use app\ais\model\AisShop;
+use app\ais\model\AisShopCoupon;
+use app\ais\model\AisShopOrder;
+use app\ais\model\AisStoreBill;
+use app\ais\model\AisVip;
+use app\ais\model\AisVipOrder;
+use app\ais\model\AisVipUser;
+use app\ais\model\AisInfo;
+use app\ais\model\AisInfoOrder;
+use app\common\facade\Inform;
+use app\common\facade\WechatPay;
+use app\ais\model\AisConfig;
+use think\facade\Log;
+use filter\Filter;
+use Exception;
+
+class Test extends Common{
+
+
+      /**
+     * 采购基金
+     * @return void
+     */
+    public function index(int $types = 0){
+        $aa = "20200723090806";
+        $bb = strtotime($aa);
+        code(date('Y-m-d H:i:s',$bb));
+        $page = WechatProgram::isTypes($this->member_miniapp_id)->code->getPage();  //小程序页面
+        code($page);
+        // $result = AisVipOrder::where(['order_no' => '5GGA5097384338190763328'])->find();
+        // AisCouponUser::addUserCoupon($result->coupon_ids,$result->uid);
+    }
+}

+ 47 - 0
application/ais/controller/admin/City.php

@@ -0,0 +1,47 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 联盟城市
+ */
+namespace app\ais\controller\admin;
+use app\common\controller\Admin;
+use app\ais\model\AisCity;
+use think\facade\Validate;
+
+class City extends Admin{
+
+
+    /**
+     * 列表
+     */
+    public function index(){
+        $view['parent_id'] = $this->request->param('parent_id/d',0);
+        $view['pathMaps']  = AisCity::selectPath($view['parent_id']);  
+        $view['lists']     = AisCity::where(['parent_id' => $view['parent_id']])->order('sort asc,id asc')->paginate(20);
+        $this->view->engine->layout('admin/layout');
+        return view()->assign($view);
+    }
+    
+    /**
+     * 排序
+     */
+    public function sort(){
+        if(request()->isAjax()){
+            $param = [
+                'sort' => $this->request->param('sort/d',0),
+                'id'   => $this->request->param('id/d'),
+            ];
+            $validate = $this->validate($param,'Category.sort');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $result = AisCity::where(['id'=>$param['id']])->update(['sort' => $param['sort']]);
+            if($result){
+                return enjson(200);
+            }
+            return enjson(0);
+        }
+    }
+}

+ 35 - 0
application/ais/controller/api/Base.php

@@ -0,0 +1,35 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 小程序公共API服务
+ */
+namespace app\ais\controller\api;
+use app\common\controller\Api;
+use app\ais\model\AisStore;
+use app\ais\model\AisCity;
+use think\facade\Request;
+
+class Base extends Api{
+
+    protected $header;
+    protected $lbs;
+    protected $citycode;
+
+    /**
+     * 初始化API并读取城市或你的经纬度
+     * @return void
+     */
+    public function initialize() {
+        parent::initialize();
+        $header_lbs = Request::header('request-lbs');
+        if(!empty($header_lbs)){
+            $lbs =  explode('/',$header_lbs);
+            $location = new \stdClass();
+            $location->lng = $lbs[0] ?: 0;
+            $location->lat = $lbs[1] ?: 0;
+            $this->lbs = $location;
+        }
+    }
+}

+ 146 - 0
application/ais/controller/api/v1/Config.php

@@ -0,0 +1,146 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 获取配置
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisConfig;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisOrder;
+use app\ais\model\AisStore;
+use app\ais\model\AisStoreBill;
+use app\ais\model\AisStoreGroup;
+use app\ais\model\AisStoreUnion;
+use app\ais\model\AisShopOrder;
+use app\ais\model\AisVip;
+use app\ais\model\AisVipUser;
+use app\common\facade\Upload;
+use Yurun\Util\HttpRequest;
+use think\Db;
+
+class Config extends Base{
+
+     /**
+     * 获取应用配置
+     **/
+    public function index(){
+        $info = AisConfig::getConfig($this->miniapp->id);
+        if(!isset($info)) {
+            return enjson(403,'应用未配置');
+        }
+        $writer = json_decode($info->writer);
+        $config['service_telephone'] = $info->service_telephone ??'';
+        $config['shore_img']         = $writer->shore_img ??'';
+        $config['shore_text']        = $writer->shore_text ??'';
+        $config['mch_text']          = $writer->mch_text ??'';
+        $config['mch_qrcode']        = $writer->mch_qrcode ??'';
+        $config['group_profit']      = $info->group_profit ??0;
+        //未绑定手机
+        $config['user_bindphone']    = "";
+        //是否会员
+        $config['vip']              = ['is_vip' => 0,'info' => []];;
+        //判断用户是否商家
+        $config['store']             = ['is_store' => 0,'info' => []];
+        //判断是否圈主
+        $config['group']             = [
+            'is_group'     => 0,
+            'join_num'     => 0,
+            'order'        => 0,
+            'count'        => 0,
+            'help'         => 0,
+            'group_member' => $info->group_member,
+            'group_join'   => $info->group_join,
+            'info'         => []
+        ];
+        $config['user_coupon_num']   = 0; //优惠券
+        $config['user_order_num']    = 0; //买单数
+        $config['user_save_money']   = 0; //已省钱
+        $config['shop_order']        = 0; //优选订单数量
+        if($this->user){
+            //是否会员并返回会员信息
+            $vip = AisVipUser::with(['vip' => function($query) {
+                $query->field('id,name,is_auto_up,price,open_queue_reward,open_share_reward,open_store_num,open_vip_num,pay_queue_reward,pay_share_reward,price,rule');
+            }])->where(['is_lock' => 0,'uid' => $this->user->id])->find();
+            if(!empty($vip)){
+                $config['vip']['is_vip'] = 1;
+                $config['vip']['info']   = $vip->vip;
+            }
+            //统计订单
+            $config['shop_order']        = AisShopOrder::where(['uid' =>$this->user->id,'paid_at' =>1,'status' => 0])->count(); //已支付未核销的订单
+            $config['user_bindphone']    = $this->user->phone_uid ?? ''; //未绑定手机
+            //优惠券
+            $config['user_coupon_num']  = AisCouponUser::where(['member_miniapp_id' => $this->miniapp_id, 'is_end' => 0, 'uid' => $this->user->id])->count();
+            //买单数
+            $config['user_order_num']   = AisOrder::where(['member_miniapp_id' => $this->miniapp_id, 'state'  => 1, 'uid' => $this->user->id])->count();
+            //已省钱
+            $config['user_save_money']  = AisCouponUser::where(['member_miniapp_id' => $this->miniapp_id, 'is_end' => 1, 'uid' => $this->user->id])->where('money', '>', 0)->sum('money');
+            $store = AisStore::manageStore($this->user->id);
+            if ($store) {
+                $config['store']['is_store'] = 1;
+                $config['store']['info']     = $store->toArray();
+                $group_ids = AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'type' => 0,'store_id' => $store->id])->column('group_id');
+                //圈主加群数量
+                $config['group']['join_num'] = AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'store_id' => $store->id,'type' => 0])->count();
+                //买单
+                $config['group']['order']    = AisStoreBill::where(['member_miniapp_id' => $this->miniapp_id])->whereIn('store_id',AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'type' => 0])->whereIn('group_id',$group_ids)->column('store_id'))->sum('money');
+                //次数
+                $config['group']['count']    = AisCouponUser::where(['member_miniapp_id' => $this->miniapp_id])->whereIn('store_id',AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'type' => 0])->whereIn('group_id',$group_ids)->column('store_id'))->count();
+                //互助
+                $help = 0;
+                foreach ($group_ids as $group_id){
+                    $help += AisCouponUser::where(['member_miniapp_id' => $this->miniapp_id,'is_end' => 1])->where('','EXP',Db::raw("FIND_IN_SET(".$group_id.",group_ids)"))->count();
+                }
+                $config['group']['help'] = $help;
+            }
+            $group = AisStoreGroup::where(['member_miniapp_id' => $this->miniapp_id,'uid' => $this->user->id])->find();
+            if ($group) {
+                $config['group']['is_group'] = 1;
+                $config['group']['info']     = $group->toArray();
+            }
+       }
+       return enjson(200,'应用配置',$config);
+    }
+
+    /**
+     * 腾讯地图服务
+     * @return void
+     */
+    public function lib(){
+        $info = AisConfig::getConfig($this->miniapp->id);
+        if(empty($info->qq_lbs_key)) {
+            return enjson(403,'应用未配置QQLbs服务');
+        }
+        if(empty($this->lbs)){
+            return enjson(204);
+        }
+        $http = new HttpRequest;
+        $response = $http->get('https://apis.map.qq.com/ws/geocoder/v1/?location='.$this->lbs->lat.','.$this->lbs->lng.'&key='.$info->qq_lbs_key);
+        $content = $response->json();
+        if(empty($content)){
+            return enjson(204,'位置请求失败');
+        }
+        if($content->status != 0){
+            return enjson(403,$content->message);
+        }
+        return enjson(200,['address' => $content->result->formatted_addresses->recommend,'adcode' => $content->result->ad_info->adcode]);
+    }
+
+    /**
+     * 上传图片
+     * @return void
+     */
+    public function upImg(){
+        $this->isUserAuth();
+        if(request()->isPost()){
+            $rel = Upload::index();
+            if($rel['error'] == 0){
+                return json(['code'=>200,'msg'=>'success','data' => $rel['url']]);
+            }else{
+                return json(['code'=>204,'msg'=>'error']);
+            }
+        }
+    }
+}

+ 104 - 0
application/ais/controller/api/v1/Coupon.php

@@ -0,0 +1,104 @@
+<?php
+/**
+ * 优惠券
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisCoupon;
+use app\ais\model\AisStore;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisStoreUnion;
+use think\Db;
+
+class Coupon extends Base{
+
+   /**
+     * 查询优惠券
+     * mode(new|hot|max)
+     * @return void
+     */
+    public function index(){
+        $param['mode'] = $this->request->param('mode/s','new');
+        $param['page'] = $this->request->param('page/d',1);
+        $this->apiSign($param);
+        $validate = $this->validate($param,'Coupon.api');
+        if(true !== $validate){
+            return enjson(403,$validate);
+        }
+        if($param['mode'] == 'hot'){
+            $condition = [['c.member_miniapp_id','=',$this->miniapp_id],['c.is_lock','=',0],['c.types','<=',2],['c.is_end','=',0]];
+        }else{
+            $condition = [['member_miniapp_id','=',$this->miniapp_id],['is_lock','=',0],['types','<=',2],['is_end','=',0]];
+        }
+        //查询语句
+        $couponSql = AisCoupon::with(['store' => function($query) {
+            $query->field('id,name,img');
+        }]);
+        switch ($param['mode']) {
+            case 'hot':
+                $sql = $couponSql->alias('c')->where($condition)->join('AisCouponUser u', 'c.id = u.coupon_id')->where(['u.member_miniapp_id' => $this->miniapp_id])
+                    ->field('c.*,count(coupon_id) as hot')->group('u.coupon_id')->order('hot desc,c.is_top desc,c.sort desc,c.create_time desc');
+                break;
+            case 'max':
+                $sql = $couponSql->where($condition)->field('*,IF(types > 0,howmuch - howmuch * discount/10,price) as money')->order('money desc,is_top desc,sort desc,create_time desc');
+                break;
+            default:
+                $sql = $couponSql->where($condition)->order('is_top desc,sort desc,create_time desc');
+                break;
+        }
+        $coupon = $sql->page($param['page'],10)->select();
+        if ($coupon->isEmpty()) {
+            return enjson(204,'没有优惠券');
+        }
+        //判断已领取
+        if ($this->user) {
+            $coupon_ids     = array_column($coupon->toArray(),'id');
+            $user_coupon    = AisCouponUser::where(['coupon_id' => $coupon_ids,'uid' => $this->user->id,'is_end'=> 0])->field('uid,store_id,coupon_id')->select()->toArray();
+            $user_coupon_id = array_unique(array_column($user_coupon,'coupon_id'));
+            //给已领取的加状态
+            foreach ($coupon as $key => $value) {
+                $coupon[$key]->is_get_coupon =  in_array($value['id'],$user_coupon_id) ? 1 : 0;
+            }
+        }
+        return enjson(200,$coupon);
+    }
+
+    /**
+     * 显示单个优惠券信息
+     * @return void
+     */
+    public function read(){
+        $param['id'] = $this->request->param('id');  //优惠券id
+        $this->apiSign($param);
+        $info = AisCoupon::with(['couponuser' => function($query) {
+            $query->field('coupon_id,is_end,create_time');
+        },'store' => function($query) {
+            $query->field('id,name,address,longitude,latitude,img,telphone');
+        }])->where(['member_miniapp_id' => $this->miniapp_id,'id' => $param['id']])->find();
+        if (empty($info)) {
+            return enjson(404,'未找到优惠券');
+        }
+        $info->is_get_coupon = (empty($info->couponuser) || $info->couponuser->is_end == 1) ? 0 : 1;
+        $info->store->img    =  $info->store->img;
+        if(!empty($this->lbs)){
+            $info->store->distance = getDistance($this->lbs->lng,$this->lbs->lat,$info->store->longitude,$info->store->latitude);
+        }
+        return enjson(200,$info);
+    }
+
+
+   /**
+     * 指定商家的优惠券
+     * @return void
+     */
+    public function store(){
+        $param['store_id'] = $this->request->param('store_id');  //商家ID
+        $param['page']     = $this->request->param('page/d',1);  //翻页
+        $this->apiSign($param);
+        $coupon = AisCoupon::where(['member_miniapp_id' => $this->miniapp_id,'store_id' => $param['store_id'] ,'is_end' => 0])->where('types','<',3)->order('is_top desc,sort desc,create_time desc')->page($param['page'],10)->select();
+        if ($coupon->isEmpty()) {
+            return enjson(204);
+        }
+        return enjson(200,$coupon);
+    }
+}

+ 127 - 0
application/ais/controller/api/v1/Couponuser.php

@@ -0,0 +1,127 @@
+<?php
+/**
+ * 优惠券
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisCoupon;
+use app\ais\model\AisStore;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisConfig;
+use app\ais\model\AisStoreUnion;
+use think\Db;
+
+class Couponuser extends Base{
+
+    protected $config;
+
+    /**
+     * 初始化当前应用管理员是不是联盟城市账户
+     * @return void
+     */
+    public function initialize() {
+        parent::initialize();
+        $this->isUserAuth();
+        $this->config = AisConfig::getConfig($this->member_miniapp_id);
+    }
+
+    /**
+    * 用户已领优惠券
+    * @return void
+    */
+    public function index(){
+        $param['type'] = $this->request->param('type/d',0);
+        $param['page'] = $this->request->param('page/d',1);
+        $this->apiSign($param);
+        $condition[] = ['member_miniapp_id','=',$this->miniapp_id];
+        $condition[] = ['uid','=',$this->user->id];
+        $condition[] = ['money','=',0];
+        $condition[] = ['is_end','=',0];
+        switch ($param['type']){
+            case 1:
+                $condition[] = ['types','<=',1];
+                break;
+            case 2:
+                $condition[] = ['types','=',2];
+                break;
+            case 3:
+                $condition[] = ['types','=',3];
+                break;
+        }
+        $coupon = AisCouponUser::with(['store' => function($query) {
+            $query->field('id,name,img');
+        }])->where($condition)->order('create_time desc')->page($param['page'],10)->select();
+        if ($coupon->isEmpty()) {
+            return enjson(204);
+        }
+        foreach ($coupon as $key => $info){
+            $coupon[$key]->end_time = $info->create_time + $this->config->coupon_longtime * 60 * 60;
+        }
+        return enjson(200,$coupon);
+    }
+
+    /**
+     * 领取优惠券
+     * @return void
+     */
+    public function getCoupon(){
+        $param['id']        = $this->request->param('id');
+        $param['store_id']  = $this->request->param('store_id'); //引荐的店铺id
+        $this->apiSign($param);
+        $couponUser = AisCouponUser::where(['member_miniapp_id' => $this->miniapp_id,'coupon_id' => $param['id'],'uid' => $this->user->id,'is_end' => 0])->find();
+        if(!empty($couponUser)){
+            return enjson(200,'已经拥有该优惠券',$couponUser);
+        }
+        if($param['id']){
+            $info = AisCoupon::where(['member_miniapp_id' => $this->miniapp_id,'id' => $param['id'],'is_end' => 0])->find();
+            if(!empty($info)){
+                $is_group = AisStoreUnion::isGroup($param['id'],$param['store_id'],$this->miniapp_id);
+                $data['member_miniapp_id'] = $this->miniapp_id;
+                $data['store_id']          = $info->store_id;
+                $data['coupon_id']         = $info->id;
+                $data['uid']               = $this->user->id;
+                $data['is_end']            = 0;
+                $data['types']             = $info->types;
+                $data['name']              = $info->name;
+                $data['price']             = $info->price;
+                $data['discount']          = $info->discount;
+                $data['howmuch']           = $info->howmuch;
+                $data['amount']            = $info->amount;
+                $data['tips']              = $info->tips;
+                $data['group_ids']         = $is_group ?? 0;
+                $data['parent_store_id']   = !empty($param['store_id']) ? $param['store_id'] : 0;
+                $data['update_time']       = time();
+                $data['create_time']       = time();
+                $rel = AisCouponUser::create($data);
+                if($rel){
+                    return enjson(200,$rel);
+                }
+                return enjson(204);
+            }
+        }
+        return enjson(403,'未找到优惠券');
+    }
+
+    /**
+     * 用户优惠券查看
+     * @return void
+     */
+    public function read(){
+        $param['id'] = $this->request->param('id'); 
+        $this->apiSign($param);
+        $info = AisCouponUser::with(['coupon' => function($query) {
+            $query->field('id,create_time');
+        },'store' => function($query) {
+            $query->field('id,name,address,longitude,latitude,img,telphone');
+        }])->where(['member_miniapp_id' => $this->miniapp_id,'id' => $param['id']])->find();
+        if (empty($info)) {
+            return enjson(404,'未找到优惠券');
+        }
+        $info->store->img =  $info->store->img;
+        if(!empty($this->lbs)){
+            $info->store->distance = getDistance($this->lbs->lng,$this->lbs->lat,$info->store->longitude,$info->store->latitude);
+        }
+        return enjson(200,$info);
+    }
+
+}

+ 161 - 0
application/ais/controller/api/v1/Gmcard.php

@@ -0,0 +1,161 @@
+<?php
+/**
+ * 商家储值管理
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisCoupon;
+use app\ais\model\AisStore;
+use app\ais\model\AisCard;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisStoreUnion;
+use filter\Filter;
+use think\Db;
+
+class Gmcard extends Base{
+
+    protected $store;
+
+    public function initialize() {
+        parent::initialize();
+        $this->isUserAuth();
+        $this->store = AisStore::manageStore($this->user->id);
+        if(empty($this->store)){
+            exit(json_encode(['code' => 403,'msg'=>'无法找到该商家']));
+        }
+    }
+
+   /**
+    * 用户已领优惠券
+    * @return void
+    */
+    public function index(){
+        $this->apiSign();
+        $condition[] = ['member_miniapp_id','=',$this->member_miniapp_id];
+        $condition[] = ['store_id','=',$this->store->id];
+        $condition[] = ['is_end','=',0];
+        $card = AisCard::with(['coupon'	=> function($query) {
+            $query->field('id,amount,num,howmuch');
+        }])->withCount('carduser')->withSum('cardorder','amount')->field('id,locktime,name,price,store_id,create_time,coupon_id')->where($condition)->select();
+        if ($card->isEmpty()) {
+            return enjson(204);
+        }
+        return enjson(200,$card);
+    }
+
+    /**
+     * 读取活动优惠券
+    */
+    public function storeCardInfo(){
+        $param['id'] = $this->request->param('id/d');
+        $this->apiSign($param);
+        $card = AisCard::where(['id' => $param['id']])->find();
+        if (empty($card)) {
+            return enjson(204);
+        }
+        $data = [
+            'is_lock'  => $card->is_lock,
+            'name'     => $card->name,
+            'price'    => intval($card->price),
+            'num'      => $card->coupon->num,
+            'locktime' => date('Y/m/d',$card->locktime),
+            'content'  => htmlspecialchars_decode($card->tips),
+            'coupon' =>[
+                'howmuch' => $card->coupon->howmuch,
+                'amount'  => intval($card->coupon->amount),
+                'name'    => $card->coupon->name,
+                'tips'    => $card->coupon->tips,
+            ]
+        ];
+        return enjson(200,$data);
+    } 
+
+     /**
+     * 以下商家管理
+     * ##########################################
+     * @return void
+     * 添加和修改优惠券
+     */
+    public function edit(){
+        if(request()->isPost()){
+            $param['id']       = $this->request->param('id');
+            $param['name']     = $this->request->param('name');
+            $param['price']    = $this->request->param('price/f',0);
+            $param['amount']   = $this->request->param('amount/d',0);
+            $param['howmuch']  = $this->request->param('howmuch/f',0);
+            $param['num']      = $this->request->param('num/d');
+            $param['locktime'] = $this->request->param('locktime/s');
+            $param['tips']     = $this->request->param('tips/s');
+            $param['content']  = $this->request->param('content/s');
+            $this->apiSign($param);
+            $validate = $this->validate($param,'Card.api');
+            if(true !== $validate){
+                return enjson(403,$validate);
+            }
+            //优惠券数据
+            $coupon['types']             = 3;
+            $coupon['is_lock']           = 1;
+            $coupon['name']              = $param['name'];
+            $coupon['amount']            = $param['amount'];
+            $coupon['howmuch']           = $param['howmuch'];
+            $coupon['tips']              = $param['tips'];
+            $coupon['num']               = $param['num'];
+            $coupon['member_miniapp_id'] = $this->member_miniapp_id;
+            $coupon['store_id']          = $this->store->id;
+            $coupon['citycode']         = $this->store->citycode;
+            $coupon['update_time']       = time();
+            $coupon['create_time']       = time();
+            //判断是添加还是修改
+            $card_rel = [];
+            if(!empty($param['id'])){
+                $card_rel = AisCard::where(['id' => $param['id']])->find();
+            }
+            if(empty($card_rel)){
+                $coupon_rel = AisCoupon::create($coupon);
+                if(!$coupon_rel){
+                    return enjson(403,'储值活动创建失败');
+                }
+                $coupon_id = $coupon_rel->id;
+            }else{
+                $coupon_id = $card_rel->coupon_id;
+                $coupon_rel = AisCoupon::where(['id' => $card_rel->coupon_id])->update($coupon);
+                if(!$coupon_rel){
+                    return enjson(403,'未找到储值活动');
+                }
+            }
+            //判断是修改储值还是增加
+            $card['store_id']          = $this->store->id;
+            $card['member_miniapp_id'] = $this->member_miniapp_id;
+            $card['name']              = $param['name'];
+            $card['price']             = $param['price'];
+            $card['tips']              = htmlspecialchars(base64_decode($param['content']));
+            $card['coupon_id']         = $coupon_id;
+            $card['locktime']          = strtotime($param['locktime']);
+            $card['update_time']       = time();
+            $card['create_time']       = time();
+            if(empty($card_rel)){
+                $rel = AisCard::create($card);
+            }else{
+                $rel = AisCard::where(['id' => $card_rel->id])->update($card);
+            } 
+            if($rel){
+                return enjson(200,'储值活动创建成功');
+            }
+            return enjson(403,'未找到储值活动');
+        }
+    }
+
+     //删除储值
+    public function storeCardDel(){
+        $param['id'] = $this->request->param('id/d',0);
+        $this->apiSign($param);
+        $card = AisCard::where(['member_miniapp_id' => $this->miniapp_id,'store_id' => $this->store->id,'id' => $param['id']])->find();
+        if (empty($card)) {
+            return enjson(404,'未找到储值活动');
+        }
+        $card->is_end = 1;
+        $card->save();
+        AisCoupon::where(['id' => $card->coupon_id])->update(['is_end' => 1]);
+        return enjson(200,'删除成功');
+    }
+}

+ 122 - 0
application/ais/controller/api/v1/Gmcoupon.php

@@ -0,0 +1,122 @@
+<?php
+/**
+ * 优惠券
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisCoupon;
+use app\ais\model\AisStore;
+use app\ais\model\AisCouponUser;
+use think\Db;
+
+class Gmcoupon extends Base{
+
+    protected $store;
+
+    public function initialize() {
+        parent::initialize();
+        $this->isUserAuth();
+        $this->store = AisStore::manageStore($this->user->id);
+        if(empty($this->store)){
+            exit(json_encode(['code' => 403,'msg'=>'无法找到该商家']));
+        }
+    }
+
+   /**
+     * 指定商家的优惠券
+     * @return void
+     */
+    public function index(){
+        $this->apiSign();
+        $coupon = AisCoupon::where(['member_miniapp_id' => $this->miniapp_id,'store_id' => $this->store->id,'is_end' => 0])->where('types','<',3)->order('is_top desc,sort desc,create_time desc')->select();
+        if ($coupon->isEmpty()) {
+            return enjson(204);
+        }
+        return enjson(200,$coupon);
+    }
+
+    /**
+     * 显示单个优惠券信息
+     * @return void
+     */
+    public function read(){
+        $param['id']        = $this->request->param('id');  //优惠券id
+        $this->apiSign($param);
+        $info = AisCoupon::where(['member_miniapp_id' => $this->miniapp_id,'id' => $param['id'],'store_id' => $this->store->id])->find();
+        if (empty($info)) {
+            return enjson(404,'未找到优惠券');
+        }
+        $count = AisCouponUser::where(['coupon_id' => $info->id])->count(); //已领取
+        $order = AisCouponUser::where(['coupon_id' => $info->id,'is_end' => 0,'money' => 0])->count();  //待使用
+        $money = AisCouponUser::where(['coupon_id' => $info->id,'is_end' => 1])->sum('money');  //共优惠
+        return enjson(200,['coupon' => $info,'count' => $count,'order' => $order,'money' => $money]);
+    }
+
+    /**
+     * 添加和修改
+     */
+    public function edit(){
+        $param['id']        = $this->request->param('id');
+        $param['types']     = $this->request->param('types/d',0);
+        $param['price']     = $this->request->param('price/d',0);
+        $param['amount']    = $this->request->param('amount/d',0);
+        $param['discount']  = $this->request->param('discount/s',0);
+        $param['num']       = $this->request->param('num/d',1);
+        $param['howmuch']   = $this->request->param('howmuch/d',0);
+        $param['name']      = $this->request->param('name/s');
+        $param['tips']      = $this->request->param('tips/s');
+        $this->apiSign($param);
+        $validate = $this->validate($param,'Coupon.edit');
+        if(true !== $validate){
+            return enjson(403,$validate);
+        }
+        switch ($param['types']) {
+            case 1: //折扣券
+                $param['amount']   = 0;
+                $param['price']    = 0;
+                break;
+            case 2: //兑换券
+                $param['discount'] = 0;
+                $param['price']    = 0;
+                break;
+            default: //代金券
+                $param['discount'] = 0;
+                $param['amount']   = 0;
+                break;
+        }
+        $param['is_top']  = 0;
+        $param['citycode'] = $this->store->citycode;
+        $coupon = new AisCoupon();
+        if($param['id']){
+            $info = $coupon->where(['member_miniapp_id' => $this->miniapp_id,'id' => $param['id']])->find();
+            if(!$info){
+                return enjson(403,'未找到要修改的优惠券');
+            }
+            if($info->is_lock){
+                return enjson(403,'本券禁止修改');
+            }
+            $result = $coupon->allowField(true)->save($param,['id' => $param['id']]);
+        }else{
+            $param['member_miniapp_id'] = $this->miniapp_id;
+            $param['store_id']          = $this->store->id;
+            $param['create_time']       = time();
+            $param['update_time']       = time();
+            $result                     = $coupon->create($param);
+        }
+        return enjson(200,'优惠券设置成功');
+    }
+
+
+     //商户删除优惠券
+    public function delete(){
+        $param['id'] = $this->request->param('id/d',0);
+        $this->apiSign($param);
+        $coupon = AisCoupon::where(['member_miniapp_id' => $this->miniapp_id,'store_id' => $this->store->id,'id' => $param['id'],'is_lock' => 0,'is_end' => 0])->find();
+        if (empty($coupon)) {
+            return enjson(404,'当前优惠券禁止删除');
+        }
+        $coupon->is_end = 1;
+        $coupon->save();
+        return enjson(200,'成功删除优惠券');
+    }
+}

+ 225 - 0
application/ais/controller/api/v1/Gmgroup.php

@@ -0,0 +1,225 @@
+<?php
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisConfig;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisStore;
+use app\ais\model\AisStoreBill;
+use app\ais\model\AisStoreGroup;
+use app\ais\model\AisStoreUnion;
+use filter\Filter;
+use think\Db;
+
+class Gmgroup extends Base{
+
+    protected $store;
+    public function initialize() {
+        parent::initialize();
+        $this->isUserAuth();
+        $this->store = AisStore::manageStore($this->user->id);
+        if(empty($this->store)){
+            exit(json_encode(['code' => 403,'msg'=>'无法找到该商家']));
+        }
+    }
+
+    /**
+     * 我的商圈
+     * @return void
+     */
+    public function index(){
+        $this->apiSign();
+        $flag = [];
+        $list = AisStoreGroup::whereIn('id',AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'store_id'=> $this->store->id,'type' => 0])->column('group_id'))->select()->toArray();
+        if (!empty($list)) {
+            foreach ($list as $key => $value) {
+                $list[$key]['red']       = 0;
+                $list[$key]['is_manage'] = 0; 
+                if($value['uid'] == $this->user->id){
+                    $list[$key]['is_manage'] = 1; 
+                    $unionList = AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id'=> $value['id'] ,'type' => 1])->select();
+                    if(!$unionList->isEmpty()){
+                        $list[$key]['red'] = count($unionList); //如果有值 代表你是圈主,有n个人待审核
+                    }
+                }
+                $list[$key]['num'] = AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id'=> $value['id'] ,'type' => 0])->count();
+                $flag[] = $list[$key]['is_manage'];
+            }
+        }
+        array_multisort($flag,SORT_DESC,$list); //排序把圈主排在第一
+        //申请待通过
+        $apply = AisStoreGroup::whereIn('id',AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'store_id'=> $this->store->id ?? 0,'type' => 1])->column('group_id'))->select();
+        return enjson(200,'success',['list' => $list,'apply' => $apply]);
+    }
+
+    //创建和更新商圈
+    public function edit(){
+        $param['title']     = $this->request->param('title/s');
+        $param['content']   = $this->request->param('content/s');
+        $param['face']      = $this->request->param('face/s','[]','htmlspecialchars_decode');
+        $this->apiSign($param);
+        $validate = $this->validate($param,'Group.edit');
+        if(true !== $validate){
+            return enjson(403,$validate);
+        }
+        $face  = Filter::filter_escape(json_decode($param['face'],true));
+        $store = AisStore::manageStore($this->user->id);
+        if (!$store) {
+            return enjson(403,'你不是商家,禁止创建商圈');
+        }
+        $result = AisStoreGroup::where(['member_miniapp_id' => $this->miniapp_id,'uid' =>  $this->user->id])->find();
+        if($result){
+            $days = intval((time()-$result->update_time)/86400);
+            if($days < 1){
+                return enjson(403,'每天只能修改一次商圈信息');
+            }
+            $result->title       = $param['title'];
+            $result->content     = $param['content'];
+            $result->update_time = time();
+            if(!empty($face)){
+                $result->face = $face[0];
+            }
+            $result->save();
+            return enjson(200,'商圈修改成功');
+        }else{
+            $data['member_miniapp_id'] = $this->miniapp_id;
+            $data['uid']               = $this->user->id;
+            $data['title']             = $param['title'];
+            $data['content']           = $param['content'];
+            if(!empty($face)){
+                $data['face'] = $face[0];
+            }
+            $group = AisStoreGroup::create($data);
+            AisStoreUnion::create(['member_miniapp_id' => $this->miniapp_id,'group_id' => $group->id,'store_id' => $store->id,'type' => 0,'create_time' => time(),'update_time' => time()]);
+            return enjson(200,'商圈创建成功');
+        }
+    }
+   
+    //商圈详情
+    public function read(){
+        $param['id'] = $this->request->param('id');    //商圈id
+        $this->apiSign($param);
+        $info = AisStoreGroup::where(['member_miniapp_id' => $this->miniapp_id,'id' => $param['id']])->find();
+        if (!$info) {
+            return enjson(204);
+        }
+        $info->is_manage = $info->uid == $this->user->id?1:0;
+        $info->red = 0;
+        $info->num = AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id'=> $info->id,'type' => 0])->count();
+        if($info->is_manage){
+            $info->red = AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id'=> $info->id,'type' => 1])->count();
+        } 
+        //买单
+        $order = AisStoreBill::where(['member_miniapp_id' => $this->miniapp_id])->whereIn('store_id',AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id' => $param['id'],'type' => 0])->column('store_id'))->sum('money');
+        //次数
+        $count = AisCouponUser::where(['member_miniapp_id' => $this->miniapp_id])->whereIn('store_id',AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id' => $param['id'],'type' => 0])->column('store_id'))->count();
+        //互助
+        $help = AisCouponUser::where(['member_miniapp_id' => $this->miniapp_id,'is_end' => 1])->where('','EXP',Db::raw("FIND_IN_SET(".$param['id'].",group_ids)"))->count();
+        return enjson(200,['group' => $info,'order' => $order,'count' => $count,'help' => $help]);
+    }
+
+    //商圈中的店铺
+    public function store(){
+        $param['id']   = $this->request->param('id');    //商圈id
+        $param['type'] = $this->request->param('type');  //0正常 1待审核 2拒绝 3退出 4踢出
+        $this->apiSign($param);
+        $list = AisStore::where(['member_miniapp_id' => $this->miniapp_id])->whereIn('id',AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id' => $param['id'],'type' => $param['type']])->column('store_id'))->select();
+        if ($list->isEmpty()) {
+            return enjson(200);
+        }
+        return enjson(200,$list);
+    }
+
+    //申请加入商圈
+    public function add(){
+        $param['id'] = $this->request->param('id');  //商圈id
+        $this->apiSign($param);
+        $store = AisStore::where(['member_miniapp_id' => $this->miniapp_id,'manage_uid' => $this->user->id])->find();
+        if(empty($store)){
+            return enjson(403,'你不是商家,禁止加入商家');
+        }
+        $info = AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id' => $param['id'],'store_id' => $store->id,'type' => 0])->find();
+        if($info){
+            return enjson(403,'您已经加入该商圈');
+        }
+        $info = AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id' => $param['id'],'store_id' => $store->id,'type' => 1])->find();
+        if($info){
+            return enjson(403,'您已经申请过该商圈');
+        }
+        $config = AisConfig::getConfig($this->miniapp_id);
+        $list = AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id' => $param['id'],'type' => 0])->select();
+        if(!empty($config->group_member) && count($list) >= $config->group_member){
+            return enjson(403,'商圈只能有'.$config->group_member.'个成员');
+        }
+        $size = AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'store_id' => $store->id,'type' => 0])->select();
+        if(!empty($config->group_join) && count($size) >= $config->group_join){
+            return enjson(403,'只能加入'.$config->group_join.'个商圈');
+        }
+        $code = AisStoreUnion::create(['member_miniapp_id' => $this->miniapp_id,'group_id' => $param['id'],'store_id' => $store->id,'type' => 1,'create_time' => time(),'update_time' => time()]);
+        if ($code) {
+            return enjson(200,"已提交申请");
+        }
+        return enjson(204,'未找到商圈');
+    }
+
+    //商圈操作 0同意 2拒绝 3退出 4踢出
+    public function operate(){
+        $param['group_id']  = $this->request->param('group_id');    //商圈ID
+        $param['store_id']  = $this->request->param('store_id',0);  //商店ID
+        $param['type']      = $this->request->param('type',1);      //0同意 2拒绝 3退出 4踢出
+        $this->apiSign($param);
+        //读取商店信息
+        if($param['store_id']){
+            $condition['id'] = $param['store_id'];
+        }else{
+            $condition['manage_uid'] = $this->user->id;
+        }
+        $store = AisStore::where(['member_miniapp_id' => $this->miniapp_id])->where($condition)->find();
+        if(empty($store)){
+            return enjson(403,'你不是商家');
+        }
+        $info = AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id' => $param['group_id'],'store_id' => $store->id])->find();
+        if(empty($info)){
+            return enjson(403,'你不在当前商圈');
+        }
+        $group = AisStoreGroup::where(['member_miniapp_id' => $this->miniapp_id,'id' => $info->group_id])->find();
+        if(!empty($group) && $group->uid == $this->user->id && ($param['type'] == 0 || $param['type'] == 2 || $param['type'] == 4)){
+            switch ($param['type']) {
+                case 0:
+                    //默认通过
+                    $info->type = 0;
+                    $msg = '已审核通过';
+                    //判断权限
+                    $config = AisConfig::getConfig($this->miniapp_id);
+                    $store_group_num   = AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id' => $info->group_id,'type' => 0])->count();
+                    if(!empty($config->group_member) && $store_group_num >= $config->group_member){
+                        $info->type = 2;
+                        $msg = '你的商圈只能有'.$config->group_member.'个成员';
+                    }
+                    $size = AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'store_id' => $store->id,'type' => 0])->count();
+                    if(!empty($config->group_join) && $size >= $config->group_join){
+                        $info->type = 2;
+                        $msg = '已加入'.$size.'个商圈,每个商家只能加入.'.$config->group_join.'个商圈';
+                    }
+                    break;
+                case 2:
+                    $info->type = 2;
+                    $msg = '已拒绝加圈申请';
+                    break;
+                case 4:  
+                    $info->type = 4;
+                    $msg = '已成功踢出我的商圈';
+                    break;
+                default:
+                    return enjson(403,'操作失败');
+                    break;
+            }
+        }elseif($param['type'] == 3){
+            $info->type = 3;
+            $msg = '你成功退出商圈';
+        }else{
+            return enjson(403,'操作失败');
+        }
+        $info->save();
+        return enjson(200,$msg);
+    }
+}

+ 148 - 0
application/ais/controller/api/v1/Gmstore.php

@@ -0,0 +1,148 @@
+<?php
+/**
+ * 商家管理店铺
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisStore;
+use app\ais\model\AisStoreBill;
+use app\ais\model\AisStoreGroup;
+use app\ais\model\AisStoreUnion;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisOrder;
+use app\ais\model\AisCoupon;
+use think\helper\Time;
+use filter\Filter;
+
+class Gmstore extends Base{
+
+    protected $store;
+
+    public function initialize() {
+        parent::initialize();
+        $this->isUserAuth();
+        $this->store = AisStore::manageStore($this->user->id);
+        if(empty($this->store)){
+            exit(json_encode(['code' => 403,'msg'=>'无法找到该商家']));
+        }
+    }
+
+    /**
+     * 申请入驻商家/修改商家信息
+     */
+    public function edit(){
+        if (request()->isPost()) {
+            $param = [
+                'name'      => $this->request->param('name/s'),
+                'address'   => $this->request->param('address/s'),
+                'telphone'  => $this->request->param('telphone/s'),
+                'mch_id'    => $this->request->param('mch_id/d',''),
+                'latitude'  => $this->request->param('latitude/s'),
+                'longitude' => $this->request->param('longitude/s'),
+                'imgs'      => $this->request->param('imgs/s','[]','htmlspecialchars_decode'),
+            ];
+            $this->apiSign($param);
+            $validate = $this->validate($param,'Store.gmedit');
+            if(true !== $validate){
+                return enjson(403,$validate);
+            }
+            $imgs  = Filter::filter_escape(json_decode($param['imgs'],true));
+            if(!empty($imgs)){
+                $data['img']   = $imgs[0];
+            }  
+            $data['name']      = $param['name'];
+            $data['telphone']  = $param['telphone'];
+            $data['mch_id']    = $param['mch_id'];
+            $data['address']   = $param['address'];
+            $data['latitude']  = $param['latitude'];
+            $data['longitude'] = $param['longitude'];
+            $rel = AisStore::where(['id' => $this->store->id])->update($data);
+            if($rel){
+                return enjson(200,"成功");
+            }
+            return enjson(403,"失败");
+        }
+    }
+
+    //读取商家信息
+    public function read(){
+        $this->apiSign();
+        return enjson(200,$this->store);
+    }
+
+    //商家数据统计
+    public function statis(){
+        $this->apiSign();
+        list($start, $end) = Time::yesterday();
+        $amount     = AisOrder::where([['store_id','=', $this->store->id],['state', '=',1],['update_time', '>=',$start],['update_time', '<=',$end]])->sum('price');
+        $coupon     = AisCoupon::where(['store_id' => $this->store->id])->count(); //已领取
+        $couponuser = AisCouponUser::where(['store_id' => $this->store->id])->where('parent_store_id','>',0)->count(); //引流
+        $from       = AisCouponUser::where([['store_id', '=', $this->store->id],['parent_store_id', '>',0],['money', '>',0],['is_end', '=',1]])->count(); //引流
+        return enjson(200,['store'=>$this->store,'amount' => $amount,'coupon'=>$coupon,'couponuser' => $couponuser,'from'=> $from]);
+    }
+
+    //商家收入
+    public function bill(){
+        $param = [
+            'page'           => $this->request->param('page/d',1),
+            'store_id'       => $this->request->param('store_id'),
+            'store_chain_id' => $this->request->param('store_chain_id'),
+            'fixed_date'     => $this->request->param('fixed_date'),
+            'times'          => $this->request->param('times','[]','htmlspecialchars_decode'),
+        ];
+        $this->apiSign($param);
+        //判断是修改还是创建
+        $store = AisStore::manageStore($this->user->id);
+        if (!$store) {
+            return enjson(404);
+        }
+        $condition[] = ['member_miniapp_id','=',$this->miniapp_id];
+        $condition[] = ['store_id', '=',$this->store->id];
+        if($param['store_chain_id']){
+            $condition[] = ['store_chain_id', '=',$param['store_chain_id']];
+        }
+        if($param['fixed_date'] == 3){
+            $times = Filter::filter_escape(json_decode($param['times'],true));
+            if(!empty($times['startime']) || !empty($times['endtime'])){
+                $start  = strtotime($times['startime'].'00:00:00');
+                $end   = strtotime($times['endtime'].'23:59:59');
+                if($start >= $end){
+                    return enjson(403,'开启日期禁止大于结束日期');
+                } 
+                $condition[] = ['update_time', '>=', $start];
+                $condition[] = ['update_time', '<=', $end];
+            }
+        }else{
+            switch ($param['fixed_date']) {
+                case 1:
+                    list($start, $end) = Time::yesterday();
+                    break;
+                case 2:
+                     list($start, $end) = Time::month();
+                    break;
+                default:
+                    list($start, $end) = Time::today();
+                    break;
+            }
+            $condition[] = ['update_time', '>=', $start];
+            $condition[] = ['update_time', '<=', $end];
+        }
+        $rel = AisStoreBill::withAttr('update_time', function ($value, $data) {
+            return date('Y-m-d H:i',$value);
+        })->with(['user'=> function($query) {
+            $query->field('id,face,nickname');
+        }])->where($condition)->order('id desc')->page($param['page'],20)->select();
+        if (empty($rel)) {
+            return enjson(204);
+        }
+        $amount['inc']   = 0;
+        $amount['dec']   = 0;
+        $amount['order'] = 0;
+        if($param['page'] == 1){
+            $amount['inc']   = AisStoreBill::where($condition)->where('money','>',0)->sum('money');
+            $amount['dec']   = AisStoreBill::where($condition)->where('money','<',0)->sum('money');
+            $amount['order'] = AisOrder::where($condition)->where('state','=',1)->sum('price');
+        }
+        return enjson(200,['bill' => $rel,'amount' => $amount]);
+    }
+}

+ 35 - 0
application/ais/controller/api/v1/Group.php

@@ -0,0 +1,35 @@
+<?php
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisConfig;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisStore;
+use app\ais\model\AisStoreBill;
+use app\ais\model\AisStoreGroup;
+use app\ais\model\AisStoreUnion;
+use filter\Filter;
+use think\Db;
+
+class Group extends Base{
+
+    
+    //商圈详情
+    public function read(){
+        $param['id'] = $this->request->param('id');    //商圈id
+        $this->apiSign($param);
+        $info = AisStoreGroup::where(['member_miniapp_id' => $this->miniapp_id,'id' => $param['id']])->find();
+        if (!$info) {
+            return enjson(204);
+        }
+        $info->num = AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id'=> $info->id,'type' => 0])->count();
+        //买单
+        $order = AisStoreBill::where(['member_miniapp_id' => $this->miniapp_id])->whereIn('store_id',AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id' => $param['id'],'type' => 0])->column('store_id'))->sum('money');
+        //次数
+        $count = AisCouponUser::where(['member_miniapp_id' => $this->miniapp_id])->whereIn('store_id',AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id' => $param['id'],'type' => 0])->column('store_id'))->count();
+        //互助
+        $help = AisCouponUser::where(['member_miniapp_id' => $this->miniapp_id,'is_end' => 1])->where('','EXP',Db::raw("FIND_IN_SET(".$param['id'].",group_ids)"))->count();
+        //商家列表
+        $list = AisStore::where(['member_miniapp_id' => $this->miniapp_id])->whereIn('id',AisStoreUnion::where(['member_miniapp_id' => $this->miniapp_id,'group_id' => $param['id'],'type' => 0])->column('store_id'))->select();
+        return enjson(200,['group' => $info,'order' => $order,'count' => $count,'help' => $help,'store' => $list]);
+    }
+}

+ 29 - 0
application/ais/controller/api/v1/Index.php

@@ -0,0 +1,29 @@
+<?php
+/**
+ * 常用接口
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisAdwords;
+
+class Index extends Base{
+
+    /**
+     * 广告图片
+     * @return void
+     */
+    public function adwords(){
+        $param['ids'] = $this->request->param('ids');
+        $this->apiSign($param);
+        $group = explode('/',$param['ids']);
+        $adword = [];
+        foreach ($group as $value) {
+            $adword[$value] = [];
+        }
+        $rel = AisAdwords::where(['member_miniapp_id' => $this->miniapp_id,'group' => $group])->field('title,picture,link,open_type,group')->order('sort desc,id desc')->select();
+        foreach ($rel as $rs) {
+            $adword[$rs['group']][] = $rs;
+        }
+        return enjson(200,$adword);
+    }
+}

+ 271 - 0
application/ais/controller/api/v1/Info.php

@@ -0,0 +1,271 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 小程序公共API服务
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisCity;
+use app\ais\model\AisInfoCate;
+use app\ais\model\AisInfo;
+use app\ais\model\AisInfoFollow;
+use app\ais\model\AisInfoMp;
+use app\ais\model\AisConfig;
+use app\ais\model\AisInfoReply;
+use app\ais\model\AisStore;
+use app\common\model\SystemUser;
+use think\facade\Config;
+use util\Util;
+
+class Info extends Base{
+
+    /**
+     * 获取配置参数
+     * @return void
+     */
+    public function getconfig(){
+        $this->apiSign();
+        $result = AisConfig::getConfig($this->miniapp_id);
+        if(empty($result)){
+            return enjson(204);
+        }else{
+            $data = json_decode($result->info,true);
+            foreach ($data as $key => $value) {
+                $data[$key]['money'] = intval($value['money']);
+            }
+            return enjson(200,$data);
+        }        
+    }
+
+    /**
+     * 读取信息列表
+     * @param integer 读取ID
+     * @return json
+     */
+    public function index(){
+        $param['page']    = $this->request->param('page/d');
+        $param['cate_id'] = $this->request->param('cate_id/d',0);
+        $param['citycode']  = $this->request->param('citycode/d');
+        $param['state']   = $this->request->param('state/d',1);
+        $param['keyword'] = $this->request->param('keyword/s');
+        $this->apiSign($param);
+        $order = "is_top desc,sort desc,id desc";
+        $where = [];
+        $where['member_miniapp_id'] = $this->miniapp_id;
+        $where['is_lock']           = 0;
+        if($param['citycode']){
+            $where['citycode']  = AisCity::whereIn('parent_id',AisCity::where(['code' => $param['citycode']])->column('parent_id'))->column('code');
+        }
+        if($param['cate_id']){
+            $where['cate_id']  = $param['cate_id'];
+        }else{
+            if(empty($param['keyword'])){
+                if(!$param['state']){  //关注
+                    //读取我的关注UID    
+                    $this->isUserAuth();   //我的关注要登录
+                    $uid = AisInfoFollow::where(['uid' => $this->user->id])->column('like_uid');
+                    if(empty($uid)){
+                        return enjson(204,'没有内容');
+                    }else{
+                        $where['uid'] = $uid;
+                    }
+                }else{ //热门
+                    $order = "is_top desc,sort desc,like desc,id desc";
+                }
+            }
+        }
+        $data = AisInfo::apiLists($where,$order,$this->user,$param['keyword']);
+        if(empty($data)){
+            return enjson(204,'没有内容');
+        }else{
+            return enjson(200,'成功',$data);
+        }
+    }
+
+   /**
+     * 获取信息评论
+     * @param integer 读取ID
+     * @return json
+     */
+    public function reply(){
+        $param['page'] = $this->request->param('page/d');
+        $param['id']   = $this->request->param('id/d');
+        $this->apiSign($param);
+        $where['info_id'] = $param['id'];
+        $where['state']   = 0;
+        $rel = AisInfoReply::with([
+            'user' => function($query) {
+                $query->field('id,nickname,face');
+            },
+        ])->where($where)->order('id desc')->paginate(10);
+        $data = $rel->toArray()['data'];
+        array_walk($data,function(&$item,$key){
+            $item['is_like'] = 0;
+        });
+        if(empty($data)){
+            return enjson(204);
+        }else{
+            return enjson(200,'成功',$data);
+        }
+    }    
+
+    /**
+     * 读取微信API
+     * @param integer 读取ID
+     * @return json
+     */
+    public function cate(){
+        $this->apiSign();
+        $where = [];
+        $where['member_miniapp_id'] = $this->miniapp_id;
+        $data = AisInfoCate::where($where)->field('id,name')->order('sort desc,id desc')->select()->toArray();
+        return enjson(200,'成功',$data);
+    }
+
+   /**
+     * 获取单个信息
+     * @param integer 读取ID
+     * @return json
+     */
+    public function getview(int $info_id){
+        $param['info_id'] = $this->request->param('info_id/d',0);
+        $this->apiSign($param);
+        $rel = AisInfo::with([
+            'user' => function($query) {
+                $query->field('id,nickname,face');
+            },
+            'cate' => function($query) {
+                $query->field('id,tpl_id,title');
+            },
+            'mp'   => function($query) {
+                $query->field('id,uid,logo,title,is_vip');
+            }
+        ])->where(['id'=> $info_id])->find();
+        if(empty($rel)){
+            return enjson(404);
+        }
+        //模板信息
+        if(empty($rel->cate->tpl)){
+            $rel['button_name'] = '立即下单';
+            $rel['tips']        = '任何有用户发布,下单后请电话再次确认';
+            $rel['is_shop']     = 0;
+            $rel['users']       = [];
+        }else{
+            $rel['button_name'] = $rel->cate->tpl->button_name;
+            $rel['tips']        = $rel->cate->tpl->tips;
+            $rel['is_shop']     = $rel->cate->tpl->is_shop;
+            $rel['users']       = json_decode($rel->cate->tpl->users,true);
+        }
+        $rel['images']      = $rel->images;
+        $rel['images_len']  = count($rel->images);
+        $rel['fields']      = empty($rel->fields) ? [] : json_decode($rel->fields,true);
+        $rel['create_time'] = util::ftime($rel->create_time);
+        $rel['is_mp']       = empty($rel->mp)?0:1;
+        //是否点赞
+        $rel['is_like']     = 0; 
+        $rel['like_face']   = empty($rel->like_face) ? [] : json_decode($rel->like_face,true);
+        //判断是否被关注
+        $rel['is_follow']   = !empty($rel->follow) && !empty($this->user) && $rel->follow->uid = $this->user->id ? 1:0;  
+        return enjson(200,'成功',$rel);
+    }
+
+
+    /**
+     * 注册城市号
+     */
+    public function mp(){
+        $param['uid'] = $this->request->param('uid/d',0);
+        $param['mid'] = $this->request->param('mid/d',0);
+        $this->apiSign($param);
+        $where = [];
+        if($param['mid']){
+            $where['id']  = $param['mid'];
+        }else{
+            $where['uid'] = $param['uid'];
+        }
+        $rel = AisInfoMp::where($where)->find();
+        if($rel){
+            $rel->views = AisInfo::where(['uid' => $rel->uid])->count();
+            $rel->like  = AisInfoFollow::where(['uid' => $rel->uid])->count();
+            $rel->is_follow =  0;
+            $rel->vip_time = empty($rel->vip_time)?'0':date('Y-m-d',$rel->vip_time);
+            $rel->reg_time = empty($rel->reg_time)?'0':date('Y-m-d',$rel->reg_time);
+            if($this->user){
+                $rel->is_follow = AisInfoFollow::where(['uid' => $this->user->id,'like_uid'=>$rel->uid])->count();
+            }
+            //读取好店
+            $condition['manage_uid']        = $rel->uid;
+            $condition['member_miniapp_id'] = $this->miniapp_id;
+            $condition['is_lock']           = 0;
+            $info = AisStore::getView($condition);
+            if(empty($info)){
+                $rel->is_store = 0;
+                $rel->store    = [];
+            }else{
+                $info->distance = getDistance($this->lbs->lng,$this->lbs->lat,$info['longitude'],$info['latitude']);
+                $chain = [];
+                foreach ($info->chain as $key => $value) {
+                    $chain[$key]['title']    = $value->title;
+                    $chain[$key]['address']  = $value->address;
+                    $chain[$key]['telphone'] = $value->telphone;
+                    $chain[$key]['distance'] = getDistance($this->lbs->lng,$this->lbs->lat,$value->longitude,$value->latitude);
+                }
+                unset($info->chain);
+                $info->chain = $chain;
+                $rel->store  = $info;
+                $rel->is_store = 1;
+            }
+        }else{
+            if($param['uid']){
+                $rel['is_store']  = 0;
+                $rel['views']     = AisInfo::where(['uid' => $param['uid']])->count();
+                $rel['like']      = AisInfoFollow::where(['uid'     => $param['uid']])->count();
+                $rel['fans']      = 0;
+                $rel['is_follow'] = 0;
+                $rel['vip_time']  = 0;
+                $rel['reg_time']  = 0;
+                $user = SystemUser::where(['id' => $param['uid']])->find();
+                $rel['face']      = $user->face;
+                $rel['nickname']  = $user->nickname; 
+                $rel['logo']      = $user->face; 
+                $rel['note']      = '未开通城市号';
+                $rel['skin']      = Config::get('upload.upload_relative').'static/ais/skin/2.jpg';
+            }
+        }
+        return enjson(200,$rel);
+    }
+
+
+    /**
+     * 读取信息列表
+     * @param integer 读取ID
+     * @return json
+     */
+    public function me(){
+        $param['page']  = $this->request->param('page/d',1);
+        $param['state'] = $this->request->param('state/d',1);
+        $param['uid']   = $this->request->param('uid/d',0);
+        $param['mid']   = $this->request->param('mid/d',0);
+        $param['sign']  = $this->request->param('sign');
+        $this->apiSign($param);
+        $where = [];
+        $where['member_miniapp_id'] = $this->miniapp_id;
+        $where['is_lock']           = 0;
+        if($param['state']){
+            $order = "is_top desc,id desc";
+            $where['uid'] = $param['uid'];
+        }else{ //热门
+            $uid = AisInfoFollow::where(['uid' => $param['uid']])->column('like_uid');
+            $where['uid'] = $uid;
+            $order = "views desc,sort desc,id desc";
+        }
+        $data = AisInfo::apiLists($where,$order,$this->user);
+        if(empty($data)){
+            return enjson(204,'没有内容');
+        }else{
+            return enjson(200,'成功',$data);
+        }
+    }
+}

+ 119 - 0
application/ais/controller/api/v1/Infopay.php

@@ -0,0 +1,119 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 支付接口
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisInfo;
+use app\ais\model\AisInfoOrder;
+use app\ais\model\MchId;
+use app\ais\model\AisConfig;
+use app\common\facade\WechatPay;
+use filter\Filter;
+
+class Infopay extends Base{
+
+    /**
+     * 初始化当前应用是否登录
+     * @return void
+     */
+    public function initialize() {
+        parent::initialize();
+        $this->isUserAuth();
+    }
+
+    /**
+     * 购买商品
+     */
+    public function index(){
+        if (request()->isPost()) {
+            $param['id']       = $this->request->param('id/d');
+            $param['telphone'] = $this->request->param('telphone/s','');
+            $param['message']  = $this->request->param('message','');
+            $param['ucode']    = $this->request->param('ucode','');
+            $param['fields']   = $this->request->param('fields/s','[]','htmlspecialchars_decode');
+            $this->apiSign($param);
+            $param['fields'] = json_encode(Filter::filter_escape(json_decode($param['fields'],true)));
+            //判断是否已下架
+            $item = AisInfo::where(['member_miniapp_id' => $this->miniapp_id,'id' => $param['id'],'is_lock' => 0])->find();
+            if(empty($item)){
+                return enjson(403,'信息不存在');
+            }
+            //读取订单
+            $order_no = order_no($this->user->invite_code);
+            $amount   = $item->price;
+            //唤醒微信支付参数
+            $payparm = [
+                'openid'     => $this->user->miniapp_uid,
+                'miniapp_id' => $this->miniapp_id,
+                'name'       => $item->mp->title,
+                'order_no'   => $order_no,
+                'total_fee'  => $amount <= 0 ? 1 : $amount * 100,
+                'notify_url' => api(1,'ais/notify/infoOrder',$this->miniapp_id),
+            ];
+            //读取配置
+            if($this->member_miniapp->is_psp){
+                $setting = AisConfig::getConfig($this->miniapp_id);
+                if (empty($setting->mchid)) {
+                    return enjson(403,'服务商模式下,必须配置默认商户号');
+                }
+                $payparm['mchid'] = $setting->mchid;  
+            }
+            $ispay = WechatPay::orderPay($payparm);
+            if ($ispay['code'] == 0) {
+                return enjson(403,$ispay['msg']);
+            }
+            //判断是否新订单
+            $param['member_miniapp_id'] = $this->miniapp_id;
+            $param['uid']               = $this->user->id;
+            $param['info_uid']          = $item->uid;
+            $param['info_id']           = $item->id;
+            $param['phone']             = $param['telphone'];
+            $param['amount']            = $amount;
+            $param['order_no']          = $order_no;
+            $param['message']           = $param['message'];
+            $param['fields']            = $param['fields'];
+            $param['cache']             = $item->toJson();
+            $rel = AisInfoOrder::insertOrder($param,$order_no);
+            if(empty($rel)){
+                return enjson(204,'购买商品失败');
+            }
+            return enjson(200,'成功',$ispay['data']);
+        }
+    }
+
+    /**
+     * 我的订单
+     * @return void
+     */
+    public function order(){
+        $param['active']  = $this->request->param('active/d',0);
+        $param['page']    = $this->request->param('page/d',1);
+        $this->apiSign($param);  
+        $condition['uid']     = $this->user->id;
+        $condition['is_del']  = 0;
+        switch ($param['active']) {
+            case 1:
+                $condition['paid_at'] = 0;
+                break;
+            case 2:
+                $condition['paid_at'] = 1;
+                $condition['status']  = 0;
+                break;
+            case 3:
+                $condition['paid_at'] = 1;
+                $condition['status']  = 1;
+                break;
+        }
+        $lists = AisInfoOrder::where($condition)->field('cache',true)->order('id desc')->paginate(10)->toArray();
+        $data = [];
+        foreach ($lists['data'] as $key => $value) {
+            $data[$key] = $value;
+            $data[$key]['fields'] = json_decode($value['fields'],true);
+        }
+        return enjson(200,'成功',$data);
+    }
+}

+ 376 - 0
application/ais/controller/api/v1/Infosend.php

@@ -0,0 +1,376 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 小程序公共API服务
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisInfoCate;
+use app\ais\model\AisInfo;
+use app\ais\model\AisInfoReply;
+use app\ais\model\AisInfoFollow;
+use app\ais\model\AisConfig;
+use app\ais\model\AisInfoMp;
+use app\ais\model\MchId;
+use app\common\facade\WechatPay;
+use app\common\facade\Upload;
+use app\common\model\SystemUser;
+use app\common\model\SystemMemberSms;
+use think\facade\Config;
+use filter\Filter;
+
+class Infosend extends Base{
+
+   /**
+     * 初始化当前应用是否登录
+     * @return void
+     */
+    public function initialize() {
+        parent::initialize();
+        $this->isUserAuth();
+    }
+
+    /**
+     * 判断是否注册城市号
+     */
+    public function isMp(){
+        $rel = AisInfoMp::where(['uid' => $this->user->id])->count();
+        if($rel){
+            return enjson(200);
+        }
+        return enjson(204);
+    }
+    
+    /**
+     * 判断是否注册城市号
+     */
+    public function getThemes(){
+        $rel = AisInfoCate::where(['member_miniapp_id' => $this->member_miniapp_id])->field('id,name')->select();
+        return enjson(200,$rel);
+    }
+
+    /**
+     * 读取微信API
+     * @param integer 读取ID
+     * @return json
+     */
+    public function getTpl(){
+        $param['id'] = $this->request->param('id/d',0);
+        $this->apiSign($param);
+        $rel = AisInfoCate::cateTpl($param['id']);
+        return enjson(200,'成功',$rel);
+    } 
+
+    /**
+     * 城市号信息
+     */
+    public function getMp(){
+        $param['uid'] = $this->request->param('uid/d',0);
+        $this->apiSign($param);
+        $where = [];
+        $where['uid'] = $param['uid'];
+        $rel = AisInfoMp::where($where)->find();
+        if($rel){
+            if($rel->is_lock){
+                return enjson(403,'城市号不存在');
+            }
+            $rel->views = AisInfo::where(['uid' => $rel->uid])->count();
+            $rel->like  = AisInfoFollow::where(['uid' => $rel->uid])->count();
+            $rel->is_follow =  0;
+            $rel->vip_time = empty($rel->vip_time)?'0':date('Y-m-d',$rel->vip_time);
+            $rel->reg_time = empty($rel->reg_time)?'0':date('Y-m-d',$rel->reg_time);
+            if($this->user){
+                $rel->is_follow = AisInfoFollow::where(['uid' => $this->user->id,'like_uid'=>$rel->uid])->count();
+            }
+            return enjson(200,'成功',$rel);
+        }
+        return enjson(204);
+    }
+
+    /**
+     * 编辑开通城市号和申请认证城市号
+     *
+     * @return void
+     */
+    public function editMp(){
+        $param['logo']      = $this->request->param('logo/s');
+        $param['skin']      = $this->request->param('skin/s');
+        $param['title']     = $this->request->param('title/s');
+        $param['note']      = $this->request->param('note/s');
+        $param['telphone']  = $this->request->param('telphone/s');
+        $param['vip_title'] = $this->request->param('vip_title/s','');
+        $param['vip_about'] = $this->request->param('vip_about/s','');
+        $param['checked']   = $this->request->param('checked/d',0);
+        $this->apiSign($param);
+        $data['title'] = $param['title'];
+        $data['note']  = $param['note'];
+        $rel = AisInfoMp::where(['uid' => $this->user->id])->find();
+        if($rel){
+            if($rel->is_lock){
+                return enjson(403,'城市号已被锁定');
+            }
+            //判断是否修改skin
+            if(!empty($param['skin'])){
+                $rel->skin = $param['skin'];
+            }
+            //判断是否修改logo
+            if(!empty($param['logo'])){
+                $rel->logo = $param['logo'];
+            }
+            if(!$rel->is_apply && !$rel->is_vip){
+                $rel->is_apply  = $param['checked'] ? 1 : 0;
+                $rel->vip_title = $param['vip_title'];
+                $rel->vip_about = $param['vip_about'];
+            }
+            $result = $rel->save();
+        }else{
+            $data['member_miniapp_id'] = $this->miniapp_id;
+            $data['uid']                = $this->user->id;
+            $data['is_apply']           = $param['checked'] ? 1 : 0;
+            $data['is_vip']             = 0;
+            $data['vip_title']          = $param['vip_title'];
+            $data['vip_about']          = $param['vip_about'];
+            $data['reg_time']           = time();
+            $data['vip_time']           = time();
+            $data['fans']               = AisInfoFollow::where(['uid' => $this->user->id])->count();            
+            $data['logo']               = empty($param['logo']) ? $this->user->face: $param['logo'];
+            $data['skin']               = empty($param['skin']) ? Config::get('upload.upload_relative').'static/ais/skin/2.jpg':$param['skin'];
+            $result = AisInfoMp::create($data);
+        }
+        if($result){
+            return enjson(200,'城市号设置成功');
+        }
+        return enjson(403,'设置失败');
+    }
+
+    /**
+     * VIP认证
+     */
+    public function vipAuth(){
+        if(request()->isPost()){
+            $rel = AisInfoMp::where(['uid' => $this->user->id,'is_lock' => 0,'is_vip' => 1])->count();
+            if($rel){
+                return enjson(200,'认证用户',['vip'=>1]);
+            }
+        }
+        return enjson(200,'非认证用户',['vip'=>0]);
+    }
+
+    /**
+     * 商城图片
+     */
+    public function upImg(){
+        if(request()->isPost()){
+            $rel = Upload::index();
+            if($rel['error'] == 0){
+                return enjson(200,'success',$rel['url']);
+            }else{
+                return enjson(204);
+            }
+        }
+    }
+    
+    /**
+     * 发表信息
+     */
+    public function send(){  
+        if(request()->isPost()){
+            $param =  [
+                'content'  => $this->request->param('content/s'),
+                'telphone' => $this->request->param('telphone/s',''),
+                'topday'   => $this->request->param('topday/d',0),
+                'cate_id'  => $this->request->param('cate_id/d',0),
+                'store_id' => $this->request->param('store_id/d',0),
+                'imgs'     => $this->request->param('imgs/s','[]','htmlspecialchars_decode'),
+                'fields'   => $this->request->param('fields/s','[]','htmlspecialchars_decode'),
+                'is_get'   => $this->request->param('is_get/d',0),
+                'price'    => $this->request->param('price/d'),
+            ];
+            $this->apiSign($param);
+            $param['member_miniapp_id'] = $this->miniapp_id;
+            $param['uid']               = $this->user->id;
+            $validate = $this->validate($param,'Info.sendInfo');
+            if(true !== $validate){
+                return json(['code'=>403,'msg'=>$validate]);
+            }
+            $param['images'] = json_encode(Filter::filter_escape(json_decode($param['imgs'],true)));
+            $param['fields'] = json_encode(Filter::filter_escape(json_decode($param['fields'],true)));
+            //置顶
+            $amount = 0;
+            $config = AisConfig::getConfig($this->miniapp_id);
+            if($param['topday'] && !empty($config)){
+                $topday = json_decode($config->info,true);
+                foreach ($topday as $value) {
+                    if($value['day'] == $param['topday']){
+                        $amount = $value['money'];
+                        $param['topday'] = $value['day'];
+                    }
+                }
+            }
+            $param['top_money'] = $amount; //置顶金额
+            $param['order_no']  = order_no($this->user->invite_code);
+            $result = AisInfo::postThemes($param);
+            if($result){
+                if($amount > 0){
+                    $order = [
+                        'openid'     => $this->user['miniapp_uid'],
+                        'miniapp_id' => $this->miniapp_id,
+                        'name'       => '信息置顶',
+                        'order_no'   => $param['order_no'],
+                        'total_fee'  => $amount,
+                        'notify_url' => api(1,'ais/notify/infoSend',$this->miniapp_id)
+                    ];
+                    if($this->member_miniapp->is_psp){
+                        $setting = AisConfig::getConfig($this->miniapp_id);
+                        if (empty($setting->mchid)) {
+                            return enjson(403,'服务商模式下,必须配置默认商户号');
+                        }
+                        $order['mchid'] = $setting->mchid;  
+                    }
+                    $ispay = WechatPay::orderPay($order);;
+                    if($ispay['code'] == 0){
+                        return enjson(403,$ispay['msg']);
+                    }
+                    return enjson(200,'发布成功',$ispay['data']);
+                }
+                return enjson(204,'发布成功');
+            }else{
+                return enjson(403,'发布失败');
+            }
+        }
+    }
+    
+
+    /**
+     * 发布评论
+     */
+    public function postReply(){
+        if(request()->isPost()){
+            $param =  [
+                'content'  => $this->request->param('content/s'),
+                'info_id'  => $this->request->param('info_id/d'),
+                'sign'     => $this->request->param('sign/s',0),
+            ];
+            $this->apiSign($param);
+            $data = [
+                'content'           => $param['content'],
+                'info_id'           => $param['info_id'],
+                'uid'               => $this->user->id,
+                'member_miniapp_id' => $this->miniapp_id,
+            ];
+            $validate = $this->validate($data,'Info.sendReply');
+            if(true !== $validate){
+                return enjson(403,$validate);
+            }
+            $result =  AisInfoReply::postReply($data);
+            if($result){
+                AisInfo::where(['id' => $param['info_id']])->setInc('reply_num',1);
+                return enjson(200,'评论成功');
+            }else{
+                return enjson(403,'评论失败');
+            }
+        }
+    }
+
+
+
+    /**
+     * 点赞
+     **/
+    public function like(){
+        $param['id']   = $this->request->param('id/d',0);
+        $param['sign'] = $this->request->param('sign');
+        $this->apiSign($param);
+        $condition['member_miniapp_id'] = $this->miniapp_id;
+        $condition['id']                = $param['id'];
+        $rel = AisInfo::where($condition)->find();
+        $like_face = json_decode(empty($rel->like_face) ? '[]':$rel->like_face,true);
+        if(count($like_face) < 10){
+            if(!in_array($this->user->face,$like_face)){
+                array_push($like_face,$this->user->face);
+                $rel->like_face = json_encode($like_face);
+            }
+        } 
+        $rel->like = ['inc',1];
+        $rel->save();
+        if(empty($rel)){
+            return enjson(403,'不用重复点赞');
+        }else{
+            return enjson(200);
+        }
+    }
+
+    /**
+     * 评论点赞
+     * @return void
+     */
+    public function replylike(){
+        $param['id']   = $this->request->param('id/d',0);
+        $param['sign'] = $this->request->param('sign');
+        $this->apiSign($param);
+        $condition['member_miniapp_id'] = $this->miniapp_id;
+        $condition['id']                = $param['id'];
+        $rel = AisInfoReply::where($condition)->setInc('like',1);
+        if(empty($rel)){
+            return enjson(403,'不用重复点赞');
+        }else{
+            return enjson(200);
+        }
+    }
+    /**
+     * 关注或取消
+     */
+    public function follow(){
+        $param['uid']   = $this->request->param('uid/d');
+        $param['state'] = $this->request->param('state/d',0);
+        $param['sign']  = $this->request->param('sign');
+        $this->apiSign($param);
+        if($param['uid'] == $this->user->id){
+            return enjson(403,'不用关注自己');
+        }
+        //判断关注用户是否存在
+        $is_user = SystemUser::where(['id' => $param['uid'],'is_lock' => 0,'is_delete' => 0])->find();
+        if(empty($is_user)){
+            return enjson(403,'当前用户已被封号');
+        }
+        //关注
+        $condition['like_uid'] = $param['uid'];
+        $condition['uid']      = $this->user->id;
+        $info = AisInfoFollow::where($condition)->find();
+        if(empty($info)){
+            $follow = AisInfoFollow::where(['uid' => $this->user->id,'like_uid' => 0])->find();
+            if($param['state'] == 1){
+                if(empty($follow)){
+                    $rel  = AisInfoFollow::create(['uid' => $this->user->id,'like_uid' => $param['uid']]);
+                }else{
+                    $follow->like_uid = $param['uid'];
+                    $rel  = $follow->save();
+                }
+            }else{
+                return enjson(403,'关注失败');
+            }
+        }else{
+            if($param['state'] == 0){
+                $info->like_uid = 0;
+                $rel  = $info->save();
+            }
+        }
+        if(empty($rel)){
+            return enjson(403,'关注失败');
+        }else{
+            //增加粉丝
+            $infomp = AisInfoMp::where(['uid' => $param['uid']])->find();
+            if($infomp){
+                if($param['state']){
+                    $infomp->fans = ['inc',1];
+                }else{
+                    $infomp->fans = ['dec',1];
+                }
+                $infomp->save();
+            }
+            return enjson(200,$param['state']?'已关注':'取消关注');
+        }
+    }
+}

+ 324 - 0
application/ais/controller/api/v1/Notify.php

@@ -0,0 +1,324 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 支付回调通知
+ */
+namespace app\ais\controller\api\v1;
+use app\common\facade\WechatPay;
+use app\ais\controller\api\Base;
+use app\ais\model\AisBank;
+use app\ais\model\AisBill;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisOrder;
+use app\ais\model\AisShop;
+use app\ais\model\AisShopCoupon;
+use app\ais\model\AisShopOrder;
+use app\ais\model\AisStoreBill;
+use app\ais\model\AisVip;
+use app\ais\model\AisVipOrder;
+use app\ais\model\AisVipUser;
+use app\ais\model\AisInfo;
+use app\ais\model\AisInfoOrder;
+use app\ais\model\AisConfig;
+use think\facade\Log;
+use filter\Filter;
+use Exception;
+
+class Notify extends Base{
+
+    /**
+     * 微信付款买单
+     * @return void
+     */
+    public function storePay(){
+        try {
+            $response = WechatPay::doPay($this->miniapp_id)->handlePaidNotify(function ($message,$fail) {
+                $result = AisOrder::where(['state' => 0,'order_no' => Filter::filter_escape($message['out_trade_no'])])->find();
+                if (empty($result)) {
+                    return true;
+                }
+                if ($message['return_code'] === 'SUCCESS') {
+                    if ($message['result_code'] === 'SUCCESS') {
+                        $sub_mchid = $message['sub_mch_id'] ?? '';
+                        $ispay = WechatPay::doPay($this->miniapp_id,false,$sub_mchid)->order->queryByOutTradeNumber($result->order_no);
+                        if ($ispay['return_code'] === 'SUCCESS') {
+                            if ($ispay['result_code'] === 'SUCCESS') {
+                                if ($ispay['trade_state'] === 'SUCCESS'){
+                                    //订单状态
+                                    $result->state     = 1;
+                                    $result->paid_time = strtotime($ispay['time_end']);
+                                    $result->paid_no   = $ispay['transaction_id'];
+                                    //收益计算
+                                    $result = AisOrder::income($result,money($ispay['total_fee'] / 100),$ispay['attach']);
+                                    //消费日志
+                                    AisBill::add([
+                                        'member_miniapp_id' => $this->miniapp_id,
+                                        'store_id'          => $result->store_id,
+                                        'money'             => -$result->price,
+                                        'uid'               => $result->uid
+                                    ],'微信支付[消费]');
+                                    AisStoreBill::add([
+                                        'member_miniapp_id' => $this->miniapp_id,
+                                        'store_id'          => $result->store_id,
+                                        'store_chain_id'    => $result->store_chain_id,
+                                        'money'             => $result->real,
+                                        'pay_uid'           => $result->uid
+                                    ],'微信支付[收款]');
+                                    if ($result->coupon_user_id > 0) {
+                                        AisCouponUser::where(['id' => $result->coupon_user_id])->update(['is_end' => 1,'money' => money($result->amount - $result->price),'update_time' => time()]);    //优惠券减少
+                                    }
+                                    $vip_user = AisVipUser::where(['member_miniapp_id' => $this->miniapp_id,'uid' => $result->uid])->find();
+                                    if(empty($vip_user)){
+                                        $vip = AisVip::where(['member_miniapp_id' => $this->miniapp_id,'is_lock' => 0])->order('sort desc')->find();
+                                        if(!empty($vip)){
+                                            AisVipUser::create([
+                                                'update_time'       => time(),
+                                                'is_lock'           => 0,
+                                                'vip_id'            => $vip->id,
+                                                'uid'               => $result->uid,
+                                                'member_miniapp_id' => $this->miniapp_id
+                                            ]);
+                                            AisVipOrder::create([
+                                                'create_time'       => time(),
+                                                'amount'            => 0,
+                                                'vip_id'            => $vip->id,
+                                                'uid'               => $result->uid,
+                                                'member_miniapp_id' => $this->miniapp_id,
+                                                'state'             => $result->state,
+                                                'order_no'          => $result->order_no,
+                                                'paid_time'         => $result->paid_time,
+                                                'paid_no'           => $result->paid_no
+                                            ]);
+                                        }
+                                    }
+                                    //积分增加
+                                    $bank = AisBank::where(['uid' => $result->uid])->find();
+                                    if(empty($bank)){
+                                        $bank = new AisBank;
+                                        $bank->uid = $result->uid;
+                                        $bank->member_miniapp_id = $result->member_miniapp_id;
+                                        $bank->point = 0;
+                                    }
+                                    $bank->point = $bank->point + intval($result->price);
+                                    $bank->save();
+                                    $result->allowField(true)->save();
+                                    AisOrder::subsidy($result);
+                                    return true;
+                                }
+                            }
+                        }
+                    }
+                }
+                return $fail('通信失败,请稍后再通知我');
+            });
+            $response->send();
+        }catch (Exception $e) {
+            $this->error('页面不存在');
+        }
+    }
+
+   /**
+     * 优选下单
+     * @return void
+     */
+    public function shop(){
+        try{
+            $response = WechatPay::doPay($this->miniapp_id)->handlePaidNotify(function ($message,$fail) {
+                $result = AisShopOrder::where(['status'=>0,'paid_at'=>0,'is_del'=>0,'order_no' => Filter::filter_escape($message['out_trade_no'])])->find();
+                if (empty($result)) {
+                    return true;
+                }
+                if ($message['return_code'] === 'SUCCESS') {
+                    if ($message['result_code'] === 'SUCCESS') {
+                        $sub_mchid  = $message['sub_mch_id'] ?? '';
+                        $ispay = WechatPay::doPay($this->miniapp_id,false,$sub_mchid)->order->queryByOutTradeNumber($result->order_no);
+                        if ($ispay['return_code'] === 'SUCCESS') {
+                            if ($ispay['result_code'] === 'SUCCESS') {
+                                if ($ispay['trade_state'] === 'SUCCESS') {
+                                    //修改订单状态和减少库存
+                                    $result->paid_at   = 1;
+                                    $result->paid_time = strtotime($ispay['time_end']);
+                                    $result->paid_no   = $ispay['transaction_id'];
+                                    AisShop::where(['id' => $result->shop_id])->setDec('warehouse_num',1);  //减库存
+                                    //减去所用积分
+                                    if($result['points']){
+                                        $user = AisVipUser::where(['member_miniapp_id'=>$this->miniapp_id,'uid' => $result->user_id,'is_lock' => 0])->find();
+                                        $user->point  = $user->point - $result->points;
+                                        $user->point  = $user->point + intval($result->amount);
+                                        $user->update_time = time();
+                                        $user->save();
+                                    }
+                                    //增加日志
+                                    AisBill::add([
+                                        'miniapp_id' => $this->miniapp_id,
+                                        'store_id'   => $result->store_id,
+                                        'money'      => -$result->amount,
+                                        'uid'        => $result->user_id
+                                    ],'微信支付[购买商品]');
+                                    $result = AisShopOrder::income($result->toArray(),money($ispay['total_fee'] / 100),$ispay['attach']);
+                                    AisStoreBill::add([
+                                        'miniapp_id' => $result->member_miniapp_id,
+                                        'uid'        => $result->user_id,
+                                        'store_id'   => $result->store_id,
+                                        'pay_uid'    => $result->uid,
+                                        'money'      => $result->real
+                                    ],'优选下单结算到商户号');
+                                    //赠送优惠券
+                                    AisCouponUser::addUserCoupon(json_encode(AisShopCoupon::where(['member_miniapp_id'=>$this->miniapp_id,'shop_id' => $result->shop_id])->column('coupon_id')),$result->user_id);
+                                    $result->allowField(true)->save();
+                                    return true;
+                                }
+                            }
+                        }
+                    }
+                }
+                return $fail('通信失败,请稍后再通知我');
+            });
+            $response->send();
+        }catch (Exception $e) {
+            $this->error('页面不存在');
+        }
+    } 
+
+    /**
+     * 发布付费城市号
+     *  @return void
+     */
+    public function infoSend(){
+        try {
+            $response = WechatPay::doPay($this->miniapp_id)->handlePaidNotify(function($message,$fail){
+                $order = AisInfo::where(['paid_at'=>0,'order_no' => Filter::filter_escape($message['out_trade_no'])])->find();
+                if (empty($order)) {
+                    return true;
+                }
+                if ($message['return_code'] === 'SUCCESS') {
+                    if($message['result_code'] === 'SUCCESS'){
+                        $sub_mchid  = $message['sub_mch_id'] ?? '';
+                        $ispay = WechatPay::doPay($this->miniapp_id,false,$sub_mchid)->order->queryByOutTradeNumber($order->order_no);
+                        if ($ispay['return_code'] === 'SUCCESS') {
+                            if ($ispay['result_code'] === 'SUCCESS') {
+                                if ($ispay['trade_state'] === 'SUCCESS') {
+                                    $order->is_top    = 1;
+                                    $order->paid_at   = 1;
+                                    $order->paid_no   = $ispay['transaction_id'];
+                                    $order->paid_time =  strtotime($ispay['time_end']);
+                                    $order->save();
+                                    $vip_user = AisVipUser::where(['member_miniapp_id' => $this->miniapp_id,'uid' => $order->uid])->find();
+                                    if($vip_user){
+                                        //增加积分
+                                        $vip_user->point  = $vip_user->point + intval($order->price);
+                                        $vip_user->update_time = time();
+                                        $vip_user->save();
+                                    }
+                                    return true;
+                                }
+                            }
+                        }
+                    }
+                }
+                return $fail('通信失败,请稍后再通知我');
+            });
+            $response->send();
+        }catch (Exception $e) {
+            $this->error('页面不存在');
+        }
+    }
+
+    /**
+     * 城市号下单
+     * @return void
+     */
+    public function infoOrder(){
+        try {
+            $response = WechatPay::doPay($this->miniapp_id)->handlePaidNotify(function($message,$fail){
+                $order = AisInfoOrder::where(['paid_at'=>0,'order_no' => Filter::filter_escape($message['out_trade_no'])])->find();
+                if (empty($order)) {
+                    return true;
+                }
+                if ($message['return_code'] === 'SUCCESS') {
+                    if($message['result_code'] === 'SUCCESS'){
+                        $sub_mchid  = $message['sub_mch_id'] ?? '';
+                        $ispay = WechatPay::doPay($this->miniapp_id,false,$sub_mchid)->order->queryByOutTradeNumber($order->order_no);
+                        if ($ispay['return_code'] === 'SUCCESS') {
+                            if ($ispay['result_code'] === 'SUCCESS') {
+                                if ($ispay['trade_state'] === 'SUCCESS') {
+                                    //修改订单状态
+                                    $order->paid_at   = 1;
+                                    $order->paid_no   = $ispay['transaction_id'];;
+                                    $order->paid_time = strtotime($ispay['time_end']);
+                                    $order->save();
+                                    //扣除服务费到账
+                                    $setting = AisConfig::getConfig($this->miniapp_id);
+                                    $amount = money($order->amount-(money(abs($order->amount*$setting->charge/100))));
+                                    AisBill::add(['member_miniapp_id' => $this->miniapp_id,'store_id' => 0,'money' => $amount,'uid' => $order->uid,'pay_uid' => $order->uid], '城市号下单');
+                                    AisBill::add(['member_miniapp_id' => $this->miniapp_id,'store_id' => 0,'money' => $amount,'uid' => $order->info_uid,'pay_uid' => $order->uid], '城市号订单');
+                                    $vip_user = AisVipUser::where(['member_miniapp_id' => $this->miniapp_id,'uid' => $order->uid])->find();
+                                    if($vip_user){
+                                        //增加积分
+                                        $vip_user->point  = $vip_user->point + intval($order->amount);
+                                        $vip_user->update_time = time();
+                                        $vip_user->save();
+                                    }
+                                    return true;
+                                }
+                            }
+                        }
+                    }
+                }
+                return $fail('通信失败,请稍后再通知我');
+            });
+            $response->send();
+        }catch (Exception $e) {
+            $this->error('页面不存在');
+        }
+    }
+
+    /**
+     * 开通会员支付回调
+     */
+    public function vipPay(){
+        try {
+            $response = WechatPay::doPay($this->miniapp_id)->handlePaidNotify(function ($message,$fail) {
+                $result = AisVipOrder::where(['state' => 0,'order_no' => Filter::filter_escape($message['out_trade_no'])])->find();
+                if (empty($result)) {
+                    return true;
+                }
+                if ($message['return_code'] === 'SUCCESS') {
+                    if ($message['result_code'] === 'SUCCESS') {
+                        $sub_mchid = $message['sub_mch_id'] ?? '';
+                        $ispay = WechatPay::doPay($this->member_miniapp_id,false,$sub_mchid)->order->queryByOutTradeNumber($result->order_no);
+                        if ($ispay['return_code'] === 'SUCCESS') {
+                            if ($ispay['result_code'] === 'SUCCESS') {
+                                if ($ispay['trade_state'] === 'SUCCESS'){
+                                    //订单状态
+                                    $result->state     = 1;
+                                    $result->paid_time = strtotime($ispay['time_end']);
+                                    $result->paid_no   = $ispay['transaction_id'];
+                                    //收益计算
+                                    AisVipOrder::income($result,money($ispay['total_fee']/100));
+                                    //消费日志
+                                    AisBill::add(['member_miniapp_id' => $this->member_miniapp_id,'store_id' => 0,'money' =>-$result->amount,'uid' => $result->uid],'微信支付[开通会员]');
+                                    //重置并锁定其它级别会员
+                                    AisVipUser::where(['uid' => $result->uid])->update(['is_lock' => 1]);
+                                    //新增开通当前会员
+                                    AisVipUser::create(['member_miniapp_id' => $this->member_miniapp_id,'uid' => $result->uid,'vip_id' => $result->vip_id,'is_lock' => 0,'update_time' => time()]);
+                                    AisBank::points($this->member_miniapp_id,$result->uid,$result->amount);
+                                    //领取的优惠券
+                                    AisCouponUser::addUserCoupon($result->coupon_ids,$result->uid);
+                                    $result->allowField(true)->save();
+                                    return 'true';
+                                }
+                            }
+                        }
+                    }
+                }
+                return $fail('通信失败,请稍后再通知我');
+            });
+            $response->send();
+        }catch (Exception $e) {
+            $this->error('页面不存在');
+        }
+    }
+}

+ 81 - 0
application/ais/controller/api/v1/Pay.php

@@ -0,0 +1,81 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 个人信息
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisBill;
+use app\ais\model\AisBank;
+use app\ais\model\AisBankCash;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisConfig;
+use app\ais\model\AisVip;
+use app\ais\model\AisVipUser;
+use app\ais\model\AisStore;
+use app\ais\model\AisVipOrder;
+use app\common\facade\WechatPay;
+use app\common\model\SystemUserLevel;
+use think\helper\Time;
+
+class Pay extends Base{
+ 
+    /**
+     * 微信支付开通会员
+     * @param string $no
+     * @return void
+     */
+    public function regVip(){
+        if (request()->isPost()) {
+            $param['vip_id'] = $this->request->param('vip_id/d');
+            $this->apiSign($param);
+            $vip = AisVip::where(['member_miniapp_id' => $this->member_miniapp_id,'id' => $param['vip_id']])->find();
+            if(empty($vip)){
+                return enjson(403,'未找到相关会员等级');
+            }
+            //用户VIP
+            $vipUser = AisVipUser::where(['uid' => $this->user->id,'vip_id' => $vip->id])->find();
+            if($vipUser){
+                return enjson(403,'已开通当前会员');
+            }
+            //创建订单
+            $order_no = order_no($this->user->invite_code);
+            //唤醒微信支付参数
+            $payparm = [
+                'openid'     => $this->user->miniapp_uid,
+                'miniapp_id' => $this->member_miniapp_id,
+                'name'       => $vip->name,
+                'order_no'   => $order_no,
+                'total_fee'  => $vip->price * 100,
+                'notify_url' => api(1,'ais/notify/vippay',$this->miniapp_id),
+            ];
+            //读取配置
+            if($this->member_miniapp->is_psp){
+                $setting = AisConfig::getConfig($this->miniapp_id);
+                if (empty($setting->mchid)) {
+                    return enjson(403,'服务商模式下,必须配置默认商户号');
+                }
+                $payparm['mchid'] = $setting->mchid;  
+            }
+            $ispay = WechatPay::orderPay($payparm);
+            if($ispay['code'] == 0){
+                return enjson(403,$ispay['msg']);
+            }
+            //添加订单记录
+            $data['order_no']          = $order_no;
+            $data['uid']               = $this->user->id;
+            $data['member_miniapp_id'] = $this->member_miniapp_id;
+            $data['vip_id']            = $vip->id;
+            $data['amount']            = $vip->price;    //实际金额
+            $data['state']             = 0;
+            $data['create_time']       = time();
+            $rel = AisVipOrder::create($data);
+            if(!$rel){
+                return enjson(403,'订单创建失败');
+            }
+            return enjson(200,$ispay['data']);
+        }
+    }
+}

+ 40 - 0
application/ais/controller/api/v1/Ranking.php

@@ -0,0 +1,40 @@
+<?php
+/**
+ * 各种排行榜
+ */
+namespace app\ais\controller\api\v1;
+use app\common\model\SystemUser;
+use app\ais\controller\api\Base;
+use app\ais\model\AisAdwords;
+use think\helper\Time;
+
+class Ranking extends Base{
+
+
+    //省钱榜冠军
+    public function topfirst(){
+        $this->apiSign();
+        list($start, $end) = Time::lastMonth();
+        $condition[] = ['u.update_time','>=',$start];
+        $condition[] = ['u.update_time','<=',$end];
+        $list = SystemUser::alias('c')->where(['c.member_miniapp_id' => $this->miniapp_id])->join('AisCouponUser u', 'c.id = u.uid')->where(['u.member_miniapp_id' => $this->miniapp_id,'is_end' => 1])->where('money','<>',null)->where($condition)
+            ->field('c.face,c.nickname,sum(money) as save')->group('u.uid')->order('money desc,c.create_time desc')->find();
+        if (empty($list)) {
+            return enjson(204,'没有数据');
+        }
+        $list->month = date('n',$start);
+        return enjson(200,$list);
+    }
+    
+    //省钱榜
+    public function topMoney(){
+        $param['page'] = $this->request->param('page/d',1);
+        $this->apiSign($param);
+        $list = SystemUser::alias('c')->where(['c.member_miniapp_id' => $this->miniapp_id])->join('AisCouponUser u', 'c.id = u.uid')->where(['u.member_miniapp_id' => $this->miniapp_id,'is_end' => 1])->where('money','<>',null)
+            ->field('c.face,c.nickname,sum(money) as save')->group('u.uid')->order('money desc,c.create_time desc')->page($param['page'],10)->select();
+        if ($list->isEmpty()) {
+            return enjson(204,'没有数据');
+        }
+        return enjson(200,$list);
+    }
+}

+ 241 - 0
application/ais/controller/api/v1/Shop.php

@@ -0,0 +1,241 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 商城小程序公共API服务
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisCity;
+use app\ais\model\AisShop;
+use app\ais\model\AisShopCate;
+use app\ais\model\AisShopOrder;
+use app\ais\model\AisStore;
+use app\common\model\SystemUser;
+use util\Util;
+
+class Shop extends Base{
+
+    protected $store_ids;
+
+    /**
+     * 初始化API并读取城市或你的经纬度
+     * @return void
+     */
+    public function initialize() {
+        parent::initialize();
+        $citycode = $this->request->param('citycode/d',0);
+        if($citycode){
+            $this->store_ids = AisStore::whereIn('citycode', AisCity::whereIn('parent_id', AisCity::where(['code' => $citycode])->column('parent_id'))->column('code'))->column('id');
+        }
+    }
+    /**
+     * 读取单个商品信息
+     * @param integer $id 商品ID
+     * @return void
+     */
+    public function item(){
+        $param['id'] = $this->request->param('id/d',0);
+        $this->apiSign($param);
+        $item = AisShop::with(['store'	=> function($query) {
+            $query->field('id,img,create_time,tags,name,address,longitude,latitude');
+        },'coupon' => function($query) {
+            $query->field('id,types,discount,price,amount');
+        }])->where(['is_sale'=>1,'id' => $param['id'],'member_miniapp_id' => $this->miniapp_id])
+        ->field('id,store_id,category_id,warehouse_num,warehouse_sellnum,share_price,share_vip_price,vip_price,like,group_title,group_img,group_note,coupon_id,name,title,img,imgs,points_price,sell_price,market_price,end_time,content,notice,keyword')
+        ->find();
+        if(empty($item)){
+            return enjson(204);
+        }
+        $item->like += 1;
+        $item->save();
+        //产品信息
+        $item->content      = str_replace('<img', '<img class="img" style="max-width:100%;height:auto"',dehtml($item->content));
+        $item->notice       = str_replace('<img', '<img class="img" style="max-width:100%;height:auto"',dehtml($item->notice));
+        $item->market_price = money($item->market_price);
+        $item->sell_price   = money($item->sell_price);
+        $item->coupon_price = AisShop::couponPrice($item->sell_price,$item->coupon);
+        $item->points_price = money($item->points_price);
+        $item->share_price  = ($item->sell_price-$item->vip_price-$item->points_price-$item->coupon_price)*$item->share_price/100;
+        $item->share_vip_price  = ($item->sell_price-$item->vip_price-$item->points_price-$item->coupon_price)*$item->share_vip_price/100;
+        $item->warehouse_sellnum = $item->warehouse_sellnum + AisShopOrder::where(['shop_id' => $item->id,'paid_at'=>1])->count();
+        $item->end_time          = ($item->warehouse_num ? (($item->end_time + 60 * 10) - time()) * 1000 : 0) ?: 0;
+        //店铺信息
+        $store = [];
+        if($item->store_id > 0){
+            $store['img']         = $item->store->img;
+            $store['name']        = $item->store->name; 
+            $store['address']     = $item->store->address; 
+        }
+        $item['store'] = $store;
+        return enjson(200,$item);
+    }
+
+   /**
+     * 首页显示
+     */
+    public function index(){
+        $this->apiSign(['citycode' => $this->request->param('citycode')]);
+        $where['member_miniapp_id'] = $this->miniapp_id;
+        $where['types']             = 1;
+        $where['is_sale']           = 1;
+        $where['is_del']            = 0;
+        if ($this->store_ids) {
+            $where['store_id'] = $this->store_ids;
+        }
+        $rel = AisShop::where($where)->field('id,category_id,name,title,img,share_price,points_price,warehouse_num,sell_price,market_price,vip_price,coupon_id,end_time,update_time')->limit(8)->select();
+        $data = [];
+        foreach ($rel as $key => $value) {
+            $data[$key] = $value;
+            $data[$key]['coupon_price'] = AisShop::couponPrice($value->sell_price,$value->coupon);
+            $data[$key]['img']          = $value->img;
+            $data[$key]['tags']         = time()-$value->update_time <= 86400 ? '上新':'';
+            $end_time                   = $value['warehouse_num'] ? (($value->end_time + 60 * 10) - time()) * 1000 : 0;
+            $data[$key]['end_time']     = $end_time ?: 0;
+        }
+        return enjson(200,$data);
+    }
+
+   /**
+     * 首页推荐专题
+     */
+    public function special(){
+        $this->apiSign(['citycode' => $this->request->param('citycode')]);
+        $cate = AisShopCate::where(['member_miniapp_id' => $this->miniapp_id,'types' => 1])->field('id,title,show_type,content,picture')->select();
+        if(empty($cate)){
+            return enjson(204);
+        }
+        $where['member_miniapp_id'] = $this->miniapp_id;
+        $where['types']             = 2;
+        $where['is_sale']           = 1;
+        $where['is_del']            = 0;
+        $where['category_id']       = array_column($cate->toArray(),'id');;
+        if ($this->store_ids){
+            $where['store_id'] = $this->store_ids;
+        }
+        $rel = AisShop::where($where)->field('id,category_id,name,title,img,share_price,points_price,warehouse_num,sell_price,market_price,vip_price,coupon_id,end_time,update_time')->limit(6)->select();
+        $shop = [];
+        foreach ($rel as $key => $value) {
+            $shop[$key] = $value;
+            $shop[$key]['coupon_price'] = AisShop::couponPrice($value->sell_price,$value->coupon);
+            $shop[$key]['img']          = $value->img;
+            $shop[$key]['tags']         = time()-$value->update_time <= 86400 ? '上新':'';
+            $end_time                   = $value['warehouse_num'] ? (($value->end_time + 60 * 10) - time()) * 1000 : 0;
+            $shop[$key]['end_time']     = $end_time ?: 0;
+        }
+        $goods = dataGroup($shop,'category_id');
+        $data = [];
+        foreach ($cate as $key => $value) {
+            if(!empty($goods[$value->id])){
+                $data[$key] = $value;
+                $data[$key]['goods'] = $goods[$value->id];
+            }
+        }
+        return enjson(200,$data);
+    }
+   
+   /**
+     * 专栏产品展示
+     */
+    public function lists(){
+        $param['id']       = $this->request->param('id/d');
+        $param['page']     = $this->request->param('page/d',0);
+        $param['citycode'] = $this->request->param('citycode/d',0);
+        $this->apiSign($param);
+        if ($this->store_ids){
+            $where['store_id'] = $this->store_ids;
+        }
+        $cate = [];
+        if($param['page'] == 1){
+            $cate = AisShopCate::where(['member_miniapp_id' => $this->miniapp_id,'id' => $param['id']])->field('id,title,content,picture')->find();
+            if(empty($cate)){
+                return enjson(403);
+            }
+        }
+        $rel = AisShop::with(['store' => function($query) {
+            $query->field('name,id,address,longitude,latitude');
+        }])->where(['is_sale' => 1,'is_del' => 0,'category_id' => $param['id']])->field('id,share_price,store_id,category_id,name,title,img,warehouse_num,points_price,sell_price,market_price,vip_price,coupon_id,end_time,update_time')->page($param['page'],10)->select();
+        if($rel->isEmpty()){
+            return enjson(204);
+        }
+        $shop = [];
+        foreach ($rel as $key => $value) {
+            $shop[$key] = $value;
+            $shop[$key]['coupon_price'] = AisShop::couponPrice($value->sell_price,$value->coupon);
+            $shop[$key]['img']          = $value->img;
+            $shop[$key]['tags']         = time()-$value->update_time <= 86400 ? '上新':'';
+            $end_time                   = $value['warehouse_num'] ? (($value->end_time + 60 * 10) - time()) * 1000 : 0;
+            $shop[$key]['end_time']     = $end_time ?: 0;
+            $shop[$key]['store']        = $value->store;
+        }
+        return enjson(200,'成功',['shop' => $shop,'special' => $cate]);
+    }
+
+    /**
+     * 查询指定商家的商品
+     */
+    public function store(){
+        $param['page']    = $this->request->param('page/d',1);
+        $param['store_id']= $this->request->param('store_id/d',0);
+        $param['types']   = $this->request->param('types/d');
+        $param['keyword'] = $this->request->param('keyword');
+        $this->apiSign($param);
+        $where = [];
+        $where['is_del']  = 0;
+        $where['is_sale'] = 1;
+        $where['member_miniapp_id'] = $this->miniapp_id;
+        if($param['types']){
+            $where['types'] = $param['types'];
+        }
+        if($param['store_id']){
+            $where['store_id'] = $param['store_id'];
+        }
+        $rel = AisShop::where($where)->withSearch(['name'],['name' => $param['keyword']])->field('id,share_price,store_id,category_id,name,title,img,warehouse_num,points_price,sell_price,market_price,vip_price,coupon_id,end_time,update_time')->page($param['page'],10)->select();
+        if($rel->isEmpty()){
+            return enjson(204);
+        }
+        $data = [];
+        foreach ($rel as $key => $value) {
+            $data[$key] = $value;
+            $data[$key]['coupon_price'] = AisShop::couponPrice($value->sell_price,$value->coupon);
+            $data[$key]['img']          = $value->img;
+            $end_time                   = $value['warehouse_num'] ? (($value->end_time + 60 * 10) - time()) * 1000 : 0;
+            $data[$key]['end_time']     = $end_time ?: 0;
+        }
+        return enjson(200,$data);
+    }
+
+    /**
+     * 单个商品下单用户列表
+     */
+    public function orderUser(){
+        $param['id'] = $this->request->param('id/d',0);
+        $this->apiSign($param);
+        $order = AisShopOrder::where(['shop_id' => $param['id']])->limit(6)->select();
+        $data = [];
+        if($order->isEmpty()){
+            $user = SystemUser::where(['member_miniapp_id' => $this->miniapp_id])->field('face')->limit(6)->select()->toArray();
+            $data = array_column($user,'face');
+        }else{
+            foreach ($order as $key => $value) {
+                $data[$key] = $value->user->face;
+            }
+        }
+        $new_order['id']          = 0;
+        $new_order['create_time'] = 0;
+        if($this->user){
+            $info = AisShopOrder::where(['uid'=> $this->user->id,'shop_id' =>$param['id'],'paid_at' => 0,'is_del' => 0])->field('id,create_time')->find();
+            if($info){
+                $create_time = (($info->create_time + 60 * 10) - time()) * 1000;
+                if($create_time < 0){
+                    $info->is_del = 1;
+                    $info->save();
+                }
+                $new_order['id']          = $info->id;
+                $new_order['create_time'] = $create_time;
+            }
+        }
+        return enjson(200,['share' => $data,'order' => $new_order]);
+    }
+}

+ 154 - 0
application/ais/controller/api/v1/Shoporder.php

@@ -0,0 +1,154 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 订单管理
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisShopOrder;
+use app\ais\model\AisBank;
+use app\ais\model\AisShop;
+use app\ais\model\AisConfig;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisVipUser;
+use app\common\model\SystemUser;
+use app\common\facade\WechatPay;
+
+class Shoporder extends Base{
+
+    /**
+     * 初始化当前应用是否登录
+     * @return void
+     */
+    public function initialize() {
+        parent::initialize();
+        $this->isUserAuth();
+    }
+
+    /**
+     * @param int $store_id
+     * 店铺订单
+     */
+    public function index(){
+        $param['active']  = $this->request->param('active/d',0);
+        $param['page']    = $this->request->param('page/d',1);
+        $this->apiSign($param);
+        $condition['uid']    = $this->user->id;
+        $condition['is_del'] = 0;
+        switch ($param['active']) {
+            case 1:
+                $condition['paid_at'] = 0;
+                break;
+            case 2:
+                $condition['paid_at'] = 1;
+                $condition['status']  = 0;
+                break;
+            case 3:
+                $condition['paid_at'] = 1;
+                $condition['status']  = 1;
+                break;
+        }
+        $order = AisShopOrder::with(['store' => function($query) {
+            $query->field('name,address,id');
+        }])->field('store_id,id,order_no,paid_at,paid_time,phone,points,message,shop_id,status,shop_cache,amount,create_time,is_del')->where($condition)->page($param['page'],10)->select();
+        if($order->isEmpty()){
+            return enjson(204);
+        }    
+        $data = [];
+        $ids  = [];
+        foreach ($order as $key => $value) {
+            $data[$key] = $value;
+            $data[$key]['status_text'] = $value['statu'];
+            $data[$key]['end_paytime'] = 0;
+            if($value['paid_at'] == 0){
+                $data[$key]['end_paytime'] = (($value['create_time'] + 60 * 10) - time()) * 1000;
+            }
+            if($value['paid_at'] == 0 && $data[$key]['end_paytime'] < 0){
+                $ids[] = $value['id'];
+                unset($data[$key]);
+            }
+        }
+        if(!empty($ids)){ //过期了更改了状态
+            AisShopOrder::where(['id' => $ids])->update(['is_del' => 1]);
+        }
+        if(empty($data)){
+            return enjson(204);
+        }
+        return enjson(200,array_values($data));
+    }
+
+      
+    /**
+     * @param int $store_id
+     */
+    public function views(){
+        $param['id'] = $this->request->param('id/d',0);
+        $this->apiSign($param);
+        $condition['uid'] = $this->user->id;
+        $condition['id']  = $param['id'];
+        $order = AisShopOrder::with(['store'	=> function($query) {
+            $query->field('name,address,id,longitude,latitude');
+        }])->field('store_id,id,order_no,paid_at,paid_time,phone,points,message,shop_id,status,shop_cache,amount,create_time,is_del,thrifty')->where($condition)->find();
+        if(empty($order)){
+            return enjson(204);
+        }
+        $order->end_paytime = 0;
+        if(!$order->paid_at){
+            $order->end_paytime = (($order->create_time + 60 * 10) - time()) * 1000;
+        }
+        if($order->paid_at == 0 && $order->end_paytime < 0){
+            $order->is_del = 1;
+            $order->save();
+        }
+        $shop_cache = $order->shop_cache;
+        $shop_cache['notice'] = str_replace('<img', '<img class="img" style="max-width:100%;height:auto"',dehtml($shop_cache['notice']));
+        $order->shop_cache  = $shop_cache;
+        $order->paid_time   = date('Y-m-d H:i:s',$order->paid_time);
+        $order->create_time = date('Y-m-d H:i:s',$order->create_time);
+        return enjson(200,$order);
+    }
+
+    /**
+     * @param int $order_id
+     * @return \think\response\Json
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * 获取核心订单
+     */
+    public function orderVer(){
+        $param['id'] = $this->request->param('id/d',0);
+        $this->apiSign($param);
+        $condition['id']      = $param['id'];
+        $condition['paid_at'] = 1;
+        $condition['status']  = 0;
+        $condition['is_del']  = 0;
+        $info = AisShopOrder::with(['store'	=> function($query) {
+            $query->field('name,address,id,longitude,latitude');
+        }])->where($condition)->field('store_id,uid,id,order_no,paid_at,paid_time,phone,points,message,shop_id,status,shop_cache,amount,create_time,is_del')->find();
+        if(empty($info)){
+            return enjson(303,'订单不存在',['url' => '/pages/index']);
+        }
+        $uid =  array_flip(array_column($info->storeWorker->toArray(),'uid'));
+        if(empty($uid)){
+            return enjson(303,'商家没有设置核销员',['url' => '/pages/index']);
+        }
+        if (!isset($uid[$this->user->id])){
+            return enjson(303,'你无权限核销订单',['url' => '/pages/index']);
+        }
+        if(request()->isPost()){
+            $info->status = 1;
+            $info->save();
+            return enjson(303,'订单成功核销',['url' => '/pages/user/index']);
+        }else{
+            $shop_cache = $info->shop_cache;
+            $shop_cache['notice'] = str_replace('<img', '<img class="img" style="max-width:100%;height:auto"',dehtml($shop_cache['notice']));
+            $info->shop_cache  = $shop_cache;
+            $info->paid_time   = date('Y-m-d H:i:s',$info->paid_time);
+            $info->create_time = date('Y-m-d H:i:s',$info->create_time);
+            return enjson(200,'成功',$info);
+        }
+    }
+}

+ 142 - 0
application/ais/controller/api/v1/Shoppay.php

@@ -0,0 +1,142 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 支付接口
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisShopOrder;
+use app\ais\model\AisBank;
+use app\ais\model\AisShop;
+use app\ais\model\AisConfig;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisVipUser;
+use app\common\model\SystemUser;
+use app\common\facade\WechatPay;
+use app\common\model\SystemUserLevel;
+
+class Shoppay extends Base{
+
+    /**
+     * 初始化当前应用是否登录
+     * @return void
+     */
+    public function initialize() {
+        parent::initialize();
+        $this->isUserAuth();
+    }
+
+
+    /**
+     * 读取订单并支付
+     * @param integer $id 商品ID
+     * @return void
+     */
+    public function index(){
+        $param['id'] = $this->request->param('id/d',0);
+        $this->apiSign($param);
+        //查找商品
+        $item = AisShop::field('id,store_id,coupon_id,name,title,img,points_price,sell_price,vip_price,market_price,end_time')
+                ->where(['is_sale'=>1,'id' => $param['id'],'member_miniapp_id' => $this->member_miniapp_id])->find();
+        if(empty($item)){
+            return enjson(403,'没有内容');
+        }
+        return enjson(200,AisShop::userPayPrice($item,$this->user->id));
+    }
+
+    /**
+     * 下单发起支付或重新在支付
+     */
+    public function payment(){
+        if (request()->isPost()) {
+            $param['id']       = $this->request->param('id/d');
+            $param['telphone'] = $this->request->param('telphone/s');
+            $param['message']  = $this->request->param('message','');
+            $param['ucode']    = $this->request->param('ucode','');
+            $this->apiSign($param);
+            $item = AisShop::where(['is_sale'=>1,'id' => $param['id'],'member_miniapp_id' => $this->member_miniapp_id])->find();
+            if(empty($item)){
+                return enjson(403,'商品已经下架');
+            }
+            if($item->warehouse_num <= 0){
+                return enjson(403,'商品已售完');
+            }
+            $is_rest_payment = true;
+            //读取订单
+            $shop_order = AisShopOrder::where(['member_miniapp_id' => $this->member_miniapp_id,'uid' =>$this->user->id,'shop_id' => $item->id,'is_del' => 0])->find();
+            $order_no   = order_no($this->user->invite_code);
+            if(empty($shop_order)){
+                $validate = $this->validate($param,'Dopay.shop');
+                if (true !== $validate) {
+                    return enjson(403,$validate);
+                }
+                $sell_price  = $item->sell_price;
+            }else{
+                if($shop_order->paid_at == 1 && $shop_order->status == 0){
+                    return enjson(403,'本商品订单未核销,请先去商家核销');
+                }
+                if($shop_order->sell_price < $item->sell_price){
+                    $shop_order->is_del = 1; //设置删除
+                    return enjson(403,'订单已失效,请重新下单');
+                }else{
+                    $shop_order->order_no = $order_no;
+                }
+                $shop_order->save();
+                $sell_price  = $shop_order->amount;
+                $is_rest_payment = false;
+            }
+            //价格计算器
+            $item = AisShop::userPayPrice($item,$this->user->id);
+            //唤醒微信支付参数
+            $payparm = [
+                'openid'     => $this->user->miniapp_uid,
+                'miniapp_id' => $this->member_miniapp_id,
+                'name'       => $item->name,
+                'order_no'   => $order_no,
+                'attach'     => 'N',
+                'total_fee'  => $item->amount <= 0 ? 1 : $item->amount * 100,
+                'notify_url' => api(1, 'ais/notify/shop', $this->miniapp_id),
+            ];
+            if($this->member_miniapp->is_psp){
+                if(empty($item->store->mch_id)){
+                    $setting = AisConfig::getConfig($this->miniapp_id);
+                    if (empty($setting->mchid)) {
+                        return enjson(403,'服务商模式下,必须配置默认商户号');
+                    }
+                    $payparm['mchid'] = $setting->mchid;
+                }else{
+                    $level = SystemUserLevel::where(['user_id' => $this->user->id,'level' => 1])->find();
+                    if(!empty($level) && $level->parent_id != $item->store->manage_uid){
+                        $payparm['profit_sharing'] = 'Y';
+                        $payparm['attach'] = 'Y';
+                    }
+                    if(!empty($param['ucode'])){
+                        $payparm['profit_sharing'] = 'Y';
+                        $payparm['attach'] = 'Y';
+                    }
+                    $payparm['mchid']  = $item->store->mch_id;
+                }
+            }
+            $ispay = WechatPay::orderPay($payparm);
+            if ($ispay['code'] == 0) {
+                return enjson(403,$ispay['msg']);
+            }
+            //判断是否创建订单
+            if($is_rest_payment){
+                $param['uid']               = $this->user->id;
+                $param['member_miniapp_id'] = $this->member_miniapp_id;
+                $param['store_id']          = $item->store_id;
+                $param['sell_price']        = $item->sell_price;
+                $param['amount']            = $item->amount;
+                $param['points']            = $item->user_point;
+                $param['thrifty']           = $item->thrifty;
+                $param['share_uid']         = SystemUser::isInvite($param['ucode']);
+                $param['shop_cache']        = $item->toArray();
+                AisShopOrder::createOrder($param,$order_no);
+            }
+            return enjson(200,$ispay['data']);
+        }
+    }
+}

+ 144 - 0
application/ais/controller/api/v1/Store.php

@@ -0,0 +1,144 @@
+<?php
+/**
+ * 店铺API
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisStore;
+use app\ais\model\AisStoreCate;
+use app\ais\model\AisCoupon;
+use app\ais\model\AisShop;
+use think\helper\Time;
+use filter\Filter;
+
+class Store extends Base{
+
+    
+    /**
+     * 读取行业信息列表  v4.1
+     * @param integer 读取ID
+     * @return json
+     */
+    public function cate(){
+        $param['cate_id'] = $this->request->param('cate_id/d',0);
+        $this->apiSign($param);
+        $where['parent_id']         = $param['cate_id'];
+        $where['member_miniapp_id'] = $this->miniapp_id;
+        $data = AisStoreCate::where($where)->field('id,name,picture,title')->order('sort desc,id desc')->select();
+        if($data->isEmpty()){
+            return enjson(204);
+        }
+        return enjson(200,$data);
+    }
+
+    /**
+     * 店铺列表
+     */
+    public function index(){
+        $param['keyword']  = $this->request->param('keyword');
+        $param['cate_id']  = $this->request->param('cate_id',0);
+        $param['cate_sid'] = $this->request->param('cate_sid/d',0);
+        $param['page']     = $this->request->param('page/d',0);
+        $param['citycode'] = $this->request->param('citycode/d');
+        $this->apiSign($param);
+        $where = [];
+        if($param['cate_sid']){
+            $where[] = ['cate_sid','=',$param['cate_sid']];
+        }
+        if($param['cate_id']){
+            $where[] = ['cate_id','=',$param['cate_id']];
+        }
+        $where[] = ['member_miniapp_id','=',$this->miniapp_id];
+        $where[] = ['is_lock','=',0];
+        if($param['citycode']){
+            $where[] = ['citycode','=',$param['citycode']];
+        }
+        $rel = AisStore::where($where)->withSearch(['name'],['name' => $param['keyword']])
+            ->field('id,name,longitude,latitude,img,telphone,address,tags,is_top')
+            ->order('is_top desc,sort desc,id desc')->page($param['page'],10)->select();
+        if($rel->isEmpty()){
+            return enjson(204,'没有内容');
+        }
+        return enjson(200,$rel);
+    }
+   
+    /**
+     * 店铺首页产品
+     */
+    public function read(){
+        $param['store_id'] = $this->request->param('store_id/d',0);
+        $this->apiSign($param);
+        $info = AisStore::with(['chain'])->where(['id' => $param['store_id'],'is_lock' => 0])->field('id,name,longitude,latitude,img,telphone,address,tags,is_top,likes')->find();
+        if(empty($info)){
+            return enjson(404);
+        }
+        return enjson(200,$info);
+    }
+
+    /**
+     * 点赞
+     **/
+    public function like(){
+        $this->isUserAuth();
+        $param['store_id']   = $this->request->param('store_id/d',0);
+        $this->apiSign($param);
+        $rel = AisStore::where(['id' => $param['store_id']])->setInc('likes',1);
+        if(empty($rel)){
+            return enjson(204);
+        }
+        return enjson(200);
+    }
+
+     /**
+     * 申请入驻商家
+     */
+    public function reg(){
+        $this->isUserAuth();
+        if (request()->isPost()) {
+            $param = [
+                'name'      => $this->request->param('name/s'),
+                'address'   => $this->request->param('address/s'),
+                'telphone'  => $this->request->param('telphone/s'),
+                'latitude'  => $this->request->param('latitude/s'),
+                'longitude' => $this->request->param('longitude/s'),
+                'charge'    => $this->request->param('charge/d',10),
+                'citypath'  => $this->request->param('citypath/s','[]','htmlspecialchars_decode'),
+                'imgs'      => $this->request->param('imgs/s','[]','htmlspecialchars_decode'),
+            ];
+            $this->apiSign($param);
+            $validate = $this->validate($param,'Store.reg');
+            if(true !== $validate){
+                return enjson(403,$validate);
+            }
+            //判断是否入驻
+            $store = AisStore::manageStore($this->user->id);
+            if($store){
+                return enjson(403,'不需要重复入驻');
+            }
+            //所在城市
+            $citypath = Filter::filter_escape(json_decode($param['citypath'],true));
+            if(empty($citypath)){
+                return enjson(403,'城市选择失败,请重新选择');
+            }
+            $imgs  = Filter::filter_escape(json_decode($param['imgs'],true));
+            if(empty($imgs)){
+                return enjson(403,'请重新选择Logo');
+            }
+            $data['citycode']          = $citypath[2]['code'];
+            $data['citypath']          = ['province' => $citypath[0]['code'],'city' => $citypath[1]['code'],'district' => $citypath[2]['code']];
+            $data['member_miniapp_id'] = $this->miniapp_id;
+            $data['manage_uid']        = $this->user->id;
+            $data['name']              = $param['name'];
+            $data['telphone']          = $param['telphone'];
+            $data['address']           = $param['address'];
+            $data['latitude']          = $param['latitude'];
+            $data['longitude']         = $param['longitude'];
+            $data['img']               = $imgs[0];
+            $data['charge']            = $param['charge'];;
+            if(AisStore::create($data)){
+                return enjson(200,"成功,下一步申请微信商户号");
+            }
+            return enjson(403,"提交失败");
+        }
+    }
+}

+ 208 - 0
application/ais/controller/api/v1/Storepay.php

@@ -0,0 +1,208 @@
+<?php
+/**
+ * 买单付款
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisOrder;
+use app\ais\model\AisStore;
+use app\ais\model\AisCoupon;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisConfig;
+use app\common\facade\WechatPay;
+use app\common\model\SystemUserLevel;
+use think\Db;
+
+class Storepay extends Base{
+
+    protected $config;
+
+    /**
+     * 初始化当前应用管理员是不是联盟城市账户
+     * @return void
+     */
+    public function initialize() {
+        parent::initialize();
+        $this->isUserAuth();
+        $this->config = AisConfig::getConfig($this->member_miniapp_id);
+    }
+
+    /**
+    * 读取买单商家信息和优惠券
+    * @return void
+    */
+    public function index(){
+        $param['store_id']  = $this->request->param('store_id/d');
+        $param['chain_id']  = $this->request->param('chain_id/d');
+        $this->apiSign($param);
+        if(empty($param['store_id'])){
+            return enjson(404,'为找到付款好店');
+        }
+        $store = AisStore::where(['is_lock' => 0,'id' => $param['store_id']])->field('id,name')->find();
+        if(empty($store)){
+            return enjson(303,'未找到付款好店',['url' =>'/pages/index']);
+        }
+        if(!empty($param['chain_id'])){
+            $store = $store->chain()->where('id',$param['chain_id'])->field('id,title,store_id')->find();
+            if(empty($store)){
+                return enjson(303,'未找到付款分店',['url' =>'/pages/index']);
+            }
+            $store->name     = $store->title;
+            $store->chain_id = $store->id;
+            $store->id       = $store->store_id;
+        }
+        $is_get_coupon = 0;
+        if(empty($this->config->is_pay_open_coupon)){
+            $condition[] = ['member_miniapp_id','=',$this->miniapp_id];
+            $condition[] = ['uid','=',$this->user->id];
+            $condition[] = ['is_end','=',0];
+            $condition[] = ['money','=',0];
+            $condition[] = ['store_id','=',$param['store_id']];
+            $coupon = AisCouponUser::where($condition)->field('id,name,tips,howmuch,store_id,price,types,coupon_id,discount,create_time')->order('create_time desc')->select();
+            foreach ($coupon as $key => $value){
+                $coupon[$key]->is_get_coupon = 0;
+                $coupon[$key]->end_time      = $this->config->coupon_longtime * 60 * 60;
+            }
+        }else{
+            $coupon = AisCoupon::where(['member_miniapp_id' => $this->miniapp_id,'store_id' => $param['store_id'],'is_lock' => 0,'is_end' => 0])->order('is_top desc,sort desc,create_time desc')->select();
+            foreach ($coupon as $key => $info){
+                $coupon[$key]->end_time      = $info->create_time + $this->config->coupon_longtime * 60 * 60;
+                $coupon[$key]->is_get_coupon = 0; 
+            }
+            $is_get_coupon = 1;
+        }
+        return enjson(200,['coupon' => $coupon ,'store' => $store,'is_get_coupon' => $is_get_coupon]);
+    }
+
+
+    /**
+     * 根据定位推荐附近同圈子的优惠券
+     * @return void
+     */
+    public function couponTop(){
+        $param['store_id']  = $this->request->param('store_id/d',0);   //来自哪个商家
+        $this->apiSign($param);
+        $store = AisStore::where(['member_miniapp_id' => $this->miniapp_id,'id' => $param['store_id'],'is_lock' => 0])->find();
+        if(empty($store)){
+            return enjson(204);
+        }
+        if(empty($this->lbs->lat) || empty($this->lbs->lng)){
+            return enjson(204);
+        }
+        $prefix = config('database.prefix');
+        $latitude  = $this->lbs->lat;
+        $longitude = $this->lbs->lng;
+        $sql = 'select id,img,name from '.$prefix.'Ais_store where latitude > '.$latitude .'-1 and latitude < '.$latitude .'+1 and longitude > '.$longitude.'-1 and longitude < '.
+            $longitude.'+1 %s and id != '.$param['store_id'].' order by ACOS(SIN(('.$latitude .' * 3.1415) / 180 ) *SIN((latitude * 3.1415) / 180 ) +COS(('.$latitude .
+            ' * 3.1415) / 180 ) * COS((latitude * 3.1415) / 180 ) *COS(('.$longitude.'* 3.1415) / 180 - (longitude * 3.1415) / 180 ) ) * 6380 asc limit 20';
+        $ex = 'and id in(select store_id from  '.$prefix.'Ais_store_union where group_id in (select group_id from '.$prefix.'Ais_store_union where member_miniapp_id = '.$this->miniapp_id.' and store_id = '.$param['store_id'].
+            ' and type = 0 )  and type = 0 )';
+        $unionList = Db::query(sprintf($sql,$ex)); //附近商圏店铺查询
+        if(count($unionList) == 0){
+            $ex = 'and cate_id = '. $store->cate_id;
+            $unionList = Db::query(sprintf($sql,$ex));   //附近同行业店铺查询
+        }
+        if(count($unionList) == 0){
+            $unionList = Db::query(sprintf($sql,''));  //附近店铺查询
+        }
+        $store = [];
+        foreach($unionList as $key => $val){ 
+            $store[$val['id']] = $val;
+        } 
+        $store_ids =  implode(',',array_column($unionList,'id'));
+        $list = Db::query('SELECT * FROM '.$prefix.'Ais_coupon WHERE id >= (SELECT floor( RAND() * ((SELECT MAX(id) FROM '.$prefix.'Ais_coupon)-(SELECT MIN(id) FROM '.$prefix.'Ais_coupon)) + (SELECT MIN(id) FROM '.$prefix.'Ais_coupon))) and member_miniapp_id = '.
+            $this->miniapp_id.' and is_lock = 0 and is_end = 0 and store_id in ('.$store_ids.') ORDER BY id LIMIT 15;');
+        if (count($list)) {
+            return enjson(200,'success',['coupon' => $list,'store' => $store]);
+        }
+        return enjson(204);
+    }
+    
+    /**
+     * 微信给商家支付
+     * @param string $no
+     * @return void
+     */
+    public function wechat(){
+        if (request()->isPost()) {
+            $rule = [
+                'member_miniapp_id' => $this->miniapp_id,
+                'store_id'          => $this->request->param('store_id/d'),
+                'chain_id'          => $this->request->param('chain_id/d',0),
+                'user_couponr_id'   => $this->request->param('user_couponr_id/d',0),
+                'money'             => $this->request->param('money/f'),
+                'amount'            => $this->request->param('amount/f'),
+                'uid'               => $this->user->id,
+            ];
+            $validate = $this->validate($rule,'Dopay.gopay');
+            if (true !== $validate) {
+                return enjson(204,$validate);
+            }
+            //判断好店
+            $store = AisStore::where(['member_miniapp_id' => $this->miniapp_id,'id' => $rule['store_id'],'is_lock' => 0])->find();
+            if(empty($store)){
+                return enjson(204,'未找到商户');
+            }
+            $store->chain_id = 0;
+            if(!empty($rule['chain_id'])){
+                $chain = $store->chain()->where('id',$rule['chain_id'])->field('id,title,store_id')->find();
+                if(empty($chain)){
+                    return enjson(204,'未找到付款分店');
+                }
+                $store->title = $chain->title;
+                $store->chain_id = $chain->id;
+            }
+            if(empty($store->manage_uid)){
+                return enjson(204,'未设置老板');
+            }
+            if(empty($store->mch_id)){
+                return enjson(204,'未找到商家微信商户号');
+            }
+            //计算付款金额
+            $amount = AisOrder::countPrice($rule);
+            if(!$amount){
+                return enjson(204,'优惠券不满足使用条件');
+            }
+            //创建订单
+            $order_no = order_no($this->user->invite_code);
+            //唤醒微信支付参数
+            $payparm = [
+                'openid'     => $this->user->miniapp_uid,
+                'miniapp_id' => $this->miniapp_id,
+                'name'       => $store->name,
+                'order_no'   => $order_no,
+                'attach'     => 'Y',
+                'total_fee'  => $amount['price'] * 100,
+                'notify_url' => api(1,'ais/notify/storePay', $this->miniapp_id),
+            ];
+            $payparm['mchid'] = $store->mch_id;
+            if(!empty($amount['coupon'])){
+                if($amount['coupon']->parent_store_id > 0){
+                    $rule['parent_store_id']   = $amount['coupon']->parent_store_id;  //引荐的店铺
+                    $payparm['profit_sharing'] = 'Y';
+                    $payparm['attach']         = 'Y';
+                }
+                $rule['coupon_cache'] = $amount['coupon'];    //优惠券
+            }
+            $level = SystemUserLevel::where(['user_id' => $this->user->id,'level' => 1])->find();
+            if($level && $level->parent_id != $store->manage_uid){
+                $payparm['profit_sharing'] = 'Y';
+                $payparm['attach']         = 'Y';
+            }
+            $ispay = WechatPay::orderPay($payparm);
+            if($ispay['code'] == 0){
+                return enjson(204,$ispay['msg']);
+            }
+            //添加订单记录
+            $rule['order_no']       = $order_no;
+            $rule['price']          = $amount['price'];    //实际金额
+            $rule['store_chain_id'] = $store->chain_id;    //分店ID
+            $rel = AisOrder::addOrder($rule);
+            if(!$rel){
+                return enjson(204,'订单创建失败');
+            }
+            return enjson(200,'成功',$ispay['data']);
+        }
+    }
+
+}

+ 140 - 0
application/ais/controller/api/v1/User.php

@@ -0,0 +1,140 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 个人信息
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisBill;
+use app\ais\model\AisBank;
+use app\ais\model\AisBankCash;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisConfig;
+use app\ais\model\AisVip;
+use app\ais\model\AisVipUser;
+use app\ais\model\AisStore;
+use app\common\model\SystemUserLevel;
+use think\helper\Time;
+
+class User extends Base{
+    
+    /**
+     * 个人信息
+     * @return void
+     */
+    public function initialize() {
+        parent::initialize();
+        $this->isUserAuth();
+    }
+
+   /**
+     * 判断是否会员,并返回会员数据
+     */
+    public function vip(){
+        $this->apiSign();
+        $data['is_vip'] = 0;
+        $data['info']   = [];
+        $rel = AisVipUser::where(['is_lock' => 0,'uid' => $this->user->id])->find();
+        if(!empty($rel)){
+            $data['is_vip'] = 1;
+            $data['info']  = AisVip::where(['is_lock' => 0,'id' => $rel->vip_id])->find();
+        }
+        return enjson(200,$data);
+    }
+
+ 
+   /**
+     * 帐号数据分析
+     * icp_award:服务商月业绩提成
+     */
+    public function analysis(){
+        $this->apiSign();
+        $data = [
+            'bank' => ['money'=> 0,'tobo_paid' => 0,'point'=> 0,'coupon_save' => 0,'icp_award' => 0],
+            'num'  => ['fans'=> 0,'store' => 0,'vip'=> 0]
+        ];
+        $bank = AisBank::where(['uid'=>$this->user->id])->field('money,tobo_paid,point')->find();
+        if(!empty($bank)){
+            $data['bank'] = $bank;
+            $data['bank']['icp_award'] = 0; //计算月返利多少钱
+        }
+        $uids = SystemUserLevel::where(['parent_id' => $this->user->id,'level' => 1])->column('user_id');
+        $data['num']['fans']         = count($uids);  //粉丝数量
+        $data['num']['vip']          = AisVipUser::where(['is_lock' => 0])->whereIn('uid',$uids)->count();  //会员数量
+        $data['num']['store']        = AisStore::where(['is_lock' => 0])->whereIn('manage_uid',$uids)->count(); //邀请开通的好店数量
+        $data['bank']['coupon_save'] = AisCouponUser::where(['types' => 3,'is_end' => 0])->count();  //储值券
+        return enjson(200,$data);
+    }
+
+
+   /**
+     * 查看帐号余额
+     */
+    public function balance(){
+        $this->apiSign();
+        $info = AisBank::where(['uid'=>$this->user->id])->field('money,tobo_paid,point')->find()->toArray();
+        if(empty($info)){
+            $info = ['money' => 0,'tobo_paid' => 0,'point'=> 0];
+        }
+        return enjson(200,$info);
+    }
+
+    /**
+     * 提现申请
+     **/ 
+    public function cash(){
+        if (request()->isPost()) {
+            $param = [
+                'money'         => $this->request->param('money/f'),
+                'safepassword'  => $this->request->param('safepassword/s'),
+            ];
+            $this->apiSign($param);
+            $validate = $this->validate($param,'Bank.cash_out');
+            if (true !== $validate) {
+                return json(['code'=>403,'msg'=>$validate]);
+            }
+            //判断安全密码是否正确
+            if(!password_verify(md5($param['safepassword']),$this->user->safe_password)) {
+                return json(['code'=>403,'msg'=>'安全密码不正确']);
+            }
+            //判断提现周期
+            $is_cash = AisBankCash::where(['uid' => $this->user->id,'state' => 0])->count();
+            if($is_cash){
+                return json(['code'=>403,'msg'=>'还有提现再审核中,禁止连续提现']);
+            }
+            //减少
+            $rel = AisBank::cashOut($this->user->id,$param['money']);
+            if(empty($rel)){
+                return json(['code'=>403,'msg'=>"余额不足"]);
+            }
+            return enjson(200,"提现成功");
+        }
+    }
+
+   /**
+     * 账单
+     */
+    public function bill(){
+        $param['type'] = $this->request->param('type/d',0);
+        $param['page'] = $this->request->param('page/d',1);
+        $param['sign'] = $this->request->param('sign');
+        $this->apiSign($param);
+        $condition[] = ['uid','=',$this->user->id];
+        if($param['type']){
+            $condition[] = ['money','<',0]; //历史
+        }else{  
+            $condition[] = ['money','>',0]; //今天
+        }
+        $info = AisBill::withAttr('update_time', function ($value, $data) {
+            return date('Y-m-d H:i',$value);
+        })->with(['user'=> function($query) {
+            $query->field('id,face,nickname');
+        }])->where($condition)->order('id desc')->page($param['page'],10)->select();
+        if($info->isEmpty()){
+            return enjson(204);
+        }
+        return enjson(200,$info);
+    }
+}

+ 102 - 0
application/ais/controller/api/v1/Vip.php

@@ -0,0 +1,102 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 个人信息
+ */
+namespace app\ais\controller\api\v1;
+use app\ais\controller\api\Base;
+use app\ais\model\AisBill;
+use app\ais\model\AisBank;
+use app\ais\model\AisBankCash;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisConfig;
+use app\ais\model\AisVip;
+use app\ais\model\AisVipUser;
+use app\ais\model\AisStore;
+use app\ais\model\AisVipOrder;
+use app\common\facade\WechatPay;
+use app\common\model\SystemUserLevel;
+use think\helper\Time;
+
+class Vip extends Base{
+    
+   /**
+     * 所有会员类型数据
+     */
+    public function index(){
+        $this->apiSign();
+        $rel = AisVip::where(['member_miniapp_id'=> $this->member_miniapp_id,'is_auto_up' => 1])->select();
+        return enjson(200,$rel);
+    }
+
+    /**
+     * 读取ISP会员数据
+     */
+    public function isp(){
+        $this->apiSign();
+        $rel = AisVip::where(['member_miniapp_id'=> $this->member_miniapp_id,'is_auto_up' => 0])->find();
+        if($rel){
+            $rel->rule  = str_replace('<img', '<img class="img"',dehtml($rel->rule));
+        }
+        return enjson(200,$rel);
+    }
+
+    /**
+     * 微信支付开通会员
+     * @param string $no
+     * @return void
+     */
+    public function regVip(){
+        if (request()->isPost()) {
+            $param['vip_id'] = $this->request->param('vip_id/d');
+            $this->apiSign($param);
+            $vip = AisVip::where(['member_miniapp_id' => $this->member_miniapp_id,'id' => $param['vip_id']])->find();
+            if(empty($vip)){
+                return enjson(403,'未找到相关会员等级');
+            }
+            //用户VIP
+            $vipUser = AisVipUser::where(['uid' => $this->user->id,'vip_id' => $vip->id])->find();
+            if($vipUser){
+                return enjson(403,'已开通当前会员');
+            }
+            //创建订单
+            $order_no = order_no($this->user->invite_code);
+            //唤醒微信支付参数
+            $payparm = [
+                'openid'     => $this->user->miniapp_uid,
+                'miniapp_id' => $this->member_miniapp_id,
+                'name'       => $vip->name,
+                'order_no'   => $order_no,
+                'total_fee'  => $vip->price * 100,
+                'notify_url' => api(1,'ais/notify/vippay',$this->miniapp_id),
+            ];
+            //读取配置
+            if($this->member_miniapp->is_psp){
+                $setting = AisConfig::getConfig($this->miniapp_id);
+                if (empty($setting->mchid)) {
+                    return enjson(403,'服务商模式下,必须配置默认商户号');
+                }
+                $payparm['mchid'] = $setting->mchid;  
+            }
+            $ispay = WechatPay::orderPay($payparm);
+            if($ispay['code'] == 0){
+                return enjson(403,$ispay['msg']);
+            }
+            //添加订单记录
+            $data['order_no']          = $order_no;
+            $data['uid']               = $this->user->id;
+            $data['member_miniapp_id'] = $this->member_miniapp_id;
+            $data['vip_id']            = $vip->id;
+            $data['amount']            = $vip->price;    //实际金额
+            $data['state']             = 0;
+            $data['create_time']       = time();
+            $rel = AisVipOrder::create($data);
+            if(!$rel){
+                return enjson(403,'订单创建失败');
+            }
+            return enjson(200,$ispay['data']);
+        }
+    }
+}

+ 265 - 0
application/ais/controller/coupon/Index.php

@@ -0,0 +1,265 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 优惠券管理
+ */
+namespace app\ais\controller\coupon;
+use app\ais\controller\Common;
+use app\ais\model\AisConfig;
+use app\ais\model\AisCoupon;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisCard;
+use app\ais\model\AisStore;
+use think\facade\Request;
+use think\helper\Time;
+
+class Index extends Common{
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps', [['name'=>'优惠券管理','url'=>url("coupon.index/index")]]);
+    }
+
+    /**
+     * 列表
+     */
+    public function index(int $types = 0){
+        $condition = [];
+        $time      = Request::param('time/d',0);
+        $starttime = Request::param('starttime/s');
+        $endtime   = Request::param('endtime/s');
+        if($time){
+            switch ($time) {
+                case 2:
+                    list($start, $end) = Time::yesterday();
+                    break;
+                case 30:
+                    list($start, $end) = Time::month();
+                    break;
+                case 60:
+                    list($start, $end) = Time::lastMonth();
+                    break;
+                default:
+                    list($start, $end) = Time::today();
+                    break;
+            }
+            $condition[] = ['create_time','>=',$start];
+            $condition[] = ['create_time','<=',$end];
+        }else{
+            if($starttime){
+                $condition[] = ['create_time','>=',strtotime($starttime)];
+            }
+            if($endtime){
+                $condition[] = ['create_time','<=',strtotime($endtime)];
+            }
+        }
+        $store_id   = Request::param('store_id/d');
+        $store_name = Request::param('store_name');
+        if($store_id){
+            $condition[] = ['store_id','=',$store_id];
+        }
+        $keyword = Request::param('keyword');
+        if(!empty($keyword)){
+            $condition[] = ['name','like','%'.$keyword.'%'];
+        }
+        switch ($types) {
+            case 1:
+                $condition[] = ['is_lock','=',1];
+                $condition[] = ['is_end','=',0];
+                break;
+            case 2:
+                $condition[] = ['is_end','=',1];
+                break;
+            default;
+                $condition[] = ['is_end','=',0];
+                break;
+        }
+        $view['lists']      = AisCoupon::where($this->mini_program)->where($condition)->order('sort desc,is_lock desc,update_time desc')->paginate(10,false,['query' => ['types' => $types,'store_id' => $store_id,'store_name' => $store_name]]);
+        $view['types']      = $types;
+        $view['keyword']    = $keyword;
+        $view['store_id']   = $store_id;
+        $view['store_name'] = $store_name;
+        $view['time']       = $time;
+        $view['starttime']  = $starttime;
+        $view['endtime']    = $endtime;
+        return view()->assign($view);
+    }
+
+    //优惠券预览和统计
+    public function review(int $id,int $types = 0){
+        $info = AisCoupon::where($this->mini_program)->where(['id' => $id])->find();
+        if(empty($info)){
+            $this->error('内容不存在');
+        }
+        $condition = [];
+        $condition['is_end']      = $types ?? 0;
+        $condition['coupon_id']   = $id;
+        $view['lists']            = AisCouponUser::where($this->mini_program)->where($condition)->order('id asc')->paginate(10,false,['query'=>['id' => $id,'types' => $types]]);
+        $view['types']            = $types;
+        $view['coupon_count']     = AisCouponUser::where($this->mini_program)->where(['coupon_id' => $id])->count();
+        $view['coupon_end_count'] = AisCouponUser::where($this->mini_program)->where(['coupon_id' => $id,'is_end' => 1])->count();
+        $view['info']             = $info;
+        $config = AisConfig::getConfig($this->member_miniapp_id);
+        $view['end_time']         = $config->coupon_longtime * 60 * 60;
+        return view()->assign($view);
+    }
+
+    //编辑
+    public function edit($id = 0){
+        if(request()->isAjax()){
+            $param = [
+                'id'         => $this->request->param('id/d',0),
+                'name'       => $this->request->param('name/s'),
+                'price'      => $this->request->param('price/d'),
+                'types'      => $this->request->param('types/d'),
+                'discount'   => $this->request->param('discount/d',0),
+                'howmuch'    => $this->request->param('howmuch/d',0),
+                'amount'     => $this->request->param('amount/f',0),
+                'tips'       => $this->request->param('tips/s'),
+                'num'        => $this->request->param('num/d',0),
+            ];
+            $validate = $this->validate($param,'Coupon.edit');
+            if(true !== $validate){
+                return enjson(0,$validate);
+            }
+            $data['name']     = $param['name'];
+            $data['price']    = $param['price'];
+            $data['tips']     = $param['tips'];
+            $data['num']      = $param['num'];
+            $data['howmuch']  = $param['howmuch'];
+            $data['types']    = $param['types'];;
+            $data['price']    = 0;
+            $data['amount']   = 0;
+            $data['discount'] = 0;
+            switch ($param['types'] ) {
+                case 1: //折扣券
+                    $data['discount'] = $param['discount'];
+                    break;
+                case 2: //兑换券
+                    $data['amount']   = $param['amount'];
+                    break;
+                default: //代金券
+                    $data['price']    = $param['price'];
+                    break;
+            }
+            if($param['id']){
+                $result = AisCoupon::where($this->mini_program)->where(['id' => $param['id']])->update($data);
+            }else{
+                $store_id = $this->request->param('store_id/d',0);
+                $store    = AisStore::where(['id' => $store_id])->find();
+                if(empty($store)){
+                    return json(['code'=>0,'msg'=>'商家必须选择']);
+                }
+                $data['member_miniapp_id'] = $this->member_miniapp_id;
+                $data['create_time']       = time();
+                $data['update_time']       = time();
+                $data['store_id']          = $store_id;
+                $data['cate_id']           = $store->cate_id;
+                $data['cate_sid']          = $store->cate_sid;
+                $data['citycode']          = $store->citycode;
+                $data['is_top']            = 0;
+                $result                    = AisCoupon::create($data);
+            }
+            if($result){
+                return enjson(200);
+            }
+            return enjson(0);
+        }else{
+            $view['info'] = AisCoupon::where($this->mini_program)->where(['id' => $id])->find();
+            return view()->assign($view);
+        }
+    }
+
+    //删除
+    public function delete(int $id){
+        if(AisCoupon::where($this->mini_program)->where(['id' => $id,'types' => 3])->find()){
+            return enjson(0,'本券禁止删除');
+        }
+        $result = AisCoupon::where($this->mini_program)->where(['id' => $id])->delete();
+        if($result){
+            return enjson(200);
+        }
+        return enjson(0);
+    }
+
+    /**
+     * 排序
+     */
+    public function sort(){
+        if(request()->isAjax()){
+            $data = [
+                'sort' => $this->request->param('sort/d'),
+                'id'   => $this->request->param('id/d'),
+            ];
+            $validate = $this->validate($data,'Category.sort');
+            if(true !== $validate){
+                return enjson(0,$validate);
+            }
+            $result = AisCoupon::where($this->mini_program)->where(['id' => $data['id']])->update(['sort'=>$data['sort']]);
+            if($result){
+                return enjson(200);
+            }
+            return enjson(0);
+        }
+    }
+   
+    /**
+     * 置顶/取消
+     * @param integer $id 用户ID
+     */
+    public function isTop(int $id){
+        $result = AisCoupon::where(['id' => $id])->where('types','<','3')->field('is_top')->find();
+        if(empty($result)){
+            return enjson(0,'本券禁止操作');
+        }
+        $result->is_top = $result->is_top ? 0 : 1;
+        $rel = $result->save();
+        if($rel){
+            return enjson(200);
+        }
+        return enjson(0);
+    } 
+
+     /**
+     * 审核和取消
+     * @param integer $id 用户ID
+     */
+    public function isLock(int $id){
+        $result = AisCoupon::where(['id' => $id])->where('types','<','3')->field('is_lock,store_id')->find();
+        if(empty($result)){
+            return enjson(0,'本券禁止操作');
+        }
+        $result->is_lock = $result->is_lock ? 0 : 1;
+        $rel = $result->save();
+        if($rel){
+            return enjson(200);
+        }
+        return enjson(0);
+    } 
+
+
+    /**
+     * 优惠券选项
+     */
+    public function select(){
+        $view['input']       = $this->request->param('input/s');
+        $view['store_id']    = $this->request->param('store_id/d',0);
+        $view['keyword']     = $this->request->param('keyword');
+        $view['types']       = $this->request->param('types/d',0);
+        $view['is_lock']     = $this->request->param('is_lock/d',0);
+        $condition   = [];
+        $condition[] = ['is_lock', '=',0];
+        if($view['types']){
+            $condition[] = ['types','=',$view['types']];
+        }else{
+            $condition[] = ['types','<=',1];
+        }
+        if($view['store_id']){
+            $condition[] = ['store_id','=',$view['store_id']];
+        }
+        $view['lists'] = AisCoupon::where($this->mini_program)->withSearch(['name'],['name' => $view['keyword']])->where($condition)->order('is_top desc,sort desc,is_lock desc,update_time desc')->paginate(10,false,['query' => ['keyword' => $view['keyword'],'store_id' => $view['store_id'],'input' => $view['input']]]);
+        return view()->assign($view);
+    }
+}

+ 320 - 0
application/ais/controller/coupon/User.php

@@ -0,0 +1,320 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 优惠券管理
+ */
+namespace app\ais\controller\coupon;
+use app\ais\controller\Common;
+use app\ais\model\AisConfig;
+use app\ais\model\AisCoupon;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisCard;
+use app\common\facade\Inform;
+use think\facade\Request;
+use think\helper\Time;
+use app\ais\model\AisStore;
+
+class User extends Common{
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps', [['name'=>'优惠券管理','url'=>url("coupon/index")]]);
+    }
+
+    /**
+     * 列表
+     */
+    public function index(int $types = 0,int $page = 0){
+        $condition = [];
+        $time      = Request::param('time/d',0);
+        $starttime = Request::param('starttime/s');
+        $endtime   = Request::param('endtime/s');
+        if($time){
+            switch ($time) {
+                case 2:
+                    list($start, $end) = Time::yesterday();
+                    break;
+                case 30:
+                    list($start, $end) = Time::month();
+                    break;
+                case 60:
+                    list($start, $end) = Time::lastMonth();
+                    break;
+                default:
+                    list($start, $end) = Time::today();
+                    break;
+            }
+            $condition[] = ['create_time','>=',$start];
+            $condition[] = ['create_time','<=',$end];
+        }else{
+            if($starttime){
+                $condition[] = ['create_time','>=',strtotime($starttime)];
+            }
+            if($endtime){
+                $condition[] = ['create_time','<=',strtotime($endtime)];
+            }
+        }
+        $store_id   = Request::param('store_id/d');
+        $store_name = Request::param('store_name');
+        if($store_id){
+            $condition[] = ['store_id','=',$store_id];
+        }
+        $keyword = Request::param('keyword');
+        if(!empty($keyword)){
+            $condition[] = ['name','like','%'.$keyword.'%'];
+        }
+        //统计
+        $view['coupon_count']          = AisCoupon::where($this->mini_program)->where($condition)->where(['is_end' => 0,'is_lock' => 0])->count();
+        $view['coupon_end_count']      = AisCoupon::where($this->mini_program)->where($condition)->where(['is_end' => 1])->count();
+        $view['coupon_user_count']     = AisCouponUser::where($this->mini_program)->where($condition)->where(['is_end' => 0])->count();
+        $view['coupon_user_end_count'] = AisCouponUser::where($this->mini_program)->where($condition)->where(['is_end' => 1])->count();
+        switch ($types) {
+            case 1:
+                $condition[] = ['is_lock','=',1];
+                $condition[] = ['is_end','=',0];
+                break;
+            case 2:
+                $condition[] = ['is_lock','=',0];
+                $condition[] = ['is_end','=',0];
+                break;
+            case 4:
+                $condition[] = ['is_end','=',1];
+                break;
+            default;
+                $condition[] = ['is_end','=',0];
+                break;
+        }
+        $view['lists']      = AisCoupon::where($this->mini_program)->where($condition)->order('sort desc,is_lock desc,update_time desc')->paginate(10,false,['query' => ['types' => $types,'store_id' => $store_id,'store_name' => $store_name]]);
+        $view['types']      = $types;
+        $view['page']       = $page;
+        $view['keyword']    = $keyword;
+        $view['store_id']   = $store_id;
+        $view['store_name'] = $store_name;
+        $view['time']       = $time;
+        $view['starttime']  = $starttime;
+        $view['endtime']    = $endtime;
+        return view()->assign($view);
+    }
+
+    //优惠券预览和统计
+    public function review(int $id,int $types = 0){
+        $info = AisCoupon::where($this->mini_program)->where(['id' => $id])->find();
+        if(empty($info)){
+            $this->error('内容不存在');
+        }
+        $condition = [];
+        $condition['is_end']      = $types ?? 0;
+        $condition['coupon_id']   = $id;
+        $view['lists']            = AisCouponUser::where($this->mini_program)->where($condition)->order('id asc')->paginate(10,false,['query'=>['id' => $id,'types' => $types]]);
+        $view['types']            = $types;
+        $view['coupon_count']     = AisCouponUser::where($this->mini_program)->where(['coupon_id' => $id])->count();
+        $view['coupon_end_count'] = AisCouponUser::where($this->mini_program)->where(['coupon_id' => $id,'is_end' => 1])->count();
+        $view['info']             = $info;
+        $config = AisConfig::getConfig($this->member_miniapp_id);
+        $view['end_time']         = $config->coupon_longtime * 60 * 60;
+        return view()->assign($view);
+    }
+
+    //编辑
+    public function edit(){
+        $id   = Request::param('id/d');
+        if(request()->isAjax()){
+            $data = [
+                'id'         => Request::param('id/d'),
+                'name'       => Request::param('name/s'),
+                'price'      => Request::param('price/f'),
+                'discount'   => Request::param('discount/d',0),
+                'howmuch'    => Request::param('howmuch/d',0),
+                'tips'       => Request::param('tips/s'),
+                'types'      => Request::param('types/d',0),
+            ];
+            $validate = $this->validate($data,'Coupon.edit');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            if($data['types'] == 0){
+                $data['discount']  = 0;
+            }else{
+                $data['price'] = 0;
+            }
+            if($id){
+                $data['id'] = $id;
+                $result = AisCoupon::where($this->mini_program)->where(['id' => $data['id']])->update($data);
+            }else{
+                $store_id = Request::param('store_id/d',0);
+                $store = AisStore::where(['id' => $store_id])->find();
+                if(empty($store)){
+                    return json(['code'=>0,'msg'=>'商家必须选择']);
+                }
+                $data['member_miniapp_id'] = $this->member_miniapp_id;
+                $data['create_time']       = time();
+                $data['update_time']       = time();
+                $data['store_id']          = $store_id;
+                $data['cate_id']           = $store->cate_id;
+                $data['cate_sid']          = $store->cate_sid;
+                $data['is_top']            = 0;
+                $result                    = AisCoupon::create($data);
+            }
+            if($result){
+                return json(['code'=>200,'url'=>url('coupon/index',['page' => input('get.page/d')]),'msg'=>'操作成功']);
+            }else{
+                return json(['code'=>0,'msg'=>'操作失败']);
+            }
+        }else{
+            $info = AisCoupon::where($this->mini_program)->where(['id' => $id])->find();
+            $view['info'] = $info;
+            $view['page'] = input('get.page/d');
+            return view()->assign($view);
+        }
+    }
+
+    //删除
+    public function delete(int $id){
+        $result = AisCoupon::where($this->mini_program)->where(['id' => $id])->delete();
+        if($result){
+            return json(['code'=>200,'msg'=>'操作成功']);
+        }else{
+            return json(['code'=>403,'msg'=>'删除失败']);
+        } 
+    }
+
+    /**
+     * 排序
+     */
+    public function sort(){
+        if(request()->isAjax()){
+            $data = [
+                'sort' => $this->request->param('sort/d'),
+                'id'   => $this->request->param('id/d'),
+            ];
+            $validate = $this->validate($data,'Category.sort');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $result = AisCoupon::where($this->mini_program)->where(['id' => $data['id']])->update(['sort'=>$data['sort']]);
+            if($result){
+                return json(['code'=>200,'msg'=>'操作成功']);
+            }else{
+                return json(['code'=>0,'msg'=>'操作失败']);
+            }
+        }
+    }
+   
+    /**
+     * 置顶/取消
+     * @param integer $id 用户ID
+     */
+    public function isTop(int $id){
+        $rel = AisCoupon::where(['id' => $id])->field('is_top')->find();
+        $rel->is_top = $rel->is_top ? 0 : 1;
+        $rel->save();
+        return json(['code'=>200,'msg'=>'操作成功']);
+    } 
+
+     /**
+     * 审核和取消
+     * @param integer $id 用户ID
+     */
+    public function isLock(int $id){
+        $result = AisCoupon::where(['id' => $id])->field('is_lock,store_id')->find();
+        $result->is_lock = $result->is_lock ? 0 : 1;
+        $rel = $result->save();
+        if($rel){
+            if($result->is_lock == 0){
+                $store = AisStore::where('id','=',$result->store_id)->find();
+                if($store){
+                    Inform::sms($store->manage_uid,$this->member_miniapp_id,['title' =>'业务进展通知','type' => '优惠券申请','content' =>'您的优惠券申请已经通过审核','state' => '成功']);
+                }
+            }
+            return json(['code'=>200,'msg'=>'操作成功']);
+        }else{
+            return json(['code'=>0,'msg'=>'操作失败']);
+        }
+    } 
+   
+    /**
+     * 用户已领优惠券管理
+     *
+     * @param integer $id  优惠券ID
+     * @param integer $uid 用户ID
+     * @return void
+     */
+    public function user(int $types = 0){
+        $condition = [];
+        $uid  = Request::param('uid/d');
+        if($uid){
+            $condition[] = ['uid','=',$uid];
+        }
+        $store_id   = Request::param('store_id/d');
+        $store_name = Request::param('store_name/s');
+        if($store_id){
+            $condition[] = ['store_id','=',$store_id];
+        }
+        $time = Request::param('time/d',0);
+        if($time){
+            switch ($time) {
+                case 2:
+                    list($start, $end) = Time::yesterday();
+                    break;
+                case 30:
+                    list($start, $end) = Time::month();
+                    break;
+                case 60:
+                    list($start, $end) = Time::lastMonth();
+                    break;
+                default:
+                    list($start, $end) = Time::today();
+                    break;
+            }
+            $condition[] = ['create_time','>=',$start];
+            $condition[] = ['create_time','<=',$end];
+        }
+        $starttime = Request::param('starttime/s');
+        $endtime = Request::param('endtime/s');
+        if($starttime){
+            $condition[] = ['create_time','>=',strtotime($starttime)];
+        }
+        if($endtime){
+            $condition[] = ['create_time','<=',strtotime($endtime)];
+        }
+        $view['coupon_count']     = AisCouponUser::where($this->mini_program)->where($condition)->where(['is_end' => 0])->count();
+        $view['coupon_end_count'] = AisCouponUser::where($this->mini_program)->where($condition)->where(['is_end' => 1])->count();
+        $view['lists']      = AisCouponUser::where($this->mini_program)->where($condition)->where(['is_end'=>$types ? 1 : 0])->order('id desc')->paginate(20,false,['query'=>['uid' => $uid,'types' => $types,'starttime' => $starttime,'endtime' => $endtime,'time'=>$time]]);
+        $view['types']      = $types;
+        $view['time']       = $time;
+        $view['starttime']  = $starttime;
+        $view['endtime']    = $endtime;
+        $view['uid']        = $uid;
+        $view['store_id']   = $store_id;
+        $view['store_name'] = $store_name;
+        $view['pathMaps']   = [['name'=>'已领优惠券','url'=>url("coupon/user")]];
+        $config = AisConfig::getConfig($this->member_miniapp_id);
+        $view['end_time']   = $config->coupon_longtime * 60 * 60;
+        return view()->assign($view);
+    }
+
+    /**
+     * 查看用户优惠券信息
+     * @param integer $id
+     * @return void
+     */
+    public function userCoupon(int $id = 0){
+        $view['info'] = AisCouponUser::where($this->mini_program)->where(['id' => $id])->find();
+        return view()->assign($view);
+    }
+
+    /**
+     * 删除用户的优惠券
+     * @return void
+     */
+    public function deleteUser(int $id){
+        $result = AisCouponUser::where($this->mini_program)->where(['id' => $id])->delete();
+        if($result){
+            return json(['code'=>200,'msg'=>'操作成功']);
+        }else{
+            return json(['code'=>403,'msg'=>'删除失败']);
+        }
+    }
+}

+ 22 - 0
application/ais/controller/home/Index.php

@@ -0,0 +1,22 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 文章内容
+ */
+namespace app\ais\controller\home;
+use app\common\controller\Home;
+use app\ais\model\AisConfig;
+
+class Index extends Home{
+
+    /**
+     * 服务协议
+     * @return void
+     */
+    public function index(){
+        code($this->is_minapp);
+    }
+        
+}

+ 17 - 0
application/ais/controller/home/Task.php

@@ -0,0 +1,17 @@
+<?php
+namespace app\ais\controller\home;
+use app\common\controller\Home;
+use app\ais\model\AisConfig;
+use app\ais\model\AisCouponUser;
+
+class Task extends Home{
+    //定时任务 更改优惠券过期
+    public function index(){
+        $configList = AisConfig::getAllConfig();
+        foreach ($configList as $config){
+            if(!empty($config->coupon_longtime)){
+                AisCouponUser::where(['member_miniapp_id' => $config->member_miniapp_id,'is_end' => 0])->where('create_time','<=',(time() - $config->coupon_longtime * 60 * 60 ))->update(['is_end' => 1]);
+            }
+        }
+    }
+}

+ 106 - 0
application/ais/controller/info/Cate.php

@@ -0,0 +1,106 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 栏目管理
+ */
+namespace app\ais\controller\info;
+use app\ais\controller\Common;
+use app\ais\model\AisInfoCate;
+use app\ais\model\AisInfo;
+use app\ais\model\AisInfoTpl;
+
+class Cate extends Common{
+
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps',[['name'=>'信息分类','url'=>url("info.cate/index")]]);
+    }
+
+    /**
+     * 列表
+     */
+    public function index(){
+        $view['lists']   = AisInfoCate::where(['member_miniapp_id' => $this->member_miniapp_id])->order('sort desc,id desc')->paginate(20); 
+        $view['tabs']    = [
+            ['name' =>'主题管理','url' =>url('info.cate/index'),'action' => 1],
+            ['name' =>'模板库','url' =>url('info.tpl/index')],
+            ['name' =>'推广设置','url' =>url('setting/info')],
+        ];
+        return view()->assign($view);
+    }
+
+
+    //编辑
+    public function edit(){
+        if(request()->isAjax()){
+            $data = [
+                'id'        => $this->request->param('id/d',0),
+                'title'     => $this->request->param('title/s'),
+                'name'      => $this->request->param('name/s'),
+                'sort'      => $this->request->param('sort/d',0),
+                'tpl_id'    => $this->request->param('tpl_id/d'),
+            ];
+            $validate = $this->validate($data,'Category.edit');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            if($data['tpl_id']){
+                $tpl = AisInfoTpl::where($this->mini_program)->where(['id'=>$data['tpl_id']])->field('fields')->find();
+                $data['fields'] = empty($tpl)?'[]' : $tpl->fields;
+            }else{
+                $data['fields'] = '[]';
+            }
+            $result =  AisInfoCate::edit($data);
+            if($result){
+                return json(['code'=>200,'url'=>url('info.cate/index'),'msg'=>'操作成功']);
+            }else{
+                return json(['code'=>0,'msg'=>'操作失败']);
+            }
+        }else{
+            $view['id']  = $this->request->param('id/d',0);
+            $view['info']= AisInfoCate::where($this->mini_program)->where(['id' => $view['id']])->find();
+            $view['tpl'] = AisInfoTpl::where($this->mini_program)->order('id asc')->select();
+            return view('edit',$view);
+        }
+    }
+
+    /**
+     * 排序
+     */
+    public function sort(){
+        if(request()->isAjax()){
+            $data = [
+                'sort' => $this->request->param('sort/d'),
+                'id'   => $this->request->param('id/d'),
+            ];
+            $validate = $this->validate($data,'Cate.sort');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $result = AisInfoCate::update(['sort'=>$data['sort'],'id' => $data['id']]);
+            if($result){
+                return enjson(200);
+            }else{
+                return enjson(0);
+            }
+        }
+    }
+
+    //删除
+    public function delete(){
+        $id = $this->request->param('id/d');
+        $info = AisInfo::where(['cate_id' => $id])->count();
+        if($info){
+            return enjson(0,'删除失败,栏目中还包含内容');
+        }
+        $result = AisInfoCate::where(['id'=>$id,'member_miniapp_id' => $this->member_miniapp_id])->delete();
+        if($result){
+            return enjson(200);
+        }else{
+            return enjson(0);
+        } 
+    }
+}

+ 158 - 0
application/ais/controller/info/Index.php

@@ -0,0 +1,158 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 信息管理
+ */
+namespace app\ais\controller\info;
+use app\ais\controller\Common;
+use app\ais\model\AisInfo;
+use app\ais\model\AisInfoReply;
+use think\facade\Request;
+use think\helper\Time;
+use util\Util;
+
+class index extends Common{
+
+    public function initialize(){
+        parent::initialize();
+        $this->assign('pathMaps',[['name'=>'信息管理','url'=>url("info.index/index")]]);
+    }
+
+    /**
+     * 列表
+     */
+    public function index(int $types = 0){
+        $condition  = [];
+        $time      = Request::param('time/d',0);
+        $starttime = Request::param('starttime/s');
+        $endtime   = Request::param('endtime/s');
+        if($time){
+            switch ($time) {
+                case 2:
+                    list($start, $end) = Time::yesterday();
+                    break;
+                case 30:
+                    list($start, $end) = Time::month();
+                    break;
+                case 60:
+                    list($start, $end) = Time::lastMonth();
+                    break;
+                default:
+                    list($start, $end) = Time::today();
+                    break;
+            }
+            $condition[] = ['create_time','>=',$start];
+            $condition[] = ['create_time','<=',$end];
+        }else{
+            if($starttime){
+                $condition[] = ['create_time','>=',strtotime($starttime)];
+            }
+            if($endtime){
+                $condition[] = ['create_time','<=',strtotime($endtime)];
+            }
+        }
+        $view['top_num']   = AisInfo::where($this->mini_program)->where($condition)->sum("is_top");
+        $view['views_num'] = AisInfo::where($this->mini_program)->where($condition)->sum("views");
+        $view['lock_num']  = AisInfo::where($this->mini_program)->where($condition)->where(['is_lock' => 1])->sum("is_lock");
+        $condition[] = ['is_lock','=',$types];
+        $lists = AisInfo::where($this->mini_program)->where($condition)->order('is_top desc,sort desc,id desc')->paginate(20,false,['query' => ['types' => $types,'starttime' => $starttime,'endtime' => $endtime,'time'=>$time]]); 
+        $view['types']     = $types;
+        foreach ($lists as $key => $value) {
+            $lists[$key]['howday'] = Util::ftime($value['create_time']);
+            $lists[$key]['images'] = json_decode($value['images'],true);
+        }
+        $view['lists']      = $lists;
+        $view['time']       = $time;
+        $view['starttime']  = $starttime;
+        $view['endtime']    = $endtime;
+        return view()->assign($view);
+    }
+
+   /**
+     * 查看回复
+     * @param integer $id 用户ID
+     */
+    public function reply(int $id){
+        $info = AisInfo::where($this->mini_program)->where(['id'=> $id])->find();
+        if(empty($info)){
+            return $this->error('没有内容');
+        }
+        $info['images']      = empty($info['images']) ? [] :json_decode($info['images']);
+        $info['create_time'] = Util::ftime($info['create_time']);
+        $view['info']        = $info;
+        $view['reply']       = $info->comments()->order('id desc')->paginate(10,false,['query'=>['id' => $id]]);
+        $view['fields']      = json_decode($info->fields,true);
+        if($info->is_get){
+            $view['tabs'] = [
+                ['name' =>'信息内容','url' =>url('info.index/reply',['id' => $id]),'action' => 1],
+                ['name' =>'订单列表','url' =>url('info.order/index',['infoid' => $id])],
+            ];
+        }
+        return view()->assign($view);
+    }
+  
+    //删除
+    public function delete(){
+        $id = input('get.id/d');
+        $result = AisInfo::where($this->mini_program)->where(['id' => $id])->delete();
+        if($result){
+            AisInfoReply::where($this->mini_program)->where(['info_id' => $id])->delete();
+            return json(['code'=>200,'msg'=>'操作成功']);
+        }else{
+            return json(['code'=>403,'msg'=>'删除失败,请查看是否包含子链接']);
+        } 
+    }
+
+    /**
+     * 锁定
+     * @param integer $id 用户ID
+     */
+    public function islock(int $id){
+        $result = AisInfo::lock($id,$this->member_miniapp_id);
+        if(!$result){
+            return json(['code'=>0,'message'=>'操作失败']);
+        }else{
+            return json(['code'=>200,'message'=>'操作成功']);
+        }
+    }
+
+
+    /**
+     * 指定
+     * @param integer $id 用户ID
+     */
+    public function isTop(int $id){
+        $result = AisInfo::Top($id);
+        if(!$result){
+            return json(['code'=>0,'message'=>'操作失败']);
+        }else{
+            return json(['code'=>200,'message'=>'操作成功']);
+        }
+    }
+ 
+    //删除
+    public function delReply(){
+        $id = input('get.id/d');
+        $result = AisInfoReply::where($this->mini_program)->where(['id' => $id])->delete();
+        if($result){
+            return json(['code'=>200,'msg'=>'操作成功']);
+        }else{
+            return json(['code'=>403,'msg'=>'删除失败']);
+        } 
+    }
+
+    /**
+     * 锁定
+     * @param integer $id 用户ID
+     */
+    public function islockReply(int $id){
+        $result = AisInfoReply::lock($id);
+        if(!$result){
+            return json(['code'=>0,'message'=>'操作失败']);
+        }else{
+            return json(['code'=>200,'message'=>'操作成功']);
+        }
+    }    
+}

+ 157 - 0
application/ais/controller/info/Mp.php

@@ -0,0 +1,157 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 同城号
+ */
+namespace app\ais\controller\info;
+use app\ais\controller\Common;
+use app\ais\model\AisInfoMp;
+use app\common\model\SystemUser;
+use think\facade\Validate;
+use think\facade\Request;
+use think\helper\Time;
+
+class Mp extends Common{
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps',[['name'=>'城市号','url'=>url("info.mp/index")]]);
+    }
+
+    /**
+     * 列表
+     */
+    public function index(int $types = 0){
+        $condition  = [];
+        $time      = Request::param('time/d',0);
+        $starttime = Request::param('starttime/s');
+        $endtime   = Request::param('endtime/s');
+        if($time){
+            switch ($time) {
+                case 2:
+                    list($start, $end) = Time::yesterday();
+                    break;
+                case 30:
+                    list($start, $end) = Time::month();
+                    break;
+                case 60:
+                    list($start, $end) = Time::lastMonth();
+                    break;
+                default:
+                    list($start, $end) = Time::today();
+                    break;
+            }
+            $condition[] = ['reg_time','>=',$start];
+            $condition[] = ['reg_time','<=',$end];
+        }else{
+            if($starttime){
+                $condition[] = ['reg_time','>=',strtotime($starttime)];
+            }
+            if($endtime){
+                $condition[] = ['reg_time','<=',strtotime($endtime)];
+            }
+        }
+        $view['num']  = AisInfoMp::where($this->mini_program)->where($condition)->count();
+        $view['vip_num']   = AisInfoMp::where($this->mini_program)->where($condition)->where(['is_vip' => 1])->count();
+        $view['notvip_num'] = AisInfoMp::where($this->mini_program)->where($condition)->where(['is_vip' => 0])->count();
+        $condition[] = ['is_lock','=',$types];
+        $lists = AisInfoMp::where($this->mini_program)->where($condition)->order('id desc')->paginate(20,false,['query' => ['types' => $types,'starttime' => $starttime,'endtime' => $endtime,'time'=>$time]]); 
+        $view['types']     = $types;
+        $view['lists']      = $lists;
+        $view['time']       = $time;
+        $view['starttime']  = $starttime;
+        $view['endtime']    = $endtime;
+        return view()->assign($view);
+    }
+
+
+    //规格编辑
+    public function edit(){
+        if(request()->isAjax()){
+            $data = [
+                'member_miniapp_id' => $this->member_miniapp_id,
+                'id'                => $this->request->param('id/d',0),
+                'uid'               => $this->request->param('uid/d'),
+                'logo'              => $this->request->param('logo/s'),
+                'title'             => $this->request->param('title/s'),
+                'note'              => $this->request->param('note/s'),
+                'is_vip'            => $this->request->param('is_vip/d',0),
+                'vip_title'         => $this->request->param('vip_title/s'),
+                'vip_about'         => $this->request->param('vip_about/s'),
+                'vip_time'          => $this->request->param('vip_time/s'),
+            ];
+            $validate = $this->validate($data,$data['is_vip'] ? 'Info.mpVip':'Info.mpEdit');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $result = AisInfoMp::edit($data);
+            if(empty($result)){
+                return enjson(403,'操作失败');
+            }
+            return enjson(200,'操作成功',['url'=>url('info.mp/index')]);
+        }else{
+            $view['info'] = AisInfoMp::where($this->mini_program)->where(['id' => $this->request->param('id/d',0)])->find();
+            return view()->assign($view);
+        }
+    }
+    
+    /**
+     * 预览信息
+     * @return void
+     */
+    public function review(){
+        $view['info'] = AisInfoMp::where($this->mini_program)->where(['id' => $this->request->param('id/d',0)])->find();
+        return view()->assign($view);
+    }
+
+    /**
+     * 选择所属用户
+     */
+    public function selectUid(){
+        $keyword = Request::param('keyword');
+        $input   = Request::param('input');
+        $condition = [];
+        if(!empty($keyword)){
+            if(Validate::isMobile($keyword)){
+                $condition[] = ['phone_uid','=',$keyword];
+            }else{
+                $condition[] = ['nickname','like','%'.$keyword.'%'];
+            }
+        }
+        $view['list']    = SystemUser::where($this->mini_program)->where($condition)->whereNotIn('id',AisInfoMp::where($this->mini_program)->column('uid'))->order('id desc')->paginate(10,false,['query' => ['input' => $input,'keyword' => $keyword]]);
+        $view['keyword'] = $keyword;
+        $view['input']   = $input;
+        $view['id']      = $this->member_miniapp_id;
+        return view()->assign($view);
+    }
+
+    /**
+     * 认证
+     */
+    public function vip(int $id){
+        $result = AisInfoMp::where($this->mini_program)->where(['id' => $id])->field('is_vip')->find();
+        if(!$result){
+            return enjson(0);
+        }else{
+            $result->is_vip = $result->is_vip ? 0: 1;
+            $result->save();
+            return enjson(200);
+        }
+    } 
+
+    /**
+     * 锁定
+     */
+    public function lock(int $id){
+        $result = AisInfoMp::where($this->mini_program)->where(['id' => $id])->field('is_lock')->find();
+        if(!$result){
+            return enjson(0);
+        }else{
+            $result->is_lock = $result->is_lock ? 0: 1;
+            $result->save();
+            return enjson(200);
+        }
+    } 
+}

+ 119 - 0
application/ais/controller/info/Order.php

@@ -0,0 +1,119 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 同城号
+ */
+namespace app\ais\controller\info;
+use app\ais\controller\Common;
+use app\ais\model\AisInfoOrder;
+use think\facade\Request;
+use think\helper\Time;
+
+class Order extends Common{
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps',[['name'=>'订单管理','url'=>url("info.order/index")]]);
+    }
+
+    /**
+     * 列表
+     */
+    public function index(int $infoid = 0,int $types = 1){
+        $condition = [];
+        $condition[] = ['member_miniapp_id','=',$this->member_miniapp_id];
+        $condition[] = ['is_del', '=',0];
+        $view['keyword']   = Request::param('keyword/s');
+        if($view['keyword'] ){
+            $condition[] = ['phone','<=', $view['keyword']];
+        }
+        $view['starttime'] = Request::param('starttime/s');
+        $view['endtime']   = Request::param('endtime/s');
+        $view['time']      = Request::param('time/d',0);
+        if ($view['time']) {
+            switch ($view['time']) {
+                case 2:
+                    list($start, $end) = Time::yesterday();
+                    break;
+                case 30:
+                    list($start, $end) = Time::month();
+                    break;
+                case 60:
+                    list($start, $end) = Time::lastMonth();
+                    break;
+                default:
+                    list($start, $end) = Time::today();
+                    break;
+            }
+            $condition[] = ['create_time', '>=', $start];
+            $condition[] = ['create_time', '<=', $end];
+        } else {
+            if ($view['starttime']) {
+                $condition[] = ['create_time', '>=', strtotime($view['starttime'])];
+            }
+            if ($view['endtime']) {
+                $condition[] = ['create_time', '<=', strtotime($view['endtime'])];
+            }
+        }
+        $view['types']     = $types;
+        switch ($types) {
+            case 1:
+                $condition[] = ['paid_at', '=',1];
+                $condition[] = ['status', '=', 0];
+                break;
+            case 2:
+                $condition[] = ['paid_at', '=',1];
+                $condition[] = ['status', '=', 1];
+                break;
+            default:
+                $condition[] = ['paid_at', '=',0];
+                break;
+        }
+        $view['lists']   = AisInfoOrder::where($condition)->order('id desc')->paginate(20, false, ['query' => ['keyword' => $view['keyword'], 'starttime' => $view['starttime'], 'endtime' => $view['endtime'], 'time' => $view['time']]]);
+        $view['pay']     = AisInfoOrder::where($this->mini_program)->where(['paid_at' => 1])->sum('amount');
+        $view['invalid'] = AisInfoOrder::where($this->mini_program)->where(['status' => 1])->sum('amount');
+        $view['infoid']  = $infoid;
+        if($infoid){
+            $view['tabs'] = [
+                ['name' =>'信息内容','url' =>url('info.index/reply',['id' => $infoid])],
+                ['name' =>'订单列表','url' =>url('info.order/index',['infoid' => $infoid]),'action' => 1],
+            ];
+        }
+        return view()->assign($view);
+    }
+
+    /**
+     * 订单详情
+     */
+    public function detail(int $id){
+        $info         = AisInfoOrder::where(['id' => $id])->find();
+        $info->field  = json_decode($info->fields, true);
+        $view['info'] = $info;
+        return view()->assign($view);
+    }
+
+    /**
+     * 删除
+     */
+    public function delete($id){
+        $result = AisInfoOrder::update(['is_del'=>1],['id' => $id]);
+        if($result){
+            return enjson(200,'操作成功',['url' => url('index',['status' => $this->request->param('status/d')])]);
+        }
+        return enjson(0,'操作失败');
+    }
+
+    /**
+     * 订单完成
+     */
+    public function completion($id){
+        $result = AisInfoOrder::update(['status'=>1],['id' => $id]);
+        if($result){
+            return enjson(200,'操作成功',['url' => url('index',['status' => $this->request->param('status/d')])]);
+        }else{
+            return enjson(0,'操作失败');
+        }
+    }
+}

+ 115 - 0
application/ais/controller/info/Tpl.php

@@ -0,0 +1,115 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 模板管理
+ */
+namespace app\ais\controller\info;
+use app\ais\controller\Common;
+use app\ais\model\AisInfoTpl;
+use app\ais\model\AisInfoCate;
+
+class Tpl extends Common{
+
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps',[['name'=>'模板库','url'=>url("info.tpl/index")]]);
+    }
+
+    //商品规格
+    public function index(){
+        $view['lists'] = AisInfoTpl::where($this->mini_program)->order('id asc')->paginate(20);
+        $view['tabs']    = [
+            ['name' =>'主题管理','url' =>url('info.cate/index')],
+            ['name' =>'模板库','url' =>url('info.tpl/index'),'action' => 1],
+            ['name' =>'推广设置','url' =>url('setting/info')],
+        ];
+        return view('index',$view);
+    }
+
+    //规格编辑
+    public function edit(){
+        if(request()->isAjax()){
+            $data = [
+                'id'                => $this->request->param('id/d',0),
+                'name'              => $this->request->param('name/s'),
+                'note'              => $this->request->param('note/s'),
+                'titles'            => $this->request->param('title/a'),
+                'types'             => $this->request->param('types/a'),
+                'values'            => $this->request->param('values/a'),
+                'placeholder'       => $this->request->param('placeholder/a'),
+                'member_miniapp_id' => $this->member_miniapp_id,
+            ];
+            $validate = $this->validate($data,'Info.tpl');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            return AisInfoTpl::edit($data);
+        }else{
+            $id = $this->request->param('id/d',0);
+            if($id){
+                $info = AisInfoTpl::where($this->mini_program)->where(['id' => $id])->find();
+                $fields = json_decode($info->fields,true);
+                foreach ($fields as $key => $value) {
+                    if($value['types'] == 'selector'){
+                        $fields[$key]['values'] = implode('|',$value['values']);
+                    }
+                }
+                $info->fields = $fields;
+                $view['info'] = $info;
+                return view()->assign($view);
+            }else{
+                return view('add');
+            }
+        }
+    }
+
+    //规格编辑
+    public function users(){
+        if(request()->isAjax()){
+            $data = [
+                'id'                => $this->request->param('id/d',0),
+                'is_shop'           => $this->request->param('is_shop/d',0),
+                'name'              => $this->request->param('button_name/s','下单'),
+                'tips'              => $this->request->param('tips/s','下单'),
+                'titles'            => $this->request->param('title/a',[]),
+                'types'             => $this->request->param('types/a',[]),
+                'values'            => $this->request->param('values/a',[]),
+                'placeholder'       => $this->request->param('placeholder/a',[]),
+                'member_miniapp_id' => $this->member_miniapp_id,
+            ];
+            $validate = $this->validate($data,'Info.tpl');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            return AisInfoTpl::usersEdit($data);
+        }else{
+            $id = $this->request->param('id/d',0);
+            $info = AisInfoTpl::where($this->mini_program)->where(['id' => $id])->find();
+            $users = json_decode($info->users,true);
+            foreach ($users as $key => $value) {
+                if($value['types'] == 'selector'){
+                    $users[$key]['values'] = implode('|',$value['values']);
+                }
+            }
+            $info->users  = $users;
+            $view['info'] = $info;
+            return view()->assign($view);
+        }
+    }
+
+    //规格模板
+    public function delete(int $id){
+        $rel = AisInfoCate::where(['tpl_id' => $id])->find();
+        if($rel){
+            return enjson(0,'模板在【'.$rel->name.'】的信息类别中启用,禁止删除');
+        }
+        $result = AisInfoTpl::destroy(['member_miniapp_id' => $this->member_miniapp_id,'id' => $id]);
+        if($result){
+            return enjson(200,'操作成功');
+        }
+        return enjson(0);
+    }
+}

+ 42 - 0
application/ais/controller/manage/Index.php

@@ -0,0 +1,42 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 管理首页
+ */
+namespace app\ais\controller\Manage;
+use app\ais\controller\Common;
+use app\ais\model\Bank as ModelBank;
+use app\ais\model\BankBill;
+use app\ais\model\BankCash;
+use app\ais\model\Card;
+use app\ais\model\CardUser;
+use app\ais\model\CardUserOrder;
+use app\ais\model\Coupon;
+use app\ais\model\CouponUser;
+use app\ais\model\Fund;
+use app\ais\model\CouponSubsidize;
+use app\ais\model\MchIdQueen;
+use app\ais\model\Store;
+use app\ais\model\Order;
+use app\ais\model\Vip;
+use app\common\model\SystemUser;
+use think\facade\Request;
+use think\helper\Time;
+
+class Index extends Common{
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps', [['name'=>'管理首页','url'=>'javascript:;']]);
+    }
+
+    /**
+     * 应用管理首页
+     * @access public
+     */
+    public function Index(){
+        $this->redirect(url('store.index/index'));
+    }    
+}

+ 94 - 0
application/ais/controller/shop/Cate.php

@@ -0,0 +1,94 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 商品分类管理
+ */
+namespace app\ais\controller\shop;
+use app\ais\controller\Common;
+use app\ais\model\AisShopCate;
+use app\ais\model\AisShop;
+use app\ais\model\AisStore;
+
+class Cate extends Common{
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps',[['name'=>'宝贝专题','url'=>url("ais/shopCate/index")]]);
+    }
+
+    /**
+     * 列表
+     */
+    public function index(){
+        $condition = [];
+        $condition[] = ['member_miniapp_id','=',$this->member_miniapp_id];
+        $view['lists'] = AisShopCate::where($condition)->order('sort desc,id desc')->paginate(20);
+        return view()->assign($view);
+    }
+
+    //编辑
+    public function edit(){
+        if(request()->isAjax()){
+            $data = [
+                'id'                => $this->request->param('id/d',0),
+                'types'             => $this->request->param('types/d',0),
+                'show_type'         => $this->request->param('show_type/d',0),
+                'title'             => $this->request->param('title/s'),
+                'content'           => $this->request->param('content/s'),
+                'picture'           => $this->request->param('picture/s'),
+                'member_miniapp_id' => $this->member_miniapp_id,
+            ];
+            $validate = $this->validate($data,'Category.save');
+            if(true !== $validate){
+                return enjson(0,$validate);
+            }
+            $result =  AisShopCate::edit($data);
+            if($result){
+                return enjson(200,'操作成功');
+            }else{
+                return enjson(0,'操作失败');
+            }
+        }else{
+            $view['info'] = AisShopCate::where(['id' => $this->request->param('id/d'),'member_miniapp_id' => $this->member_miniapp_id])->find();
+            return view()->assign($view);
+        }
+    }
+
+    /**
+     * 排序
+     */
+    public function sort(){
+        if(request()->isAjax()){
+            $data = [
+                'sort' => $this->request->param('sort/d'),
+                'id'   => $this->request->param('id/d'),
+            ];
+            $validate = $this->validate($data,'Category.sort');
+            if(true !== $validate){
+                return enjson(0,$validate);
+            }
+            $result = AisShopCate::update(['sort'=>$data['sort'],'id' => $data['id']]);
+            if($result){
+                return enjson(200,'操作成功');
+            }else{
+                return enjson(0,'操作失败');
+            }
+        }
+    }
+
+    //删除
+    public function delete(int $id){
+        $goods =  AisShop::where(['category_id' => $id])->find();
+        if($goods){
+            return enjson(403,'删除失败,请查看是否包含商品');
+        }
+        $result = AisShopCate::destroy(['id' => $id,'member_miniapp_id' => $this->member_miniapp_id]);
+        if($result){
+            return enjson(200,'操作成功');
+        }else{
+            return enjson(403,'删除失败,请查看是否包含商品');
+        } 
+    }
+}

+ 195 - 0
application/ais/controller/shop/Index.php

@@ -0,0 +1,195 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 商品管理
+ */
+namespace app\ais\controller\shop;
+use app\ais\controller\Common;
+use app\ais\model\AisShop;
+use app\ais\model\AisShopCate;
+use app\ais\model\AisShopCoupon;
+use app\ais\model\AisCoupon;
+use app\ais\model\AisStore;
+use app\ais\model\Coupon;
+
+class Index extends Common{
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps',[['name'=>'优选宝贝','url'=>url("ais/shop/index")]]);
+    }
+
+    /**
+     * 列表
+     */
+    public function index(){
+        $condition = [];
+        $status   = $this->request->param('status');
+        switch ($status) {
+            case 'trash':       //回收站
+                $condition[] = ['is_del','=',1];
+                break; 
+            case 'off_sale': //在售
+                $condition[] = ['is_sale','=',1];
+                $condition[] = ['is_del','=',0];
+                break;           
+            case 'on_sale': //下架
+                $condition[] = ['is_sale','=',0];
+                $condition[] = ['is_del','=',0];
+                break;  
+            default:
+                $condition[] = ['is_del','=',0];
+                break;
+        }
+        $keyword  = $this->request->param('keyword');
+        if(!empty($keyword)){
+            $condition[] = ["name","like","%{$keyword}%"];
+        }
+        $cate_id  = $this->request->param('cate_id/d',0);
+        if($cate_id){
+            $condition[] = ["category_id","=",$cate_id];
+        }        
+        $view['lists']   = AisShop::where($this->mini_program)->where($condition)->order('id desc')->paginate(20,false,['query' => ['cate_id'=>$cate_id,'status' => $status,'keyword' => $keyword]]);
+        $view['keyword'] = $keyword;
+        $view['status']  = $status;
+        $view['cate_id'] = $cate_id;
+        $view['page']    = $this->request->param('page/d',0);
+        return view()->assign($view);
+    }
+
+    /**
+     * 编辑
+     */
+    public function edit(){
+        if(request()->isAjax()){
+            $param = [
+                'id'                => $this->request->param('id/d',0),
+                'store_id'          => $this->request->param('store_id/d'),
+                'category_id'       => $this->request->param('category_id/d'),
+                'types'             => $this->request->param('types/d', 0),
+                'name'              => $this->request->param('name/s'),
+                'title'             => $this->request->param('title/s'),
+                'sell_price'        => $this->request->param('sell_price/f'),
+                'market_price'      => $this->request->param('market_price/f', 0),
+                'cost_price'        => $this->request->param('cost_price/f', 0),
+                'warehouse_num'     => $this->request->param('warehouse_num/d', 0),
+                'warehouse_sellnum' => $this->request->param('warehouse_sellnum/d', 0),
+                'coupon_id'         => $this->request->param('coupon_id/d', 0),
+                'vip_price'         => $this->request->param('vip_price/f', 0),
+                'points_price'      => $this->request->param('points_price/d', 0),
+                'share_vip_price'   => $this->request->param('share_vip_price/d',0),
+                'share_price'       => $this->request->param('share_price/d',0),
+                'imgs'              => $this->request->param('imgs/a'),
+                'img'               => $this->request->param('img/s'),
+                'content'           => $this->request->param('content/s'),
+                'notice'            => $this->request->param('notice/s'),
+                'keyword'           => $this->request->param('keyword/s'),
+                'group_title'       => $this->request->param('group_title/s'),
+                'group_note'        => $this->request->param('group_note/s'),
+                'group_img'         => $this->request->param('group_img/s'),
+                'end_time'          => $this->request->param('end_time/s'),
+            ];
+            $validate = $this->validate($param,'shop.save');
+            if(true !== $validate){
+                return enjson(0,$validate);
+            }
+            $store  = AisStore::where(['id' => $param['store_id']])->field('id,citycode')->find();
+            $param['citycode']         = empty($store) ? 0:$store->citycode;
+            $param['member_miniapp_id'] = $this->member_miniapp_id;
+            $result =  AisShop::edit($param);
+            if($result){
+                return enjson(200,['url' => url('ais/shop/index')]);
+            }
+            return enjson(0);
+        }else{
+            $view['id']   = $this->request->param('id/d');
+            $view['info'] = AisShop::where(['id' => $view['id']])->find();
+            $view['cate'] = AisShopCate::where($this->mini_program)->select();
+            return view()->assign($view);
+        }
+    }
+
+     /**
+     * 删除
+     */
+    public function delete(){
+        $id  = $this->request->param('id/d',0);
+        $ids = $this->request->param('ids/s');
+        $result = AisShop::ids_delete($id,$ids);
+        if($result){
+            return enjson(200);
+        }else{
+            return enjson(403);
+        } 
+    }
+
+    /**
+     * 上架,下架,从回收站恢复
+     */
+    public function ids_action(){
+        if(request()->isAjax()){
+            $issale = $this->request->param('issale/d');
+            $ids    = $this->request->param('ids/s');
+            if(empty($ids)){
+                return enjson(403,'没有选择任何要操作商品');
+            }else{
+                AisShop::ids_action($issale,$ids,$this->member_miniapp_id);
+                return enjson(200);
+            }
+        }
+    }
+    
+    /**
+     * 商品栏目
+     */
+    public function category(){
+        if(request()->isAjax()){
+            $info = AisShopCate::where(['member_miniapp_id' => $this->member_miniapp_id,'parent_id' => $this->request->param('parent_id/d',0)])
+                ->field('id,parent_id,title')
+                ->order(['sort'=>'desc','id'=>'desc'])
+                ->select();
+            return enjson(200,'操作成功',$info);
+        }else{
+            $view['input'] = $this->request->param('input');
+            $view['path']  = $this->request->param('path');
+            return view('category',$view);
+        }
+    }
+    
+    /**
+     *返回当前路径
+     */
+    public function category_path(){
+        $info = AisShopCate::getPath($this->member_miniapp_id,$this->request->param('parent_id/d',0));
+        if($info){
+            $category = [];
+            foreach ($info as $key => $value) {
+                $category[] = $value['id'];
+            }
+            $category_id = implode(',',$category);
+            return json(['code'=>200,'msg'=>'操作成功','data'=>$info,'category_id' => $category_id]);
+        }
+        return enjson(403,'读取商品分类路径失败');
+    }
+
+    /**
+     * 计算价格
+     */
+    public function couponPrice(){
+        $coupon_id  = $this->request->param('coupon_id/d');
+        $sell_price = $this->request->param('sell_price/f');
+        $coupon     = AisCoupon::where(['id' => $coupon_id])->find();
+        if($coupon){
+            if($coupon->types == 1){
+                $coupon_user_price = $sell_price - $sell_price * $coupon->discount/10; 
+            }else{
+                $coupon_user_price = $coupon->price;
+            }
+        }else{
+            $coupon_user_price = 0;
+        }
+        return enjson(200,'成功',$coupon_user_price);
+    }
+}

+ 116 - 0
application/ais/controller/shop/Order.php

@@ -0,0 +1,116 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 订单管理
+ */
+namespace app\ais\controller\shop;
+use app\ais\controller\Common;
+use app\ais\model\AisShopOrder;
+use think\facade\Request;
+use think\helper\Time;
+
+class Order extends Common{
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps',[['name'=>'订单管理','url'=>url("ais/shopOrder/index")]]);
+    }
+
+    /**
+     * 列表
+     */
+    public function index(int $types = 1){
+        $condition = [];
+        $condition[] = ['AisShopOrder.member_miniapp_id','=',$this->member_miniapp_id];
+        $condition[] = ['AisShopOrder.is_del', '=',0];
+        $time      = Request::param('time/d',0);
+        $starttime = Request::param('starttime/s');
+        $endtime   = Request::param('endtime/s');
+        if ($time) {
+            switch ($time) {
+                case 2:
+                    list($start, $end) = Time::yesterday();
+                    break;
+                case 30:
+                    list($start, $end) = Time::month();
+                    break;
+                case 60:
+                    list($start, $end) = Time::lastMonth();
+                    break;
+                default:
+                    list($start, $end) = Time::today();
+                    break;
+            }
+            $condition[] = ['create_time', '>=', $start];
+            $condition[] = ['create_time', '<=', $end];
+        } else {
+            if ($starttime) {
+                $condition[] = ['create_time', '>=', strtotime($starttime)];
+            }
+            if ($endtime) {
+                $condition[] = ['create_time', '<=', strtotime($endtime)];
+            }
+        }
+        switch ($types) {
+            case 1:
+                $condition[] = ['paid_at', '=',1];
+                $condition[] = ['status', '=', 0];
+                break;
+            case 2:
+                $condition[] = ['paid_at', '=',1];
+                $condition[] = ['status', '=', 1];
+                break;
+            default:
+                $condition[] = ['paid_at', '=',0];
+                break;
+        }
+        $keyword  = Request::param('keyword/s');
+        $lists = AisShopOrder::hasWhere('shop', function($query) use($keyword) {
+           if($keyword){
+               $query->where('phone|name', 'like', '%'.$keyword.'%', 'or');
+           }
+        })->where($condition)->order('id desc')->paginate(20, false, ['query' => ['keyword' => $keyword, 'starttime' => $starttime, 'endtime' => $endtime, 'time' => $time]]);
+        $view['pay']       = AisShopOrder::where($this->mini_program)->where(['paid_at' => 1])->sum('amount');
+        $view['invalid']   = AisShopOrder::where($this->mini_program)->where(['status' => 1])->sum('amount');
+        $view['lists']     = $lists;
+        $view['types']     = $types;
+        $view['keyword']   = $keyword;
+        $view['time']      = $time;
+        $view['starttime'] = $starttime;
+        $view['endtime']   = $endtime;
+        return view()->assign($view);
+    }
+    
+    /**
+     * 订单详情
+     */
+    public function detail(int $id){
+        $view['info'] = AisShopOrder::where(['id' => $id])->find();
+        return view()->assign($view);
+    }
+
+    /**
+     * 删除
+     */
+    public function delete($id){
+        $result = AisShopOrder::update(['is_del'=>1],['id' => $id]);
+        if($result){
+            return enjson(200,'操作成功',['url' => url('ais/shopOrder/index',['status' => $this->request->param('status/d')])]);
+        }
+        return enjson(0,'操作失败');
+    }
+
+    /**
+     * 订单完成
+     */
+    public function force_completion($id){
+        $result = AisShopOrder::update(['status'=>1],['id' => $id]);
+        if($result){
+            return enjson(200,'操作成功',['url' => url('ais/shopOrder/index',['status' => $this->request->param('status/d')])]);
+        }else{
+            return enjson(0,'操作失败');
+        }
+    } 
+}

+ 350 - 0
application/ais/controller/store/Card.php

@@ -0,0 +1,350 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 赠品管理
+ */
+namespace app\ais\controller\store;
+use app\ais\controller\Common;
+use app\ais\model\AisCard;
+use app\ais\model\AisCardUser;
+use app\ais\model\AisCardOrder;
+use app\ais\model\AisStore;
+use app\ais\model\AisCoupon;
+use think\facade\Request;
+use think\helper\Time;
+
+class Card extends Common{
+
+    public function initialize(){
+        parent::initialize();
+        $this->assign('pathMaps', [['name'=>'商家储值','url'=>url("store.card/index")]]);
+    }
+
+    /**
+     * 列表
+     */
+    public function index(int $types = 0){
+        $condition   = [];
+        $condition[] = ['member_miniapp_id','=',$this->member_miniapp_id];
+        $time      = Request::param('time/d',0);
+        $starttime = Request::param('starttime/s');
+        $endtime   = Request::param('endtime/s');
+        if($time){
+            switch ($time) {
+                case 2:
+                    list($start, $end) = Time::yesterday();
+                    break;
+                case 30:
+                    list($start, $end) = Time::month();
+                    break;
+                case 60:
+                    list($start, $end) = Time::lastMonth();
+                    break;
+                default:
+                    list($start, $end) = Time::today();
+                    break;
+            }
+            $condition[] = ['create_time','>=',$start];
+            $condition[] = ['create_time','<=',$end];
+        }else{
+            if($starttime){
+                $condition[] = ['create_time','>=',strtotime($starttime)];
+            }
+            if($endtime){
+                $condition[] = ['create_time','<=',strtotime($endtime)];
+            }
+        }
+        $keyword = Request::param('keyword');
+        if(!empty($keyword)){
+            $condition[] = ['name','like','%'.$keyword.'%'];
+        }
+        switch ($types) {
+            case 1:
+                $condition[] = ['is_lock','=',1];
+                $condition[] = ['is_end','=',0];
+                break;
+            case 2:
+                $condition[] = ['is_end','=',1];
+                break;
+            default:
+                $condition[] = ['is_lock','=',0];
+                $condition[] = ['is_end','=',0];
+                break;
+        }
+        $view['lists']      = AisCard::where($condition)->order('update_time desc')->paginate(10);
+        $view['types']      = $types;
+        $view['time']       = $time;
+        $view['starttime']  = $starttime;
+        $view['endtime']    = $endtime;
+        $view['keyword']    = $keyword;
+        return view()->assign($view);
+    }
+
+    //编辑
+    public function edit(){
+        if(request()->isAjax()){
+            $param['id']       = $this->request->param('id/d',0);
+            $param['store_id'] = $this->request->param('store_id');
+            $param['name']     = $this->request->param('name');
+            $param['price']    = $this->request->param('price/f',0);
+            $param['amount']   = $this->request->param('amount/d',0);
+            $param['howmuch']  = $this->request->param('howmuch/f',0);
+            $param['num']      = $this->request->param('num/d');
+            $param['locktime'] = $this->request->param('locktime/s');
+            $param['tips']     = $this->request->param('tips/s');
+            $param['content']  = $this->request->param('content/s');
+            $validate = $this->validate($param,$param['id']?'Card.api':'Card.edit');
+            if(true !== $validate){
+                return enjson(403,$validate);
+            }
+            $card_rel = [];
+            if(!empty($param['id'])){
+                $card_rel = AisCard::where(['id' => $param['id']])->find();
+            }
+            $store_id = empty($card_rel) ? $param['store_id'] : $card_rel->store_id;
+            $store   = AisStore::where(['id' => $store_id])->field('id,citycode')->find();
+            //优惠券数据
+            $coupon['types']             = 3;
+            $coupon['is_lock']           = 1;
+            $coupon['name']              = $param['name'];
+            $coupon['amount']            = $param['amount'];
+            $coupon['howmuch']           = $param['howmuch'];
+            $coupon['tips']              = $param['tips'];
+            $coupon['num']               = $param['num'];
+            $coupon['member_miniapp_id'] = $this->member_miniapp_id;
+            $coupon['update_time']       = time();
+            $coupon['create_time']       = time();
+            $coupon['store_id']          = $store_id;
+            $coupon['citycode']         = $store->citycode;
+            //判断是添加还是修改
+            if(empty($card_rel)){
+                $coupon_rel = AisCoupon::create($coupon);
+                if(!$coupon_rel){
+                    return enjson(403,'储值活动创建失败');
+                }
+                $coupon_id = $coupon_rel->id;
+            }else{
+                $coupon_id = $card_rel->coupon_id;
+                $coupon_rel = AisCoupon::where(['id' => $card_rel->coupon_id])->update($coupon);
+                if(!$coupon_rel){
+                    return enjson(403,'未找到储值活动');
+                }
+            }
+            //判断是修改储值还是增加
+            $card['store_id']          = $store_id;
+            $card['member_miniapp_id'] = $this->member_miniapp_id;
+            $card['name']              = $param['name'];
+            $card['price']             = $param['price'];
+            $card['tips']              = $param['content'];
+            $card['coupon_id']         = $coupon_id;
+            $card['locktime']          = strtotime($param['locktime']);
+            $card['update_time']       = time();
+            $card['create_time']       = time();
+            if(empty($card_rel)){
+                $rel = AisCard::create($card);
+            }else{
+                $rel = AisCard::where(['id' => $card_rel->id])->update($card);
+            } 
+            if($rel){
+                return enjson(200,'储值活动创建成功');
+            }
+            return enjson(403,'未找到储值活动');
+        }else{
+            $view['info'] = AisCard::where($this->mini_program)->where(['id' => $this->request->param('id/d')])->find();
+            return view()->assign($view);
+        }
+    }
+
+    //删除
+    public function delete(int $id){
+        $card =  AisCard::where($this->mini_program)->where(['id' => $id])->find();
+        if(empty($card)){
+            return enjson(0);
+        }
+        $card->is_end = 1;
+        $card->save();
+        AisCoupon::where(['id' => $card->coupon_id])->update(['is_end' => 1]);
+        return enjson(200);
+    }
+
+     /**
+     * 置顶/取消
+     * @param integer $id 用户ID
+     */
+    public function isLock(int $id){
+        $result = AisCard::isLock($id, $this->member_miniapp_id);
+        if($result){
+            return enjson(200);
+        }
+        return enjson(0);
+    } 
+
+
+    /**
+     * ######################################################
+     * 选择赠品
+     */
+    public function coupon(int $id){
+        $coupon           = AisCard::where($this->mini_program)->where(['id' => $id])->field('coupon_ids')->find();
+        $view['lists']   = AisCoupon::where($this->mini_program)->whereIn('id',$coupon->coupon_ids)->order('sort desc,id desc')->select();
+        $view['card_id'] = $id;
+        return view()->assign($view);
+    }
+
+    /**
+     * 弹出选择优惠券
+     */
+    public function selectCoupon(int $card_id){
+        if(request()->isAjax()){
+            $ids = $this->request->param('ids');
+            if(empty($ids)){
+                return json(['code'=>0,'msg'=>'请选择要关联的赠品']);
+            }
+            $result = AisCard::editCoupon($card_id,(array)ids($ids,true));
+            if($result){
+                return json(['code'=>302,'msg'=>'关联赠品成功','data' =>[]]);
+            }else{
+                return json(['code'=>0,'msg'=>'关联赠品失败']);
+            }
+        }else{
+            $coupon     = AisCard::where($this->mini_program)->where(['id' => $card_id])->field('coupon_ids')->find();
+            $condition[] = ['is_end','=',0];
+            $condition[] = ['types','<=',2];
+            if(!empty($coupon->coupon_ids)){
+                $condition[] = ['id','notIn',explode(',',$coupon->coupon_ids)];
+            }
+            $keyword = $this->request->param('keyword');
+            if(!empty($keyword)){
+                $condition[] = ['name','like','%'.$keyword.'%'];
+            }
+            $view['lists']   = AisCoupon::where($this->mini_program)->where($condition)->order('sort desc,id desc')->paginate(20,false,['query' => ['card_id' => $card_id,'keyword'=>$keyword]]); 
+            $view['card_id'] = $card_id;
+            $view['keyword'] = $keyword;
+            return view()->assign($view);
+        }
+    }
+
+
+    //删除
+    public function delCoupon(){
+        $card_id   = $this->request->param('card_id/d');
+        $coupon_id = $this->request->param('coupon_id/d');
+        $info   = AisCard::where($this->mini_program)->where(['id' => $card_id])->find();
+        if($info){
+            $info->coupon_ids = ids(array_values_unset($coupon_id,explode(',',$info->coupon_ids)));
+            $result = $info->save(); 
+            if($result){
+                return enjson(200);
+            }
+        }
+        return enjson(0);
+    }
+
+
+
+    /**
+     * 已开通商家的会员卡用户
+     * @param integer $id  赠品ID
+     * @param integer $uid 用户ID
+     * @return void
+     */
+    public function user(){
+        $condition   = [];
+        $condition[] = ['member_miniapp_id','=',$this->member_miniapp_id];
+        $store_id  = Request::param('store_id/d', 0);
+        $time      = Request::param('time/d', 0);
+        $starttime = Request::param('starttime/s');
+        $endtime   = Request::param('endtime/s');
+        if($time){
+            switch ($time) {
+                case 2:
+                    list($start, $end) = Time::yesterday();
+                    break;
+                case 30:
+                    list($start, $end) = Time::month();
+                    break;
+                case 60:
+                    list($start, $end) = Time::lastMonth();
+                    break;
+                default:
+                    list($start, $end) = Time::today();
+                    break;
+            }
+            $condition[] = ['create_time','>=',$start];
+            $condition[] = ['create_time','<=',$end];
+        }else{
+            if($starttime){
+                $condition[] = ['create_time','>=',strtotime($starttime)];
+            }
+            if($endtime){
+                $condition[] = ['create_time','<=',strtotime($endtime)];
+            }
+        }
+        $view['pathMaps'] = [['name' => '储值用户', 'url' => url("card/user")]];
+        if (!empty($store_id)) {
+            $condition[] = ['store_id', '=', $store_id];
+        };
+        $view['carduser_num']    = AisCardUser::where($condition)->count();
+        $view['carduser_amount'] = AisCardOrder::where($condition)->where(['state' => 1])->sum('amount');
+        $view['lists']           = AisCardUser::where($this->mini_program)->order('id asc')->paginate(20);
+        $view['time']            = $time;
+        $view['starttime']       = $starttime;
+        $view['endtime']         = $endtime;
+        $view['store_id']        = $store_id;
+        return $this->fetch()->assign($view);
+    }
+
+    /**
+     * 删除某个用户的会员卡
+     * @return void
+     */
+    public function deleteUser(int $id){
+        $result = AisCardUser::where($this->mini_program)->where(['id' => $id])->delete();
+        if($result){
+            return json(['code'=>200,'msg'=>'操作成功']);
+        }else{
+            return json(['code'=>403,'msg'=>'删除失败']);
+        }
+    }
+
+   /**
+     * 选择好店
+     */
+    public function selectStore(){
+        $condition  = [];
+        $condition[] = ['is_lock','=',0];
+        $keyword  = $this->request->param('keyword');
+        if(!empty($keyword)){
+            $condition[] = ['name','like','%'.$keyword.'%'];
+        }
+        $view['input']     = $this->request->param('input','store_id');
+        $view['lists']     = AisStore::where($this->mini_program)->where($condition)->order('sort desc,id desc')->paginate(20,false,['query' => ['input' => $view['input'],'keyword'=>$keyword]]);
+        $view['keyword']   = $keyword;
+        return view()->assign($view);   
+    }
+
+    /**
+     * 选择专属赠品(用户领取赠品主送)
+     */
+    public function selectConpon(int $store_id){
+        $condition = [];
+        $keyword = $this->request->param('keyword');
+        if(!empty($keyword)){
+            $condition[] = ['name','like','%'.$keyword.'%'];
+        }
+        $condition[] = ['member_miniapp_id','=',$this->member_miniapp_id];
+        $condition[] = ['store_id','=',$store_id];
+        $condition[] = ['is_platform','=',1];
+        $condition[] = ['is_lock','=',0];
+        $condition[] = ['is_check','=',0];
+        $condition[] = ['is_shop','=',0];
+        $condition[] = ['is_vip','=',0];
+        $view['input']   = $this->request->param('input/s');
+        $view['store_id']= $store_id;
+        $view['lists']   = Coupon::where($condition)->order('sort desc,id desc')->paginate(20,false,['query' => ['input' => $view['input'],'store_id'=>$store_id,'keyword'=>$keyword]]);
+        $view['keyword'] = $keyword;
+        return view()->assign($view);
+    }
+}

+ 131 - 0
application/ais/controller/store/Cate.php

@@ -0,0 +1,131 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 行业分类
+ */
+namespace app\ais\controller\store;
+use app\ais\controller\Common;
+use app\ais\model\AisStoreCate;
+use app\ais\model\AisStore;
+
+class Cate extends Common{
+
+    public function initialize() {
+        parent::initialize();
+        $this->cate  = new AisStoreCate();
+        $this->store = new AisStore();
+    }
+
+    /**
+     * 列表
+     */
+    public function index(){
+        $view['parent_id'] = $this->request->param('parent_id/d',0);
+        $view['pathMaps']  = $this->cate->selectPath($view['parent_id']);  
+        $view['lists']     = $this->cate->where(['member_miniapp_id' => $this->member_miniapp_id,'parent_id' => $view['parent_id']])->order('sort desc,id desc')->paginate(20);
+        return view()->assign($view);
+    }
+    
+    /**
+     * 添加
+     */
+    public function add(){
+        if(request()->isAjax()){
+            $data = [
+                'member_miniapp_id' => $this->member_miniapp_id,
+                'title'             => $this->request->param('title/s'),
+                'name'              => $this->request->param('name/s'),
+                'sort'              => $this->request->param('sort/d'),
+                'parent_id'         => $this->request->param('parent_id/d'),
+                'picture'           => $this->request->param('picture/s')
+            ];
+            $validate = $this->validate($data,'Category.add');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $result =  $this->cate->edit($data);
+            if($result){
+                return json(['code'=>200,'url'=> url('store.cate/index',['parent_id'=>$data['parent_id']]),'msg'=>'操作成功']);
+            }else{
+                return json(['code'=>0,'msg'=>'操作失败']);
+            }
+        }else{
+            $view['parent_id'] = $this->request->param('parent_id/d',0);
+            $view['pathMaps']  = $this->cate->selectPath($view['parent_id']);
+            return view()->assign($view);
+        }
+    }
+
+    //编辑
+    public function edit(){
+        if(request()->isAjax()){
+            $data = [
+                'id'        => $this->request->param('id/s'),
+                'title'     => $this->request->param('title/s'),
+                'name'      => $this->request->param('name/s'),
+                'sort'      => $this->request->param('sort/d'),
+                'parent_id' => $this->request->param('parent_id/d'),
+                'picture'   => $this->request->param('picture/s'),
+            ];
+            $validate = $this->validate($data,'Category.edit');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $result =  $this->cate->edit($data);
+            if($result){
+                return json(['code'=>200,'url'=>url('store.cate/index',['parent_id'=>$data['parent_id']]),'msg'=>'操作成功']);
+            }else{
+                return json(['code'=>0,'msg'=>'操作失败']);
+            }
+        }else{
+            $view['info'] = $this->cate->where(['id' => $this->request->param('id/d'),'member_miniapp_id' => $this->member_miniapp_id])->find();
+            if(empty($view['info'])){
+                $this->error("404 NOT FOUND");
+            }
+            $view['pathMaps'] = $this->cate->selectPath($view['info']->parent_id);  
+            return $this->fetch()->assign($view);
+        }
+    }
+
+    /**
+     * 排序
+     */
+    public function sort(){
+        if(request()->isAjax()){
+            $data = [
+                'sort' => $this->request->param('sort/d'),
+                'id'   => $this->request->param('id/d'),
+            ];
+            $validate = $this->validate($data,'Category.sort');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $result = $this->cate->save(['sort'=>$data['sort']],['id' => $data['id']]);
+            if($result){
+                return json(['code'=>200,'msg'=>'操作成功']);
+            }else{
+                return json(['code'=>0,'msg'=>'操作失败']);
+            }
+        }
+    }
+
+    //删除
+    public function delete(int $id){
+        $info =  $this->cate->where(['parent_id' => $id])->find();
+        if($info){
+            return json(['code'=>403,'msg'=>'删除失败,请查看是否包含子栏目']);
+        }
+        $store = $this->store->where(['cate_id' => $id])->find();
+        if($store){
+            return json(['code'=>403,'msg'=>'删除失败,栏目中还包含好店']);
+        }
+        $result = $this->cate->where(['id'=>$id,'member_miniapp_id' => $this->member_miniapp_id])->delete();
+        if($result){
+            return json(['code'=>200,'msg'=>'操作成功']);
+        }else{
+            return json(['code'=>403,'msg'=>'删除失败,请查看是否包含子栏目']);
+        } 
+    }
+}

+ 95 - 0
application/ais/controller/store/Chain.php

@@ -0,0 +1,95 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 门店管理
+ */
+namespace app\ais\controller\store;
+use app\ais\controller\Common;
+use app\ais\model\AisStoreCate;
+use app\ais\model\AisStore;
+use app\ais\model\AisStoreChain;
+
+class Chain extends Common{
+
+    public function initialize() {
+        parent::initialize();
+        $this->cate  = new AisStoreCate();
+        $this->store = new AisStore();
+    }
+
+    /**
+     * 连锁门店
+     */
+    public function index(int $store_id){
+        $view['info']     = AisStore::where(['id' => $store_id])->find();
+        $view['lists']    = AisStoreChain::where(['store_id' => $store_id])->order('sort desc,id desc')->paginate(20);
+        $view['store_id'] = $store_id;
+        return view()->assign($view);
+    }
+
+
+    //编辑
+    public function edit(int $store_id){
+        if(request()->isAjax()){
+            $data = [
+                'store_id'          => $store_id,
+                'id'                => $this->request->param('id/d',0),
+                'title'             => $this->request->param('title/s'),
+                'address'           => $this->request->param('address/s'),
+                'longitude'         => $this->request->param('longitude/s'),
+                'latitude'          => $this->request->param('latitude/s'),
+                'telphone'          => $this->request->param('telphone/s'),
+                'update_time'       => time(),
+                'member_miniapp_id' => $this->member_miniapp_id
+            ];
+            $validate = $this->validate($data,'Store.chain');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            if($data['id']){
+                $rel = AisStoreChain::update($data);
+            }else{
+                $rel = AisStoreChain::create($data);
+            }
+            if($rel){
+                return enjson(200);
+            }
+            return enjson(0);
+        }else{
+            $view['id']       = $this->request->param('id/d',0);
+            $view['info']     = AisStoreChain::where(['store_id' => $store_id,'id' => $view['id']])->find();
+            $view['store_id'] = $store_id;
+            return view()->assign($view);
+        }
+    }
+
+    //删除
+    public function delete(int $id){
+        AisStoreChain::where($this->mini_program)->where(['id' =>$id])->delete();   //删除好店
+        return json(['code'=>200,'msg'=>'操作成功']);
+    } 
+
+    /**
+     * 门店排序
+     */
+    public function sort(){
+        if(request()->isAjax()){
+            $data = [
+                'sort' => $this->request->param('sort/d'),
+                'id'   => $this->request->param('id/d'),
+            ];
+            $validate = $this->validate($data,'Category.sort');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $result = AisStoreChain::where(['id' => $data['id']])->update(['sort' => $data['sort']]);
+            if($result){
+                return enjson(200);
+            }
+            return enjson(0);
+        }
+    }
+
+}

+ 186 - 0
application/ais/controller/store/Group.php

@@ -0,0 +1,186 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 行业分类
+ */
+namespace app\ais\controller\store;
+use app\ais\controller\Common;
+use app\ais\model\AisConfig;
+use app\ais\model\AisOrder;
+use app\ais\model\AisStoreGroup;
+use app\ais\model\AisStore;
+use app\ais\model\AisStoreUnion;
+use think\Db;
+use think\facade\Request;
+use think\helper\Time;
+
+class Group extends Common{
+
+    /**
+     * 列表
+     */
+    public function index(){
+        $view['lists']    = AisStoreGroup::where(['member_miniapp_id' => $this->member_miniapp_id])->order('id desc')->paginate(20);
+        $view['pathMaps'] = [['name'=>'商圏管理','url'=> url("group/index")]];
+        return $this->fetch()->assign($view);
+    }
+
+    /**
+     * 已绑定商圏列表
+     */
+    public function store(int $id){
+        $view['quan_id']  = $id;
+        $view['lists']    = AisStore::where($this->mini_program)->whereIn('id',AisStoreUnion::where($this->mini_program)->where(['group_id' => $id])->column('store_id'))->order('id desc')->paginate(20);
+        $view['pathMaps'] = [['name'=>'商圏管理','url'=> url("group/index")],['name'=>'商圈商户','url'=> url("group/storeindex",['id' => $id])]];
+        return $this->fetch()->assign($view);
+    }
+
+    /**
+     * 商圏列表
+     */
+    public function selectStore(int $quan_id){
+        $condition   = [];
+        $condition[] = ['member_miniapp_id', '=', $this->member_miniapp_id];
+        if(request()->isAjax()){
+            $ids     = $this->request->param('ids');
+            if(empty($ids)){
+                return json(['code'=>0,'msg'=>'请选择要入住商圏的好店']);
+            }
+            $list = AisStore::where($condition)->whereIn('id',$ids)->whereNotIn('id',AisStoreUnion::where($this->mini_program)->where(['group_id'=>$quan_id,'type' => 0])->whereIn('store_id',$ids)->column('store_id'))->select();
+            foreach ($list as $info){
+                $config = AisConfig::getConfig($this->member_miniapp_id);
+                $member = AisStoreUnion::where(['member_miniapp_id' => $this->member_miniapp_id,'group_id' => $quan_id,'type' => 0])->select();
+                if(!empty($config->group_member) && count($member) >=$config->group_member){
+                    return enjson(403,'商圈只能有'.$config->group_member.'个成员');
+                }
+                $size = AisStoreUnion::where(['member_miniapp_id' => $this->member_miniapp_id,'store_id' => $info->id,'type' => 0])->select();
+                if(!empty($config->group_join) && count($size) >=$config->group_join){
+                    return enjson(403,'只能加入'.$config->group_join.'个商圈');
+                }
+                $union = AisStoreUnion::where(['member_miniapp_id'=>$this->member_miniapp_id,'store_id' => $info->id,'group_id' => $quan_id,'type' => 1])->find();
+                if($union){
+                    $union->delete();
+                }
+                AisStoreUnion::create(['member_miniapp_id'=>$this->member_miniapp_id,'store_id' => $info->id,'group_id' => $quan_id,'type' => 0,'create_time' => time(),'update_time' => time()]);
+            }
+            return json(['code'=>200,'msg'=>'好店入住商圏成功','data' =>[]]);
+        }else{
+            $keyword  = $this->request->param('keyword');
+            if(!empty($keyword)) {
+                $condition[] = ['name', 'like', '%' . $keyword . '%'];
+            }
+            $view['lists']   = AisStore::where($condition)->whereNotIn('id',AisStoreUnion::where($this->mini_program)->where(['group_id'=>$quan_id,'type' => 0])->column('store_id'))->order('id desc')->paginate(20);
+            $view['keyword'] = $keyword;
+            $view['quan_id'] = $quan_id;
+            return $this->fetch()->assign($view);
+        }
+    }
+
+    //编辑
+    public function edit(){
+        if(request()->isAjax()){
+            $param = [
+                'id'      => $this->request->param('id/d', 0),
+                'title'   => $this->request->param('title/s'),
+                'face'    => $this->request->param('face/s'),
+                'content' => $this->request->param('content/s'),
+                'uid'     => $this->request->param('uid/d'),
+            ];
+            $validate = $this->validate($param,'Group.edit');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $result =  AisStoreGroup::where(['member_miniapp_id' => $this->member_miniapp_id,'id' =>  $param['id']])->find();
+            if($result){
+                $result->title   = $param['title'];
+                $result->content = $param['content'];
+                $result->uid     = $param['uid'];
+                $result->face    = $param['face'];
+                $result->save();
+            }else{
+                $info =  AisStoreGroup::where(['member_miniapp_id' => $this->member_miniapp_id,'uid' =>  $param['uid']])->find();
+                if($info){
+                    return json(['code'=>403,'msg'=>'只能管理一个商圈']);
+                }
+                $param['member_miniapp_id'] = $this->member_miniapp_id;
+                AisStoreGroup::create($param);
+            }
+            return json(['code'=>200,'url'=>url('group/index'),'msg'=>'操作成功']);
+        }else{
+            $view['info']= AisStoreGroup::where(['id' => $this->request->param('id/d',0),'member_miniapp_id' => $this->member_miniapp_id])->find();
+            return $this->fetch()->assign($view);
+        }
+    }
+
+    //删除商圈
+    public function delete(int $id){
+        $store = AisStoreGroup::where(['member_miniapp_id' => $this->member_miniapp_id])->whereIn('id',AisStoreUnion::where($this->mini_program)->where(['group_id' => $id,'type' => 0])->column('group_id'))->find();
+        if($store){
+            return json(['code'=>403,'msg'=>'删除失败,商圏中还包含店铺']);
+        }
+        $result = AisStoreGroup::destroy($id);
+        if($result){
+            return json(['code'=>200,'msg'=>'操作成功']);
+        }else{
+            return json(['code'=>403,'msg'=>'删除失败']);
+        } 
+    }
+
+    //从商圏中删除好店
+    public function deleteStore(int $id,$quan_id){
+        $result = AisStoreUnion::destroy(['store_id' => $id,'group_id' => $quan_id]);
+        if($result){
+            return json(['code'=>200,'msg'=>'操作成功']);
+        }
+        return json(['code'=>403,'msg'=>'删除失败']);
+    }
+
+    /**
+     * 商圏用户订单
+     * @access public
+     */
+    public function order(int $state = 1,int $group_id){
+        $condition   = [];
+        $condition[] = ['member_miniapp_id', '=',$this->member_miniapp_id];
+        $condition[] = ['group_id', '=', $group_id];
+        $time = Request::param('time/d',0);
+        if($time){
+            switch ($time) {
+                case 2:
+                    list($start, $end) = Time::yesterday();
+                    break;
+                case 30:
+                    list($start, $end) = Time::month();
+                    break;
+                case 60:
+                    list($start, $end) = Time::lastMonth();
+                    break;
+                default:
+                    list($start, $end) = Time::today();
+                    break;
+            }
+            $condition[] = ['paid_time','>=',$start];
+            $condition[] = ['paid_time','<=',$end];
+        }
+        $starttime = Request::param('starttime/s');
+        if($starttime){
+            $condition[] = ['paid_time','>=',strtotime($starttime)];
+        }
+        $endtime   = Request::param('endtime/s');
+        if($endtime){
+            $condition[] = ['paid_time','<=',strtotime($endtime)];
+        }
+        $view['orders']          = AisOrder::where(['state' => $state ? 1 : 0])->whereIn('store_id',AisStoreUnion::where($condition)->column('store_id'))->order('id desc')->paginate(20, false, ['query' => ['time' => $time, 'starttime' => $starttime, 'endtime' => $endtime, 'group_id' => $group_id]]);
+        $view['order_num']       = AisOrder::where(['state' => 1])->whereIn('store_id',AisStoreUnion::where($condition)->column('store_id'))->count();
+        $view['user_amount']     = AisOrder::where(['state' => 1])->whereIn('store_id',AisStoreUnion::where($condition)->column('store_id'))->sum('amount');
+        $view['order_amount']    = AisOrder::where(['state' => 1])->whereIn('store_id',AisStoreUnion::where($condition)->column('store_id'))->sum('price');
+        $view['coupon_price']    = money($view['user_amount'] - $view['order_amount']);
+        $view['time']            = $time;
+        $view['starttime']       = $starttime;
+        $view['endtime']         = $endtime;
+        $view['group_id']        = $group_id;
+        return view()->assign($view);
+    }
+}

+ 356 - 0
application/ais/controller/store/Index.php

@@ -0,0 +1,356 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 商店管理
+ */
+namespace app\ais\controller\store;
+use app\ais\model\AisStoreWorker;
+use app\common\facade\AliApi;
+use app\common\model\SystemUser;
+use app\ais\controller\Common;
+use app\ais\model\AisCoupon;
+use app\ais\model\AisStoreCate;
+use app\ais\model\AisStore;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisOrder;
+use app\ais\model\AisConfig;
+use app\common\facade\Inform;
+use think\helper\Time;
+use think\facade\Request;
+use think\facade\Validate;
+
+class Index extends Common{
+
+    public function initialize(){
+        parent::initialize();
+        $this->assign('pathMaps',[['name'=>'商家管理','url'=>url("ais/store.index/index")]]);
+    }
+
+    /**
+     * 列表
+     */
+    public function index(int $types = 0){
+        $condition   = [];
+        $time      = Request::param('time/d',0);
+        $starttime = Request::param('starttime/s');
+        $endtime   = Request::param('endtime/s');
+        if($time){
+            switch ($time) {
+                case 2:
+                    list($start, $end) = Time::yesterday();
+                    break;
+                case 30:
+                    list($start, $end) = Time::month();
+                    break;
+                case 60:
+                    list($start, $end) = Time::lastMonth();
+                    break;
+                default:
+                    list($start, $end) = Time::today();
+                    break;
+            }
+            $condition[] = ['create_time','>=',$start];
+            $condition[] = ['create_time','<=',$end];
+        }else{
+            if($starttime){
+                $condition[] = ['create_time','>=',strtotime($starttime)];
+            }
+            if($endtime){
+                $condition[] = ['create_time','<=',strtotime($endtime)];
+            }
+        }
+        $keyword = Request::param('keyword/s');
+        if(!empty($keyword)){
+            $condition[] = ['name','like','%'.$keyword.'%'];
+        }
+        if($types){
+            $condition[] = ['is_lock','=',$types == 2 ? 1 : 0];
+        }
+        $view['lists']      = AisStore::where($this->mini_program)->where($condition)->order('is_top desc,sort desc,id desc')->paginate(20,false,['query' => ['types' => $types,'starttime' => $starttime,'endtime' => $endtime,'time'=>$time]]);
+        $view['keyword']    = $keyword;
+        $view['types']      = $types;
+        $view['time']       = $time;
+        $view['starttime']  = $starttime;
+        $view['endtime']    = $endtime;
+        return view()->assign($view);
+    }
+
+
+    /**
+     * 好店预览
+     */
+    public function review(int $id){
+        $condition['id'] = $id;
+        $view['info']   = AisStore::where($condition)->find();
+        if(!$view['info']){
+            $this->error('内容不存在');
+        }
+        $view['user']   = AisStoreWorker::where($this->mini_program)->where(['store_id' => $id])->order('id desc')->select();
+        $view['manage'] = SystemUser::where($this->mini_program)->where(['id' => $view['info']['manage_uid']])->find();
+        $view['orders']  = AisOrder::where($this->mini_program)->where(['store_id'=>$id,'state' => 1])->order('id desc')->paginate(10,false,['query' => ['id' => $id]]);
+        return view()->assign($view);
+    }
+    
+    //编辑
+    public function edit(){
+        if(request()->isAjax()){
+            $param = [
+                'member_miniapp_id' => $this->member_miniapp_id,
+                'id'                => Request::param('id/d'),
+                'manage_uid'        => Request::param('manage_uid/d',0),
+                'cate_id'           => Request::param('cate_id/d',0),
+                'cate_sid'          => Request::param('cate_sid/d',0),
+                'province'          => Request::param('province/d'),
+                'city'              => Request::param('city/d'),
+                'district'          => Request::param('district/d'),
+                'citycode'          => Request::param('citycode/d'),
+                'name'              => Request::param('name/s'),
+                'address'           => Request::param('address/s'),
+                'longitude'         => Request::param('longitude/s'),
+                'latitude'          => Request::param('latitude/s'),
+                'telphone'          => Request::param('telphone/s'),
+                'img'               => Request::param('img/s'),
+                'imgs'              => Request::param('imgs/a'),
+                'mch_id'            => Request::param('mch_id/s'),
+                'tags'              => Request::param('tags/s'),
+                'charge'            => Request::param('charge/f'),
+            ];
+            $validate = $this->validate($param,'Store.edit');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $condition[] = ['manage_uid','=',$param['manage_uid']];
+            if($param['id']){
+                $condition[] = ['id','<>',$param['id']];
+            }
+            $store = AisStore::where($condition)->find();  
+            if($store){
+                return json(['code'=>0,'msg'=>'禁止绑定,设置的店长已属于['.$store->name.']的店长']);
+            }
+            $param['citypath'] = [
+                'province' => $param['province'],
+                'city'     => $param['city'],
+                'district' => $param['district'],
+            ];
+            $store_id = AisStore::edit($param);
+            return json(['code'=>200,'url'=>url('store/index',['cate_id' => $param['cate_id']]),'msg'=>'操作成功']);
+        }else{
+            $view['info']     = AisStore::where($this->mini_program)->where(['id' => $this->request->param('id/d')])->find();
+            $view['cate']     = AisStoreCate::where($this->mini_program)->where(['parent_id' => 0])->field('name,id')->order('sort desc,id desc')->select();
+            $view['setting']  = AisConfig::getConfig($this->member_miniapp_id);
+            $view['cate_sub'] = [];
+            if($view['info']){
+                $view['cate_sub'] = AisStoreCate::where($this->mini_program)->where(['parent_id' => $view['info']->cate_id])->field('name,id')->order('sort desc,id desc')->select();
+            }
+            return view()->assign($view);
+        }
+    }
+     
+    /**
+     * 排序
+     */
+    public function sort(){
+        if(request()->isAjax()){
+            $data = [
+                'sort' => $this->request->param('sort/d'),
+                'id'   => $this->request->param('id/d'),
+            ];
+            $validate = $this->validate($data,'Category.sort');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $result = AisStore::where(['id' => $data['id']])->update(['sort' => $data['sort']]);
+            if($result){
+                return json(['code'=>200,'msg'=>'操作成功']);
+            }else{
+                return json(['code'=>0,'msg'=>'操作失败']);
+            }
+        }
+    }
+    
+    /**
+     * 置顶/取消
+     * @param integer $id 用户ID
+     */
+    public function isTop(int $id){
+        $result = AisStore::isTop($id);
+        if(!$result){
+            return json(['code'=>0,'message'=>'操作失败']);
+        }else{
+            return json(['code'=>200,'message'=>'操作成功']);
+        }
+    } 
+
+     /**
+     * 置顶/取消
+     * @param integer $id 用户ID
+     */
+    public function isLock(int $id){
+        $result = AisStore::isLock($id,$this->member_miniapp_id);
+        if(!$result){
+            return json(['code'=>0,'message'=>'操作失败']);
+        }else{
+            return json(['code'=>200,'message'=>'操作成功']);
+        }
+    } 
+   
+    //删除
+    public function delete(int $id){
+        $coupon = AisCoupon::where($this->mini_program)->where(['store_id' => $id])->count();
+        if($coupon){
+            return json(['code'=>403,'msg'=>'请先删除好店优惠券']);
+        }
+        $couponUser =  AisCouponUser::where($this->mini_program)->where(['store_id' => $id])->count();
+        if($couponUser){
+            return json(['code'=>403,'msg'=>'请先删除用户已领优惠券']);
+        }
+        AisStore::where($this->mini_program)->where(['id' => $id])->delete();   //删除好店
+        return json(['code'=>200,'msg'=>'操作成功']);
+    }
+
+    
+    /**
+     * 读取好店分类
+     * @return void
+     */
+    public function storecate(int $cate_id){
+        $cate = AisStoreCate::where(['member_miniapp_id' => $this->member_miniapp_id,'parent_id' => $cate_id])->field('id,name')->order('sort desc,id desc')->select(); 
+        return json(['code'=>200,'msg'=>'成功','data' => $cate]);
+    }
+ 
+    /**
+     *  根据地址位置转账
+     * @return void
+     */
+    public function baidu($address){
+        $view['address']  = $address;
+        $this->view->engine->layout(false);
+        return view()->assign($view);
+    }   
+
+    /**
+     *  根据地址位置读取地址
+     * @return void
+     */
+    public function maps($address){
+        $rel = AliApi::address($address);
+        if(!$rel){
+            return enjson(0,'请确认是否帐号欠费');
+        }
+        $address = $rel['geocodes'][0];
+        $location =  explode(',',$address['location']);
+        return enjson(200,'成功',$location);
+    }
+
+    /**
+     * 选择商家列表
+     */
+    public function selectStore($select_uid = 0){
+        $condition = [];
+        $condition[] = ['is_lock','=',0];
+        $view['keyword'] = $this->request->param('keyword/s');
+        if(!empty($view['keyword'])){
+            $condition[] = ['name','like','%'.$view['keyword'].'%'];
+        }
+        $view['lists']      = AisStore::where($this->mini_program)->where($condition)->order('is_top desc,sort desc,id desc')->paginate(20);
+        $view['input']      = $this->request->param('input');
+        $view['select_uid'] = $select_uid;
+        return view()->assign($view);
+    }
+   
+
+    /**
+     * 选择所属用户
+     */
+    public function selectUid(){
+        $view['keyword'] = Request::param('keyword');
+        $view['input']   = Request::param('input');
+        $condition = [];
+        if(!empty($view['keyword'])){
+            if(Validate::isMobile($view['keyword'])){
+                $condition[] = ['phone_uid','=',$view['keyword']];
+            }else{
+                $condition[] = ['nickname','like','%'.$view['keyword'].'%'];
+            }
+        }
+        $view['list'] = SystemUser::where($this->mini_program)->where($condition)->whereNotIn('id',AisStore::where($this->mini_program)
+                    ->column('manage_uid'))->order('id desc')
+                    ->paginate(10,false,['query' => ['input' => $view['input'],'keyword' => $view['keyword']]]);
+        return view()->assign($view);
+    }
+
+
+    /**
+     * 给好店添加管理员
+     */
+    public function winUser(int $store_id){
+        if(request()->isAjax()){
+            $ids = Request::param('ids/s');
+            if(empty($ids)){
+                return json(['code'=>0,'msg'=>'请选择要关联的员工']);
+            }
+            $uid = (array)ids($ids,true);
+            $worker_uid = AisStoreWorker::where($this->mini_program)->where(['uid' => $uid])->column('uid'); //查询添加的用户是否在其它点做员工
+            $uid = array_diff($uid,$worker_uid);//如果存在就去重
+            $data = [];
+            foreach ($uid as $key => $value) {
+                $data[$key]['member_miniapp_id'] = $this->member_miniapp_id;
+                $data[$key]['uid']               = $value;
+                $data[$key]['store_id']          = $store_id;
+            }
+            $result = AisStoreWorker::insertAll($data);
+            if($result){
+                //批量添加的员工为当前店铺的会员
+                foreach ($data as $key => $value) {
+                    //通知到申请者微信
+                    Inform::sms($value['uid'],$this->member_miniapp_id,['title' =>'业务进展通知','type' => '身份变更','state' => '成功','content' =>'您的身份已变更为员工']);
+                }
+                return json(['code'=>200,'msg'=>'添加员工成功','data' =>[]]);
+            }else{
+                return json(['code'=>0,'msg'=>'添加员工失败']);
+            }
+        }else{
+            //读好好店员工和好店老板的UID,做筛查排除
+            $uid = AisStoreWorker::where($this->mini_program)->column('uid');       //好店员工
+            $keyword  = Request::param('keyword');
+            $condition  = [];
+            $condition[] = ['id','NOT IN',$uid];
+            if(!empty($keyword)){
+                if(Validate::isMobile($keyword)){
+                    $condition[] = ['phone_uid','=',$keyword];
+                }else{
+                    $condition[] = ['nickname','LIKE','%'.$keyword.'%'];
+                }
+            }
+            $view['list']     = SystemUser::where($this->mini_program)->where($condition)->order('id desc')->paginate(20,false,['query' => ['store_id' => $store_id]]);
+            $view['store_id'] = $store_id;
+            $view['keyword']  = $keyword;
+            return view()->assign($view);
+        }
+    }
+
+    //删除员工
+    public function delUser(int $id){
+        $result = AisStoreWorker::where($this->mini_program)->where(['uid' => $id])->delete();
+        if($result){
+            return json(['code'=>200,'msg'=>'操作成功']);
+        }else{
+            return json(['code'=>403,'msg'=>'删除失败']);
+        }
+    }
+
+    /**
+     * 设置好店收银员
+     * @param integer $id 用户ID
+     */
+    public function isCashier(int $id){
+        $result = AisStoreWorker::setWorker($id);
+        if(!$result){
+            return json(['code'=>0,'message'=>'操作失败']);
+        }else{
+            return json(['code'=>200,'message'=>'操作成功']);
+        }
+    }
+}

+ 81 - 0
application/ais/controller/vip/Coupon.php

@@ -0,0 +1,81 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 会员设置
+ */
+namespace app\ais\controller\vip;
+use app\ais\controller\Common;
+use app\ais\model\AisVip;
+use app\ais\model\AisCoupon;
+
+class Coupon extends Common{
+
+    public $mini_program   = []; 
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps',[['name'=>'会员组','url'=>url("vip.index/index")],['name'=>'优惠券','url'=>url("vip.coupon/index")]]);
+    }
+
+    /**
+     * 列表
+     */
+    public function index(int $id){
+        $condition = [];
+        $vip = AisVip::where(['id' => $id,'member_miniapp_id' => $this->member_miniapp_id])->where($condition)->field('coupon_ids')->find();
+        if(empty($vip)){
+            $this->error('没有找到对应会员类型');
+        }
+        $view['lists']  = AisCoupon::where($this->mini_program)->whereIn('id',$vip->coupon_ids)->order('sort desc,id desc')->paginate(20,false,['query' => ['id' => $id]]);
+        $view['id']     = $id;
+        return view()->assign($view);
+    }
+
+
+    /**
+     * 弹出选择优惠券
+     */
+    public function coupon(int $id){
+        if(request()->isAjax()){
+            $ids = $this->request->param('ids/s');
+            if(empty($ids)){
+                return json(['code'=>0,'msg'=>'请选择要关联的优惠券']);
+            }
+            $result = AisVip::editCoupon($id,ids($ids,true));
+            if($result){
+                return json(['code'=>302,'msg'=>'关联优惠券成功','data' =>[]]);
+            }else{
+                return json(['code'=>0,'msg'=>'关联优惠券失败']);
+            }
+        }else{
+            $coupon      = AisVip::where($this->mini_program)->where(['id' => $id])->field('coupon_ids')->find();
+            $coupon_ids  = [];
+            if($coupon->coupon_ids){
+                $coupon_ids = explode(',',$coupon->coupon_ids);
+            }
+            $keyword = $this->request->param('keyword');
+            if(empty($keyword)){
+                $sql = AisCoupon::where($this->mini_program);
+            }else{
+                $sql = AisCoupon::where($this->mini_program)->whereLike('name','%'.$keyword.'%'); 
+            }
+            $view['lists']   = $sql->whereNotIn('id',$coupon_ids)->where(['is_end' => 0])->order('id desc')->paginate(10,false,['query' => ['id' => $id,'keyword'=>$keyword]]); 
+            $view['id']      = $id;
+            $view['keyword'] = $keyword;
+            return view()->assign($view);
+        }
+    }
+
+   //删除
+   public function delete(int $id,int $coupon_id){
+        $result   = AisVip::where($this->mini_program)->where(['id' => $id])->find();
+        if($result){
+            $result->coupon_ids =  ids(array_values_unset($coupon_id,explode(',',$result->coupon_ids)));
+            $result->save();
+            return enjson(200);
+        }
+        return enjson(0);
+    }
+}

+ 125 - 0
application/ais/controller/vip/Index.php

@@ -0,0 +1,125 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 会员设置
+ */
+namespace app\ais\controller\vip;
+use app\ais\controller\Common;
+use app\ais\model\AisVip;
+use app\ais\model\AisVipUser;
+
+class Index extends Common{
+
+    public $mini_program   = []; 
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps',[['name'=>'会员组','url'=>url("vip.index/index")]]);
+    }
+
+    /**
+     * 列表
+     */
+    public function index(){
+        $view['lists'] = AisVip::where($this->mini_program)->order('sort desc,id desc')->paginate(20);
+        return view()->assign($view);
+    }
+
+    //编辑
+    public function edit(){
+        if(request()->isAjax()){
+            $param = [
+                'name'              => $this->request->param('name/s'),
+                'price'             => $this->request->param('price/f'),
+                'rule'              => $this->request->param('rule'),
+                'fund'              => $this->request->param('fund/d',0),
+                'open_queue_reward' => $this->request->param('open_queue_reward/f',0),
+                'open_share_reward' => $this->request->param('open_share_reward/f',0),
+                'pay_queue_reward'  => $this->request->param('pay_queue_reward/d',0),
+                'pay_share_reward'  => $this->request->param('pay_share_reward/d',0),
+                'open_store_num'    => $this->request->param('open_store_num/d',0),
+                'open_vip_num'      => $this->request->param('open_vip_num/d',0),
+                'is_auto_up'        => $this->request->param('is_auto_up/d',0),
+                'member_miniapp_id' => $this->member_miniapp_id
+            ];
+            $validate = $this->validate($param,'Vip.edit');
+            if(true !== $validate){
+                return enjson(0,$validate);
+            }
+            $id = $this->request->param('id/d',0);
+            if($id){
+                $result = AisVip::where(['id' => $id,'member_miniapp_id' => $this->member_miniapp_id])->update($param);
+            }else{
+                $param['update_time']       = time();
+                $param['member_miniapp_id'] = $this->member_miniapp_id;
+                $result = AisVip::create($param);
+            }
+            if($result){
+                return enjson(200,['url' => url("vip.index/index")]);
+            }
+            return enjson(0);
+        }else{
+            $view['info'] = AisVip::where(['id' => $this->request->param('id/d',0)])->find();
+            return view()->assign($view);
+        }
+    }
+
+    /**
+     * 排序
+     */
+    public function sort(){
+        if(request()->isAjax()){
+            $data = [
+                'sort' => $this->request->param('sort/d'),
+                'id'   => $this->request->param('id/d'),
+            ];
+            $validate = $this->validate($data,'Category.sort');
+            if(true !== $validate){
+                return json(['code'=>0,'msg'=>$validate]);
+            }
+            $result = AisVip::where(['id' => $data['id'],'member_miniapp_id' => $this->member_miniapp_id])->update(['sort'=>$data['sort']]);
+            if($result){
+                return enjson(200);
+            }
+            return enjson(0);
+        }
+    }
+
+    /**
+     * 是否自读升级
+     * @param integer $id 用户ID
+     */
+    public function isAutoUp(int $id){
+        AisVip::where(['member_miniapp_id' => $this->member_miniapp_id])->update(['is_auto_up' => 1]);
+        if(AisVip::where(['member_miniapp_id' => $this->member_miniapp_id,'id' => $id])->update(['is_auto_up' => 0])){
+            return enjson(200);
+        }
+        return enjson(0);
+    } 
+
+    /**
+     * 是否自读升级
+     * @param integer $id 用户ID
+     */
+    public function isLock(int $id){
+        $rel = AisVip::where(['member_miniapp_id' => $this->member_miniapp_id,'id' => $id])->find();
+        $rel->is_lock = !$rel->is_lock;
+        $rel->save();
+        return enjson(200);
+    } 
+
+    //删除
+    public function delete(int $id){
+        $rel = AisVipUser::where($this->mini_program)->where(['vip_id' => $id])->find();
+        if($rel){
+            return enjson(0,'会员组已有会员开通,建议禁止');
+        }
+        $result = AisVip::where($this->mini_program)->where(['id' => $id])->delete();
+        if($result){
+            return enjson(200);
+        }
+        return enjson(0);
+    }
+}

+ 152 - 0
application/ais/controller/vip/User.php

@@ -0,0 +1,152 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 创客管理
+ */
+namespace app\ais\controller\vip;
+use app\common\model\SystemUser;
+use app\common\facade\Inform;
+use think\facade\Request;
+use think\facade\Validate;
+use think\helper\Time;
+use app\ais\controller\Common;
+use app\ais\model\AisVip;
+use app\ais\model\AisVipUser;
+
+class User extends Common{
+
+    public function initialize() {
+        parent::initialize();
+        $this->assign('pathMaps',[['name'=>'会员设置','url'=>url("vip.user/index")]]);
+    }
+
+    /**
+     * 
+     * @param int $types
+     * @param int $vip_id
+     * @return type
+     */
+    public function index(int $types = 0,int $vip_id = 0){
+        $time      = Request::param('time/d',0);
+        $starttime = Request::param('starttime/s');
+        $endtime   = Request::param('endtime/s');
+        $condition[] = ['is_lock','=',$types ? 1 : 0];
+        if($time){
+            switch ($time) {
+                case 2:
+                    list($start, $end) = Time::yesterday();
+                    break;
+                case 30:
+                    list($start, $end) = Time::month();
+                    break;
+                case 60:
+                    list($start, $end) = Time::lastMonth();
+                    break;
+                default:
+                    list($start, $end) = Time::today();
+                    break;
+            }
+            $condition[] = ['update_time','>=',$start];
+            $condition[] = ['update_time','<=',$end];
+        }else{
+            if($starttime){
+                $condition[] = ['update_time','>=',strtotime($starttime)];
+            }
+            if($endtime){
+                $condition[] = ['update_time','<=',strtotime($endtime)];
+            }
+        }
+        //查询内容
+        $view['vip']  = AisVip::where($this->mini_program)->order('sort desc,id desc')->select();
+        $view['info'] = [];
+        $view['pathMaps'][]   = ['name'=>' 会员列表','url'=>url('ais/vip.user/index')];
+        if($vip_id){
+            $condition[] = ['vip_id','=',$vip_id];
+            $view['info'] = AisVip::where(['id' => $vip_id])->field('name,id')->find();
+            $view['pathMaps'][] = ['name' => $view['info']->name,'url'=>url('ais/vip.user/index',['vip_id' => $view['info']->id])];
+        }
+        //用户精准查询
+        $uid = Request::param('uid/d','');
+        if($uid){
+            $condition[] = ['uid','=',$uid];
+        }
+        $view['lists']  = AisVipUser::where($this->mini_program)->where($condition)->order('id desc')->paginate(20,false,['query'=> ['types' => $types,'vip_id' => $vip_id,'time' => $time]]);
+        //模板赋值
+        $view['pathMaps'][] = ['name' => $types ? '<span class="red fn-fb">锁定<span>' : '<span class="blue fn-fb">正常<span>','url'=>'javascript:;'];
+        $view['types']      = $types;
+        $view['vip_id']     = $vip_id;
+        $view['time']       = $time;
+        $view['starttime']  = $starttime;
+        $view['endtime']    = $endtime;
+        $view['uid']        = $uid;
+        return view()->assign($view);
+    }
+    
+    /**
+     * 添加创客会员
+     * @return type
+     */
+    public function winUser(){
+        if(request()->isAjax()){
+            $uids = ids($this->request->param('ids/s'),true);
+            if(empty($uids)){
+                return json(['code'=>0,'msg'=>'请选择要关联的用户']);
+            }
+            $vip_id  = $this->request->param('vip_id/d');
+            $vipcard = AisVip::where($this->mini_program)->where(['id' => $vip_id])->find();
+            if(empty($vipcard)){
+                return json(['code'=>0,'msg'=>'未找到对应会员组']);
+            }
+            //读取并判断是否VIP
+            $vipdata  = [];
+            foreach ($uids as $key => $uid) {
+                $vipdata[$key]['update_time'] = time();
+                $vipdata[$key]['is_lock']     = 0;
+                $vipdata[$key]['vip_id']    = $vipcard->id;
+                $vipdata[$key]['uid']     = $uid;
+                $vipdata[$key]['member_miniapp_id'] = $this->member_miniapp_id;
+                //通知到申请者微信
+                Inform::sms($uid,$this->member_miniapp_id,['title' =>'业务进展通知','type' => '身份变更','state' => '成功','content' =>'您的身份已变更为'.$vipcard['name']]);
+            }
+            //锁定以前的会员
+            AisVipUser::where(['uid' => $uids])->update(['is_lock' => 1]);
+            AisVipUser::insertAll($vipdata);
+            return json(['code'=>200,'msg'=>'会员用户新增成功','data' => ['url'=>'']]);
+        }else{
+            $vip_id = $this->request->param('vip_id/d');
+            $view['vip'] = AisVip::where($this->mini_program)->where(['id' => $vip_id])->find();
+            if(empty($view['vip'])){
+                $this->error('未找到会员类型');
+            }
+            $condition = [] ;
+            $keyword = $this->request->param('keyword');
+            if(!empty($keyword)){
+                if(Validate::isMobile($keyword)){
+                    $condition[] = ['phone_uid','=',$keyword] ;
+                }else{
+                    $condition[] = ['nickname','like','%'.$keyword.'%'];
+                }
+            }       
+            $view['list'] = SystemUser::where($this->mini_program)->where($condition)->where('id', 'NOT IN', function ($query) use($vip_id){
+                $query->table('ai_ais_vip_user')->where(['vip_id' => $vip_id,'is_lock' => 0])->field('uid');
+            })->order('id desc')->paginate(20,false,['query' => ['keyword'=>$keyword,'vip_id' => $vip_id]]);
+            $view['keyword'] = $keyword;
+            $view['vip_id']  = $vip_id;
+            return view()->assign($view);
+        }
+    }
+
+    /**
+     * 删除用户的优惠券
+     * @return void
+     */
+    public function delete(){
+        $result = AisVipUser::where($this->mini_program)->where(['uid' => $this->request->param('uid/d')])->delete();
+        if($result){
+            return enjson(200);
+        }
+        return enjson(0);
+    }
+}

+ 28 - 0
application/ais/event/City.php

@@ -0,0 +1,28 @@
+<?php
+/**
+* 城市编码读取
+**/
+namespace app\ais\event;
+use app\ais\model\AisCity;
+use think\facade\Request;
+use think\Validate;
+
+class City{
+
+    /**
+     * 查看城市编码
+     * @param integer $id 用户ID
+     */
+    public static function read(){
+        $province = Request::param('province/s');
+        $city     = Request::param('city/s');
+        $district = Request::param('district/s');
+        if(empty($province) || empty($city) || empty($district)){
+            return;
+        }
+        $city = AisCity::where(['code' => $district])->field('code')->find();
+        if ($city){
+            return $city->code;
+        }  
+    }
+}

+ 206 - 0
application/ais/event/Micro.php

@@ -0,0 +1,206 @@
+<?php
+namespace app\ais\event;
+
+use app\common\model\SystemMemberPayment;
+use EasyWeChat\Factory;
+
+class Micro
+{
+    protected static $mch_id;   //商户号
+    protected static $mch_key;   //32位密钥
+    protected static $mch_private_key;  //商户私钥
+    protected static $wechat_serial_no;  //  平台证书序列号
+    protected static $serial_no = '275E949C1475DFCE8DDBEB5AC195D9DFABF48906';  //  商户证书序列号
+    protected static $apiv3_key = '37Qx18rqjVVAWPXnuMSsL7hqbsxMFLSr';  //  APIv3 密钥
+    protected static $wechat_cert;  //  平台证书
+
+    //初始化配置
+    public static function config(int $miniapp_id,$flag = false){
+        $config = SystemMemberPayment::config($miniapp_id,'wepay');
+        if(empty($config)) return;
+        self::$mch_id = $config['mch_id'];
+        self::$mch_key = $config['key'];
+        self::$mch_private_key = self::getPrivateKey($config['key_path']);
+        //如果需要,ture为获取平台证书
+        if($flag){
+            $data = [
+                // 必要配置
+                'mch_id'           => $config['mch_id'], // 服务商的商户号
+                'key'              => $config['key'], // API 密钥
+                'apiv3_key'        => self::$apiv3_key, // APIv3 密钥
+                'cert_path'        => $config['cert_path'], // XXX: 绝对路径!!!!
+                'key_path'         => $config['key_path'], // XXX: 绝对路径!!!!
+            ];
+            $response = Factory::microMerchant($data)->certficates->get();
+            self::$wechat_cert = $response['certificates'];
+            self::$wechat_serial_no =  $response['serial_no'];
+        }
+    }
+
+    //获取商户私钥
+    public static function getPrivateKey($key){
+        return  openssl_get_privatekey(file_get_contents($key));
+    }
+
+    //签名
+    public static function sign($url,$http_mothod,$timestamp,$nonce,$body,$mch_private_key,$merchant_id,$serial_no){
+        $url_parts = parse_url($url);
+        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
+        $message =
+            $http_mothod . "\n".
+            $canonical_url . "\n".
+            $timestamp . "\n".
+            $nonce . "\n".
+            $body . "\n";
+        openssl_sign($message,$raw_sign,$mch_private_key,'sha256WithRSAEncryption');
+        $sign = base64_encode($raw_sign);
+        $token = sprintf('mchid="%s",nonce_str="%s",signature="%s",timestamp="%d",serial_no="%s"', $merchant_id,$nonce,$sign,$timestamp,$serial_no);
+        return $token;
+    }
+
+    //发送请求
+    protected static function curl($url,$data = [],$sign,$method = "POST"){
+        //设置header头
+        $header = [
+            'Accept:application/json',
+            'User-Agent:'.self::$mch_id,
+            'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $sign,
+            'Content-Type:application/json',
+            'Wechatpay-Serial:' . self::$wechat_serial_no ?? self::$serial_no,
+        ];
+        $curl = curl_init();
+        curl_setopt($curl,CURLOPT_URL,$url);
+        curl_setopt($curl,CURLOPT_HTTPHEADER,$header);
+        curl_setopt($curl,CURLOPT_HEADER,false);
+        curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
+        curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,false);
+        if($method == "POST"){
+            curl_setopt($curl,CURLOPT_POST,true);
+            curl_setopt($curl,CURLOPT_POSTFIELDS,$data);
+        }
+        $result = curl_exec($curl);
+        curl_close($curl);
+        return $result;
+    }
+
+    //加密
+    private static function getEncrypt($str){
+        //$str是待加密字符串
+        $encrypted = '';
+        if (openssl_public_encrypt($str,$encrypted,self::$wechat_cert,OPENSSL_PKCS1_OAEP_PADDING)) {
+            //base64编码
+            $sign = base64_encode($encrypted);
+        } else {
+            throw new \Exception('encrypt failed');
+        }
+        return $sign;
+    }
+
+    //随机字符串
+    public static function nonce_str(){
+        return date('YmdHis',time().rand(10000,99999));
+    }
+
+
+    /**
+     * 上传图片到微信服务器
+     * @param integer $appid   来源小程序
+     * @return void
+     */
+    public static function uploadMedia(int $miniapp_id,string $filename){
+        self::config($miniapp_id);
+        $url = 'https://api.mch.weixin.qq.com/v3/merchant/media/upload';
+        $fi = new \finfo(FILEINFO_MIME_TYPE);
+        $mime_type = $fi->file($filename);
+        $data['filename'] = pathinfo($filename, PATHINFO_BASENAME);
+        $meta['filename'] = pathinfo($filename, PATHINFO_BASENAME);
+        $meta['sha256'] = hash_file('sha256', $filename);
+        $boundary = uniqid(); //分割符号
+        $sign = self::sign($url,'POST',time(),self::nonce_str(),json_encode($meta),self::$mch_private_key,self::$mch_id,self::$serial_no);//$http_method要大写
+        $header[] = 'User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36';
+        $header[] = 'Accept:application/json';
+        $header[] = 'Authorization:WECHATPAY2-SHA256-RSA2048 '.$sign;
+        $header[] = 'Content-Type:multipart/form-data;boundary='.$boundary;
+        $boundaryStr = "--{$boundary}\r\n";
+        $out = $boundaryStr;
+        $out .= 'Content-Disposition: form-data; name="meta"'."\r\n";
+        $out .= 'Content-Type: application/json'."\r\n";
+        $out .= "\r\n";
+        $out .= json_encode($meta)."\r\n";
+        $out .=  $boundaryStr;
+        $out .= 'Content-Disposition: form-data; name="file"; filename="'.$data['filename'].'"'."\r\n";
+        $out .= 'Content-Type: '.$mime_type.';'."\r\n";
+        $out .= "\r\n";
+        $out .= file_get_contents($filename)."\r\n";
+        $out .= "--{$boundary}--\r\n";
+        $ch = curl_init();
+        curl_setopt($ch, CURLOPT_URL, $url);
+        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
+        //避免https 的ssl验证
+        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
+        curl_setopt($ch, CURLOPT_SSLVERSION, false);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
+        curl_setopt($ch, CURLOPT_POST, true);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $out);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+        // 模拟来源
+        curl_setopt($ch, CURLOPT_REFERER, "");
+        $response = curl_exec($ch);
+        if ($error = curl_error($ch)) {
+            return $error;
+        }
+        curl_close($ch);
+        return $response;
+    }
+    //进件
+    public static function submit($miniapp_id,$params){
+        self::config($miniapp_id,true);
+        $params['contact_info']['contact_name'] = self::getEncrypt($params['contact_info']['contact_name']);
+        $params['contact_info']['contact_id_number'] = self::getEncrypt($params['contact_info']['contact_id_number']);
+        $params['contact_info']['mobile_phone'] = self::getEncrypt($params['contact_info']['mobile_phone']);
+        $params['contact_info']['contact_email'] = self::getEncrypt($params['contact_info']['contact_email']);
+        $params['bank_account_info']['account_number'] = self::getEncrypt($params['bank_account_info']['account_number']);
+        $params['bank_account_info']['account_name'] = self::getEncrypt($params['bank_account_info']['account_name']);
+        $params['subject_info']['identity_info']['id_card_info']['id_card_name'] = self::getEncrypt($params['subject_info']['identity_info']['id_card_info']['id_card_name']);
+        $params['subject_info']['identity_info']['id_card_info']['id_card_number'] = self::getEncrypt($params['subject_info']['identity_info']['id_card_info']['id_card_number']);
+        if($params['subject_info']['identity_info']['owner'] == 1){
+            $params['subject_info']['identity_info']['owner'] = true;
+        }else{
+            $params['subject_info']['identity_info']['owner'] = false;
+        }
+        $url    = 'https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/';
+        $sign   = self::sign($url, 'POST', time(), self::nonce_str(), json_encode($params), self::$mch_private_key, self::$mch_id, self::$serial_no);
+        $result = self::curl($url, json_encode($params), $sign);
+        return json_decode($result,true);
+    }
+
+    //查询进件
+    public static function query($miniapp_id,$no){
+        self::config($miniapp_id);
+        $url    = 'https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/business_code/' . $no;
+        $sign   = self::sign($url, 'GET', time(), self::nonce_str(), '', self::$mch_private_key, self::$mch_id, self::$serial_no);
+        $result = self::curl($url, '', $sign, 'GET');
+        return json_decode($result,true);
+    }
+
+    //修改结算帐号
+    public static function modify($miniapp_id,$params){
+        self::config($miniapp_id,true);
+        $params['account_number'] = self::getEncrypt($params['account_number']);
+        $url    = sprintf('https://api.mch.weixin.qq.com/v3/apply4sub/sub_merchants/%s/modify-settlement', $params['sub_mchid']);
+        $sign   = self::sign($url, 'POST', time(), self::nonce_str(), json_encode($params), self::$mch_private_key, self::$mch_id, self::$serial_no);
+        $result = self::curl($url, json_encode($params), $sign);
+        return json_decode($result,true);
+    }
+
+    //查询结算账户
+    public static function settlement($miniapp_id,$sub_mchid){
+        self::config($miniapp_id);
+        $url    = sprintf('https://api.mch.weixin.qq.com/v3/apply4sub/sub_merchants/%s/settlement', $sub_mchid);
+        $sign   = self::sign($url, 'GET', time(), self::nonce_str(), '', self::$mch_private_key, self::$mch_id, self::$serial_no);
+        $result = self::curl($url, '', $sign, 'GET');
+        return json_decode($result,true);
+    }
+}

+ 808 - 0
application/ais/install.sql

@@ -0,0 +1,808 @@
+/*
+Navicat MySQL Data Transfer
+
+Source Server         : 本地开发
+Source Server Version : 50731
+Source Host           : localhost:3306
+Source Database       : wechat
+
+Target Server Type    : MYSQL
+Target Server Version : 50731
+File Encoding         : 65001
+
+Date: 2020-12-18 10:29:16
+*/
+
+SET FOREIGN_KEY_CHECKS=0;
+
+-- ----------------------------
+-- Table structure for ai_ais_adwords
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_adwords`;
+CREATE TABLE `ai_ais_adwords` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT '0',
+  `open_type` varchar(50) DEFAULT NULL,
+  `group` varchar(100) DEFAULT NULL,
+  `title` varchar(50) DEFAULT NULL,
+  `link` varchar(200) DEFAULT NULL,
+  `picture` varchar(255) DEFAULT NULL,
+  `sort` int(11) DEFAULT '0',
+  `update_time` int(11) DEFAULT NULL,
+  `create_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_bank
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_bank`;
+CREATE TABLE `ai_ais_bank` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `uid` bigint(20) DEFAULT NULL,
+  `money` decimal(10,2) DEFAULT '0.00' COMMENT '帐号余额',
+  `tobo_paid` decimal(10,2) DEFAULT '0.00' COMMENT '锁定金额',
+  `pledge_money` decimal(10,2) DEFAULT NULL,
+  `point` bigint(20) DEFAULT '0' COMMENT '积分',
+  `update_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_bank_cash
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_bank_cash`;
+CREATE TABLE `ai_ais_bank_cash` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `uid` bigint(20) DEFAULT NULL,
+  `money` decimal(10,2) DEFAULT '0.00' COMMENT '申请金额',
+  `realmoney` decimal(10,2) DEFAULT '0.00' COMMENT '实际到账',
+  `update_time` int(11) DEFAULT NULL,
+  `state` tinyint(1) DEFAULT '0' COMMENT '0新申请1通过-1不通过',
+  `audit_time` int(11) DEFAULT NULL,
+  `trade_no` varchar(100) DEFAULT NULL,
+  `msg` varchar(255) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='提现申请列表';
+
+-- ----------------------------
+-- Table structure for ai_ais_bill
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_bill`;
+CREATE TABLE `ai_ais_bill` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `store_id` int(11) DEFAULT '0',
+  `uid` bigint(20) DEFAULT '0',
+  `pay_uid` bigint(20) DEFAULT '0',
+  `money` decimal(10,2) DEFAULT '0.00',
+  `message` tinytext,
+  `update_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `id` (`id`) USING BTREE,
+  KEY `id_2` (`id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='个人财务记录';
+
+-- ----------------------------
+-- Table structure for ai_ais_card
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_card`;
+CREATE TABLE `ai_ais_card` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `is_lock` tinyint(1) DEFAULT '0',
+  `is_end` tinyint(1) DEFAULT '0',
+  `store_id` int(11) DEFAULT NULL,
+  `name` varchar(255) DEFAULT NULL,
+  `price` decimal(11,2) DEFAULT NULL,
+  `tips` text,
+  `coupon_id` bigint(20) DEFAULT NULL,
+  `coupon_ids` text,
+  `locktime` int(11) DEFAULT NULL,
+  `create_time` int(11) DEFAULT NULL,
+  `update_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_card_order
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_card_order`;
+CREATE TABLE `ai_ais_card_order` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `store_id` int(11) DEFAULT NULL,
+  `uid` bigint(11) DEFAULT NULL,
+  `card_id` int(11) DEFAULT NULL,
+  `coupon_id` bigint(11) DEFAULT NULL,
+  `user_card_id` int(11) DEFAULT NULL,
+  `coupon_ids` varchar(255) DEFAULT NULL COMMENT '赠品列表',
+  `state` tinyint(1) DEFAULT '0',
+  `price` decimal(10,2) DEFAULT NULL,
+  `amount` decimal(10,2) DEFAULT NULL,
+  `order_no` varchar(255) DEFAULT NULL,
+  `paid_time` int(11) DEFAULT NULL,
+  `create_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `UID` (`uid`),
+  KEY `APIID` (`member_miniapp_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_card_user
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_card_user`;
+CREATE TABLE `ai_ais_card_user` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `uid` bigint(11) DEFAULT NULL,
+  `user_coupon_id` bigint(11) DEFAULT '0',
+  `store_id` int(11) DEFAULT NULL,
+  `card_id` int(11) DEFAULT NULL,
+  `amount` decimal(11,2) DEFAULT NULL,
+  `create_time` int(11) DEFAULT NULL,
+  `update_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `UID` (`uid`) USING BTREE,
+  KEY `APIID` (`member_miniapp_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_city
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_city`;
+CREATE TABLE `ai_ais_city` (
+  `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
+  `code` bigint(12) DEFAULT NULL COMMENT '行政区划代码',
+  `name` varchar(32) DEFAULT NULL COMMENT '名称',
+  `parent_id` bigint(11) DEFAULT NULL COMMENT '上级id',
+  `level` varchar(32) DEFAULT NULL COMMENT 'level_id',
+  `sort` int(11) DEFAULT '0',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_config
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_config`;
+CREATE TABLE `ai_ais_config` (
+  `member_miniapp_id` int(11) NOT NULL,
+  `coupon_longtime` tinyint(4) DEFAULT '0',
+  `coupon_is_pay_open` tinyint(2) DEFAULT NULL,
+  `group_join` int(11) DEFAULT NULL,
+  `group_member` int(11) DEFAULT NULL,
+  `group_profit` int(11) DEFAULT NULL COMMENT '引流分润',
+  `city_sharing_price` decimal(10,2) DEFAULT NULL,
+  `city_only_price` decimal(10,2) DEFAULT NULL,
+  `mchid` int(11) DEFAULT NULL,
+  `charge` tinyint(3) DEFAULT NULL,
+  `service_telephone` varchar(100) DEFAULT NULL,
+  `qq_lbs_key` varchar(100) DEFAULT NULL,
+  `sla` text,
+  `writer` text,
+  `info` text COMMENT '城市号配置',
+  PRIMARY KEY (`member_miniapp_id`),
+  UNIQUE KEY `APPID` (`member_miniapp_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_coupon
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_coupon`;
+CREATE TABLE `ai_ais_coupon` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `store_id` int(11) DEFAULT NULL,
+  `citycode` int(6) DEFAULT NULL,
+  `is_top` tinyint(1) DEFAULT '0',
+  `is_lock` tinyint(1) DEFAULT '0' COMMENT '锁定',
+  `is_end` tinyint(1) DEFAULT '0' COMMENT '是否过期失效或删除',
+  `types` tinyint(1) DEFAULT '0' COMMENT '0满减/抵扣1满折/折扣/2兑换券3储值券',
+  `discount` float(2,1) DEFAULT '0.0' COMMENT '折扣力度',
+  `price` int(11) DEFAULT '0' COMMENT '满减代金券',
+  `amount` int(11) DEFAULT '0' COMMENT '额度大小',
+  `howmuch` int(10) DEFAULT '0' COMMENT '满多少用',
+  `name` varchar(255) DEFAULT NULL,
+  `tips` varchar(255) DEFAULT NULL,
+  `sort` int(11) DEFAULT '0',
+  `num` int(11) DEFAULT '0' COMMENT '发行数量',
+  `update_time` int(11) DEFAULT NULL,
+  `create_time` int(11) DEFAULT NULL COMMENT '0',
+  PRIMARY KEY (`id`),
+  KEY `APPID` (`member_miniapp_id`) USING BTREE,
+  KEY `STOREID` (`store_id`) USING BTREE,
+  KEY `CITYID` (`citycode`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_coupon_subsidize
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_coupon_subsidize`;
+CREATE TABLE `ai_ais_coupon_subsidize` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `coupon_id` int(11) NOT NULL COMMENT '赠品ID',
+  `how_much` decimal(10,2) DEFAULT NULL COMMENT '补贴金额',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='补贴优惠券';
+
+-- ----------------------------
+-- Table structure for ai_ais_coupon_user
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_coupon_user`;
+CREATE TABLE `ai_ais_coupon_user` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `store_id` int(11) DEFAULT NULL,
+  `coupon_id` int(11) DEFAULT NULL,
+  `parent_store_id` int(11) DEFAULT '0',
+  `uid` bigint(20) DEFAULT NULL,
+  `is_end` tinyint(1) DEFAULT '0',
+  `types` tinyint(4) DEFAULT '0' COMMENT '0满减/抵扣1满折/折扣/2兑换券3储值券',
+  `discount` float(2,1) DEFAULT NULL,
+  `price` int(11) DEFAULT NULL COMMENT '分',
+  `amount` int(11) DEFAULT NULL,
+  `howmuch` int(10) DEFAULT NULL COMMENT '元',
+  `name` varchar(255) DEFAULT NULL,
+  `tips` varchar(255) DEFAULT NULL,
+  `group_ids` varchar(11) DEFAULT '0',
+  `money` decimal(10,2) DEFAULT '0.00' COMMENT '优惠多少钱',
+  `update_time` int(11) DEFAULT NULL,
+  `create_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `APPID` (`member_miniapp_id`) USING BTREE,
+  KEY `STOREID` (`store_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户的赠品';
+
+-- ----------------------------
+-- Table structure for ai_ais_fund
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_fund`;
+CREATE TABLE `ai_ais_fund` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `balance` decimal(10,2) DEFAULT NULL,
+  `subsidize` decimal(10,2) DEFAULT NULL,
+  `subsidize_num` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='采购基金';
+
+-- ----------------------------
+-- Table structure for ai_ais_fund_bill
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_fund_bill`;
+CREATE TABLE `ai_ais_fund_bill` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `store_id` int(11) DEFAULT NULL,
+  `uid` int(11) DEFAULT NULL,
+  `types` tinyint(13) DEFAULT NULL COMMENT '0入1出',
+  `state` tinyint(2) DEFAULT '0' COMMENT '1成功 2失败',
+  `money` decimal(10,2) DEFAULT NULL,
+  `order_no` varchar(100) DEFAULT NULL,
+  `message` varchar(255) DEFAULT NULL,
+  `update_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='基金账单';
+
+-- ----------------------------
+-- Table structure for ai_ais_income
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_income`;
+CREATE TABLE `ai_ais_income` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `store_id` int(11) DEFAULT '0',
+  `pay_uid` bigint(20) DEFAULT '0',
+  `types` tinyint(1) DEFAULT '0' COMMENT '1买单2优选3会员4城市号',
+  `money` decimal(10,2) DEFAULT '0.00',
+  `update_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `id` (`id`) USING BTREE,
+  KEY `id_2` (`id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='收入账单';
+
+-- ----------------------------
+-- Table structure for ai_ais_info
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_info`;
+CREATE TABLE `ai_ais_info` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `uid` bigint(20) DEFAULT NULL,
+  `cate_id` int(11) DEFAULT NULL,
+  `citycode` int(6) DEFAULT NULL,
+  `store_id` int(11) DEFAULT '0',
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `themes` text,
+  `fields` text,
+  `telphone` varchar(255) DEFAULT NULL,
+  `url_slogan` varchar(255) DEFAULT NULL,
+  `links` varchar(255) DEFAULT NULL,
+  `is_get` tinyint(2) DEFAULT '0' COMMENT '是否获取用户信息',
+  `price` decimal(10,2) DEFAULT '0.00' COMMENT '获取用户价格',
+  `video` varchar(255) DEFAULT NULL,
+  `images` text,
+  `is_top` int(11) DEFAULT '0',
+  `topday` int(11) DEFAULT NULL,
+  `top_money` bigint(20) DEFAULT NULL,
+  `order_no` varchar(100) DEFAULT NULL,
+  `paid_at` tinyint(1) DEFAULT '0',
+  `paid_time` int(11) DEFAULT '0',
+  `paid_no` varchar(100) DEFAULT NULL,
+  `sort` int(11) DEFAULT '0',
+  `views` int(11) DEFAULT '0' COMMENT '阅读人数',
+  `like` int(11) DEFAULT '0' COMMENT '点赞人数',
+  `like_face` text,
+  `reply_num` int(11) DEFAULT '0' COMMENT '评论人数',
+  `is_lock` tinyint(1) DEFAULT '0',
+  `create_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `UID` (`uid`),
+  KEY `MID` (`member_miniapp_id`),
+  KEY `CITYID` (`citycode`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_info_cate
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_info_cate`;
+CREATE TABLE `ai_ais_info_cate` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `title` varchar(50) DEFAULT NULL,
+  `name` varchar(50) DEFAULT NULL,
+  `tpl_id` int(11) DEFAULT NULL,
+  `sort` int(11) DEFAULT '0',
+  `update_time` int(11) DEFAULT NULL,
+  `create_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `ID` (`id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='信息栏目';
+
+-- ----------------------------
+-- Table structure for ai_ais_info_follow
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_info_follow`;
+CREATE TABLE `ai_ais_info_follow` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `uid` int(11) DEFAULT NULL,
+  `like_uid` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='关注与取消';
+
+-- ----------------------------
+-- Table structure for ai_ais_info_mp
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_info_mp`;
+CREATE TABLE `ai_ais_info_mp` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `uid` bigint(20) DEFAULT NULL,
+  `logo` varchar(100) DEFAULT NULL,
+  `skin` varchar(255) DEFAULT NULL,
+  `title` varchar(100) DEFAULT NULL,
+  `note` varchar(100) DEFAULT NULL,
+  `is_vip` tinyint(1) DEFAULT '0',
+  `is_apply` tinyint(1) DEFAULT '0',
+  `vip_title` varchar(100) DEFAULT NULL,
+  `vip_about` varchar(255) DEFAULT NULL,
+  `vip_time` int(11) DEFAULT NULL,
+  `reg_time` int(11) DEFAULT NULL,
+  `is_lock` tinyint(1) DEFAULT '0',
+  `fans` int(255) DEFAULT '0',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_info_order
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_info_order`;
+CREATE TABLE `ai_ais_info_order` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `info_id` int(11) DEFAULT NULL,
+  `info_uid` int(11) DEFAULT NULL,
+  `uid` int(11) DEFAULT NULL,
+  `status` tinyint(1) DEFAULT '0',
+  `is_del` tinyint(1) DEFAULT '0',
+  `phone` varchar(255) DEFAULT NULL,
+  `amount` decimal(10,2) DEFAULT '0.00' COMMENT '单商品价格总额',
+  `order_no` varchar(50) DEFAULT NULL,
+  `paid_at` tinyint(1) DEFAULT '0',
+  `paid_time` int(11) DEFAULT NULL,
+  `paid_no` varchar(255) DEFAULT NULL,
+  `message` varchar(255) DEFAULT NULL,
+  `fields` text,
+  `cache` text,
+  `create_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `ORDER_NO` (`order_no`) USING BTREE,
+  KEY `IS_DEL` (`is_del`) USING BTREE,
+  KEY `STATUS` (`status`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_info_reply
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_info_reply`;
+CREATE TABLE `ai_ais_info_reply` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `uid` bigint(20) DEFAULT NULL,
+  `info_id` int(11) DEFAULT NULL,
+  `reply` varchar(255) DEFAULT NULL,
+  `like` int(11) DEFAULT '0',
+  `create_time` int(11) DEFAULT NULL,
+  `state` tinyint(1) DEFAULT '0',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_info_tpl
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_info_tpl`;
+CREATE TABLE `ai_ais_info_tpl` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `name` varchar(20) DEFAULT NULL,
+  `is_shop` tinyint(1) DEFAULT '0',
+  `button_name` varchar(20) DEFAULT NULL,
+  `tips` varchar(255) DEFAULT NULL,
+  `users` text,
+  `fields` text,
+  `update_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品规格';
+
+-- ----------------------------
+-- Table structure for ai_ais_order
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_order`;
+CREATE TABLE `ai_ais_order` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `store_id` int(11) DEFAULT '0' COMMENT '总店',
+  `store_chain_id` int(11) DEFAULT '0' COMMENT '分店',
+  `uid` bigint(20) DEFAULT NULL,
+  `coupon_user_id` int(11) DEFAULT NULL,
+  `parent_store_id` int(11) DEFAULT '0',
+  `parent_store_price` decimal(10,2) DEFAULT '0.00',
+  `amount` decimal(10,2) DEFAULT NULL COMMENT '应付金额',
+  `price` decimal(10,2) DEFAULT NULL COMMENT '实付金额',
+  `state` tinyint(2) DEFAULT '0',
+  `order_no` varchar(255) DEFAULT NULL,
+  `paid_time` int(11) DEFAULT NULL,
+  `paid_no` varchar(255) DEFAULT NULL,
+  `coupon_cache` text,
+  `update_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_queen
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_queen`;
+CREATE TABLE `ai_ais_queen` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `types` tinyint(1) DEFAULT '0' COMMENT '0:open|1:mchid',
+  `store_id` bigint(20) DEFAULT NULL,
+  `uid` bigint(20) DEFAULT NULL,
+  `mch_id` bigint(20) DEFAULT NULL,
+  `amount` int(11) DEFAULT NULL,
+  `transaction_id` varchar(64) DEFAULT NULL,
+  `out_order_no` varchar(64) DEFAULT NULL,
+  `order_id` varchar(64) DEFAULT NULL,
+  `is_finish` tinyint(1) DEFAULT NULL COMMENT '0排队1失败2成',
+  `msg` varchar(255) DEFAULT NULL,
+  `sms` varchar(255) DEFAULT NULL,
+  `update_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务队列';
+
+-- ----------------------------
+-- Table structure for ai_ais_shop
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_shop`;
+CREATE TABLE `ai_ais_shop` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `store_id` int(11) DEFAULT NULL,
+  `citycode` int(6) DEFAULT NULL,
+  `member_miniapp_id` int(11) NOT NULL,
+  `category_id` bigint(20) DEFAULT NULL,
+  `coupon_id` bigint(20) DEFAULT NULL,
+  `is_sale` tinyint(1) DEFAULT '0' COMMENT '0:下架、1:上架',
+  `is_del` tinyint(1) DEFAULT '0',
+  `types` tinyint(1) DEFAULT '0',
+  `name` varchar(255) DEFAULT NULL,
+  `title` varchar(255) DEFAULT NULL,
+  `cost_price` decimal(10,2) DEFAULT NULL,
+  `sell_price` decimal(10,2) DEFAULT '0.00',
+  `market_price` decimal(10,2) DEFAULT '0.00',
+  `vip_price` decimal(10,2) DEFAULT NULL,
+  `points_price` int(11) DEFAULT NULL,
+  `warehouse_num` int(11) DEFAULT '0',
+  `warehouse_sellnum` int(11) DEFAULT '0',
+  `imgs` text,
+  `img` varchar(255) DEFAULT NULL,
+  `group_title` varchar(255) DEFAULT NULL,
+  `group_note` varchar(255) DEFAULT NULL,
+  `group_img` varchar(255) DEFAULT NULL,
+  `keyword` varchar(255) DEFAULT NULL,
+  `notice` text,
+  `like` int(11) DEFAULT '0',
+  `share_ids` text,
+  `share_price` int(11) DEFAULT NULL,
+  `share_vip_price` int(11) DEFAULT NULL,
+  `content` mediumtext,
+  `sort` int(11) DEFAULT '0',
+  `end_time` int(11) DEFAULT NULL,
+  `update_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`,`member_miniapp_id`),
+  UNIQUE KEY `ID` (`id`) USING BTREE,
+  KEY `IS_SALE` (`is_sale`) USING BTREE,
+  KEY `CITYID` (`citycode`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品主表';
+
+-- ----------------------------
+-- Table structure for ai_ais_shop_cate
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_shop_cate`;
+CREATE TABLE `ai_ais_shop_cate` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `types` tinyint(1) DEFAULT '0',
+  `show_type` tinyint(1) DEFAULT '0',
+  `title` varchar(50) DEFAULT NULL,
+  `content` varchar(255) DEFAULT NULL,
+  `picture` varchar(100) DEFAULT NULL,
+  `sort` int(11) DEFAULT '0',
+  `update_time` int(11) DEFAULT NULL,
+  `create_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `ID` (`id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品目录';
+
+-- ----------------------------
+-- Table structure for ai_ais_shop_coupon
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_shop_coupon`;
+CREATE TABLE `ai_ais_shop_coupon` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `coupon_id` int(11) DEFAULT NULL,
+  `shop_id` int(11) DEFAULT NULL,
+  `create_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `STOREID` (`coupon_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='支付有礼';
+
+-- ----------------------------
+-- Table structure for ai_ais_shop_order
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_shop_order`;
+CREATE TABLE `ai_ais_shop_order` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `store_id` int(11) DEFAULT NULL,
+  `uid` int(11) DEFAULT NULL,
+  `share_uid` int(11) DEFAULT NULL,
+  `phone` varchar(255) DEFAULT NULL,
+  `shop_id` int(11) DEFAULT NULL,
+  `order_no` varchar(50) DEFAULT NULL,
+  `status` tinyint(1) DEFAULT '0',
+  `is_del` tinyint(1) DEFAULT '0',
+  `sell_price` decimal(10,2) DEFAULT '0.00',
+  `amount` decimal(10,2) DEFAULT '0.00' COMMENT '单商品价格总额',
+  `points` int(11) DEFAULT NULL,
+  `thrifty` decimal(10,2) DEFAULT NULL,
+  `create_time` int(11) DEFAULT NULL,
+  `paid_at` tinyint(1) DEFAULT '0',
+  `paid_time` int(11) DEFAULT NULL,
+  `paid_no` varchar(255) DEFAULT NULL,
+  `message` varchar(255) DEFAULT NULL,
+  `shop_cache` text,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `ORDER_NO` (`order_no`) USING BTREE,
+  KEY `IS_DEL` (`is_del`) USING BTREE,
+  KEY `STATUS` (`status`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_store
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_store`;
+CREATE TABLE `ai_ais_store` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `manage_uid` int(11) DEFAULT '0',
+  `citypath` varchar(255) DEFAULT NULL,
+  `citycode` int(6) DEFAULT NULL,
+  `mch_id` int(11) DEFAULT NULL,
+  `cate_id` int(11) DEFAULT NULL,
+  `cate_sid` int(11) DEFAULT NULL,
+  `name` varchar(255) DEFAULT NULL,
+  `img` varchar(255) DEFAULT NULL,
+  `imgs` text,
+  `address` varchar(255) DEFAULT NULL,
+  `telphone` varchar(255) DEFAULT NULL,
+  `longitude` decimal(10,7) DEFAULT NULL COMMENT '地图坐标',
+  `latitude` decimal(10,7) DEFAULT NULL,
+  `charge` int(10) DEFAULT '0',
+  `tags` text,
+  `sort` int(11) DEFAULT '0',
+  `is_top` tinyint(1) DEFAULT '0',
+  `is_lock` tinyint(1) DEFAULT '0',
+  `create_time` int(11) DEFAULT NULL,
+  `views` int(11) DEFAULT '0',
+  `likes` int(11) DEFAULT '0',
+  PRIMARY KEY (`id`),
+  KEY `APPID` (`member_miniapp_id`) USING BTREE,
+  KEY `CID` (`cate_id`) USING BTREE,
+  KEY `CITYID` (`citycode`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_store_bill
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_store_bill`;
+CREATE TABLE `ai_ais_store_bill` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `store_id` int(11) DEFAULT '0',
+  `store_chain_id` int(11) DEFAULT '0',
+  `pay_uid` bigint(20) DEFAULT '0',
+  `money` decimal(10,2) DEFAULT '0.00',
+  `message` tinytext,
+  `update_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `ID` (`id`) USING BTREE,
+  KEY `STORE_ID` (`store_id`) USING BTREE,
+  KEY `UID` (`pay_uid`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='好店账单';
+
+-- ----------------------------
+-- Table structure for ai_ais_store_cate
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_store_cate`;
+CREATE TABLE `ai_ais_store_cate` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `parent_id` int(11) DEFAULT '0',
+  `root_id` int(11) DEFAULT NULL,
+  `title` varchar(50) DEFAULT NULL,
+  `name` varchar(50) DEFAULT NULL,
+  `picture` varchar(100) DEFAULT NULL,
+  `sort` int(11) DEFAULT '0',
+  `update_time` int(11) DEFAULT NULL,
+  `create_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `ID` (`id`) USING BTREE,
+  KEY `PARENT_ID` (`parent_id`,`root_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='分类信息栏目';
+
+-- ----------------------------
+-- Table structure for ai_ais_store_chain
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_store_chain`;
+CREATE TABLE `ai_ais_store_chain` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `store_id` int(11) DEFAULT NULL,
+  `title` varchar(100) DEFAULT NULL,
+  `address` varchar(255) DEFAULT NULL,
+  `telphone` varchar(50) DEFAULT NULL,
+  `longitude` varchar(20) DEFAULT NULL,
+  `latitude` varchar(20) DEFAULT NULL,
+  `sort` int(11) DEFAULT '0',
+  `update_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='连锁门店';
+
+-- ----------------------------
+-- Table structure for ai_ais_store_group
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_store_group`;
+CREATE TABLE `ai_ais_store_group` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `title` varchar(50) DEFAULT NULL,
+  `content` varchar(255) DEFAULT NULL,
+  `face` varchar(255) DEFAULT NULL,
+  `uid` int(11) DEFAULT NULL,
+  `create_time` int(11) DEFAULT NULL,
+  `update_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `ID` (`id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商圈';
+
+-- ----------------------------
+-- Table structure for ai_ais_store_union
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_store_union`;
+CREATE TABLE `ai_ais_store_union` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `store_id` int(11) DEFAULT NULL,
+  `group_id` int(11) DEFAULT NULL,
+  `type` tinyint(2) DEFAULT NULL COMMENT '0正常 1待审核 2拒绝 3退出 4 踢出',
+  `create_time` int(11) DEFAULT NULL,
+  `update_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商家和圈关联';
+
+-- ----------------------------
+-- Table structure for ai_ais_store_worker
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_store_worker`;
+CREATE TABLE `ai_ais_store_worker` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `store_id` int(11) DEFAULT NULL,
+  `uid` bigint(20) DEFAULT NULL,
+  `is_cashier` tinyint(1) DEFAULT '0' COMMENT '是否收银员',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='工作人员';
+
+-- ----------------------------
+-- Table structure for ai_ais_vip
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_vip`;
+CREATE TABLE `ai_ais_vip` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `is_lock` tinyint(1) DEFAULT '0',
+  `is_auto_up` tinyint(1) DEFAULT '0',
+  `name` varchar(255) DEFAULT NULL,
+  `rule` text,
+  `price` decimal(10,2) DEFAULT NULL,
+  `open_vip_num` int(11) DEFAULT NULL,
+  `open_store_num` int(11) DEFAULT NULL,
+  `pay_share_reward` tinyint(4) DEFAULT NULL,
+  `pay_queue_reward` tinyint(4) DEFAULT NULL,
+  `open_share_reward` decimal(10,2) DEFAULT NULL,
+  `open_queue_reward` decimal(10,2) DEFAULT NULL,
+  `icp_award` int(4) DEFAULT '0',
+  `fund` decimal(10,2) DEFAULT NULL,
+  `coupon_ids` varchar(255) DEFAULT NULL,
+  `sort` int(11) DEFAULT '0',
+  `update_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_vip_order
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_vip_order`;
+CREATE TABLE `ai_ais_vip_order` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `uid` int(11) DEFAULT '0',
+  `vip_id` int(11) DEFAULT NULL,
+  `amount` decimal(10,2) DEFAULT NULL,
+  `state` tinyint(1) DEFAULT '0',
+  `order_no` varchar(255) DEFAULT NULL,
+  `paid_time` int(11) DEFAULT NULL,
+  `paid_no` varchar(255) DEFAULT NULL,
+  `coupon_ids` varchar(255) DEFAULT NULL,
+  `create_time` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for ai_ais_vip_user
+-- ----------------------------
+DROP TABLE IF EXISTS `ai_ais_vip_user`;
+CREATE TABLE `ai_ais_vip_user` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `member_miniapp_id` int(11) DEFAULT NULL,
+  `uid` int(11) DEFAULT '0',
+  `vip_id` int(11) DEFAULT '0',
+  `update_time` int(11) DEFAULT NULL,
+  `point` int(11) DEFAULT NULL,
+  `is_lock` tinyint(1) DEFAULT '0',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+SET FOREIGN_KEY_CHECKS=1;

+ 35 - 0
application/ais/model/AisAdwords.php

@@ -0,0 +1,35 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 广告位管理
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisAdwords extends Model{
+      
+    protected $pk = 'id';
+    protected $autoWriteTimestamp = true;
+    protected $updateTime = false;
+
+    //添加或编辑
+    public static function edit($param){
+        $data['group']       = trim($param['group']);
+        $data['title']       = trim($param['title']);
+        $data['link']        = trim($param['link']);
+        $data['picture']     = trim($param['picture']);
+        $data['open_type']   = trim($param['open_type']);
+        $data['update_time'] = time();
+        if(empty($param['id'])){
+            $data['create_time']         = time();
+            $data['member_miniapp_id']   = $param['member_miniapp_id'];
+            return self::insert($data);
+        }else{
+            $condition['id'] = $param['id'];
+            $condition['member_miniapp_id'] = $param['member_miniapp_id'];
+            return self::update($data,$condition);
+        }
+    }
+}

+ 86 - 0
application/ais/model/AisBank.php

@@ -0,0 +1,86 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 联盟城市
+ */
+namespace app\ais\model;
+use app\ais\model\AisBankCash;
+use think\Model;
+
+class AisBank extends Model{
+
+
+  /**
+     * 积分增加
+     * @param integer $miniapp_id
+     * @param integer $uid
+     * @param integer $money(元)
+     * @return void
+     */
+    public static function points(int $weapp_id,int $uid,float $points){
+        $info = self::where(['uid' => $uid])->find();
+        if(empty($info)){
+            $data['member_miniapp_id'] = $weapp_id;
+            $data['uid']               = $uid;
+            $data['point']             = intval($points);
+            $data['update_time']       = time();
+            return self::create($data);
+        }else{
+            $info->point       = ['inc',intval($points)];
+            $info->update_time = time();
+            return $info->save();
+        }
+    }
+
+    /**
+     * 帐号充值
+     * @param integer $miniapp_id
+     * @param integer $uid
+     * @param integer $money(元)
+     * @return void
+     */
+    public static function recharge(int $weapp_id,int $uid,float $money){
+        $info = self::where(['uid' => $uid])->find();
+        if(empty($info)){
+            $data['member_miniapp_id'] = $weapp_id;
+            $data['uid']               = $uid;
+            $data['money']             = $money;
+            $data['point']             = intval($money);
+            $data['update_time']       = time();
+            return self::create($data);
+        }else{
+            $info->money       = ['inc',$money];
+            $info->point       = ['inc',intval($money)];
+            $info->update_time = time();
+            return $info->save();
+        }
+    }
+
+    /**
+     * 提现申请(小程序API)
+     * @param integer $miniapp_id
+     * @param integer $uid
+     * @param integer $money(元)
+     * @return void
+     */
+    public static function cashOut(int $uid,float $money){
+        $info = self::where(['uid' => $uid])->find();
+        if(empty($info) || $info->money < $money ){
+            return;
+        }
+        $info->money      = ['dec',$money];
+        $info->tobo_paid  = ['inc',$money];
+        $info->update_time = time();
+        $info->save();
+        //创建提现记录
+        $data['member_miniapp_id'] = $info->member_miniapp_id;
+        $data['uid']               = $info->uid; 
+        $data['money']             = $money;
+        $data['realmoney']         = 0;
+        $data['state']             = 0;
+        $data['update_time']       = time();
+        return AisBankCash::create($data);
+    }
+}

+ 13 - 0
application/ais/model/AisBankCash.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 联盟城市
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisBankCash extends Model{
+
+}

+ 29 - 0
application/ais/model/AisBill.php

@@ -0,0 +1,29 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 收益记录表
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisBill extends Model{
+    
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','pay_uid');
+    }
+
+    /**
+     * [log 增加财务日志]
+     */
+    public static function add(array $param,$message){
+        $data['member_miniapp_id'] = intval($param['member_miniapp_id']);
+        $data['uid']               = intval($param['uid']);
+        $data['store_id']          = intval($param['store_id']);
+        $data['money']             = money($param['money']);
+        $data['message']           = $message;
+        $data['update_time']       = time();
+        return self::create($data);
+    }
+}

+ 78 - 0
application/ais/model/AisCard.php

@@ -0,0 +1,78 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 会员卡管理
+ */
+namespace app\ais\model;
+use app\common\facade\Inform;
+use think\Model;
+
+class AisCard extends Model{
+
+    protected $pk = 'id';
+
+    /**
+     * 所属店铺
+     * @return void
+     */
+    public function store(){
+        return $this->hasOne('AisStore','id','store_id');
+    }
+
+    /**
+     * 所属优惠券
+     * @return void
+     */
+    public function coupon(){
+        return $this->hasOne('AisCoupon','id','coupon_id');
+    } 
+
+    /**
+     * 订单号
+     * @return void
+     */
+    public function cardorder(){
+        return $this->hasMany('AisCardOrder','card_id','id');
+    } 
+
+    /**
+     * 开通用户列表
+     * @return void
+     */
+    public function carduser(){
+        return $this->hasMany('AisCardUser','card_id','id');
+    } 
+
+    /**
+     * 编辑创客的关联的优惠券
+     * @param integer $vip_id
+     * @param [type] $coupon_ids
+     * @return void
+     */
+    public static function editCoupon(int $id,array $coupon_ids){
+        $info = self::where(['id' => $id])->find();
+        if(empty($info->coupon_ids)){
+            $info->coupon_ids = implode(',',$coupon_ids);
+        }else{
+            $coupon_ida = explode(',',$info->coupon_ids);
+            $ida        = array_merge($coupon_ida,$coupon_ids);
+            $info->coupon_ids = implode(',',$ida);
+        }
+        return $info->save();
+    }
+
+    /**
+     * 锁定或取消
+     * @param integer $id
+     */
+    public  static function isLock(int $id,$member_miniapp_id){
+        $result = self::where(['id' => $id])->field('is_lock,store_id')->find();
+        $data['is_lock'] = $result['is_lock'] ? 0 : 1;
+        if($data['is_lock'] == 0) {
+            $store = AisStore::where('id', '=', $result->store_id)->find();
+        }
+        return self::where('id',$id)->update($data);
+    }
+}

+ 27 - 0
application/ais/model/AisCardOrder.php

@@ -0,0 +1,27 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 会员用户管理
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisCardOrder extends Model{
+
+    protected $pk = 'id';
+    
+    /**
+     * 好店
+     * @return void
+     */
+    public function store(){
+        return $this->hasOne('AisStore','id','store_id');
+    }
+    
+    //用户
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','uid');
+    }
+}

+ 43 - 0
application/ais/model/AisCardUser.php

@@ -0,0 +1,43 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 会员用户管理
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisCardUser extends Model{
+
+    protected $pk = 'id';
+    
+    /**
+     * 好店
+     * @return void
+     */
+    public function store(){
+        return $this->hasOne('AisStore','id','store_id');
+    }
+    
+    /**
+     * 储值卡
+     * @return void
+     */
+    public function card(){
+        return $this->hasOne('AisCard','id','card_id');
+    }
+    
+    /**
+     * 优惠券
+     * @return void
+     */
+    public function couponUser(){
+        return $this->hasOne('AisCouponUser','id','user_coupon_id');
+    }
+
+    //用户
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','uid');
+    }
+}

+ 38 - 0
application/ais/model/AisCity.php

@@ -0,0 +1,38 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 联盟城市
+ */
+namespace app\ais\model;
+use think\Model;
+use category\Tree;
+
+class AisCity extends Model{
+    
+
+    /**
+     * 获取访问路径
+     * @param int $parent_id
+     */
+    public static function selectPath($parent_id) {
+        $pathMaps[] = ['name'=>'城市','url'=>url('admin.city/index')];
+        $getPath = self::getPath($parent_id);
+        foreach ($getPath as $value) {
+            $pathMaps[] = ['name' => $value['name'],'url' => url('admin.city/index',['parent_id'=>$value['id']])];
+        }
+        return $pathMaps;
+    }
+
+    /**
+     * 获取当前路径
+     * @param type $parent_id
+     * @return type
+     */
+    public static function getPath($parent_id){
+        $result = self::field('id,name,parent_id')->select();
+        $tree =  new Tree(array('id','parent_id','name','title'));
+        return $tree->getPath($result,$parent_id);
+    }
+}

+ 61 - 0
application/ais/model/AisConfig.php

@@ -0,0 +1,61 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 配置
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisConfig extends Model{
+
+    protected $pk = 'id';
+
+    //配置表
+    public static function getConfig(int $miniapp_id){
+        return self::where(['member_miniapp_id' => $miniapp_id])->find();
+    }
+
+   //获取所有配置
+    public static function getAllConfig(){
+        return self::select();
+    }
+    
+    //编辑
+    public static function configs(array $param,int $miniapp_id){
+        $rel = self::where(['member_miniapp_id' => $miniapp_id])->find();
+        if(empty($rel)){
+            $param['member_miniapp_id'] = $miniapp_id;
+            return self::insert($param);
+        }else{
+            return self::where(['member_miniapp_id' => $miniapp_id])->update($param);
+        }
+    }
+
+    /**
+     * 城市号配置
+     * @return void
+     */
+    public static function info(array $param,int $miniapp_id){
+        $today = [];
+        foreach ($param['info'] as $key => $value) {
+           switch ($key) {
+                case 1:
+                    $today[$key]['day'] = 7;
+                    break;
+                case 2:
+                    $today[$key]['day'] = 15;
+                    break;
+                case 3:
+                    $today[$key]['day'] = 30;
+                    break; 
+               default:
+                    $today[$key]['day'] = 2;
+                    break; 
+           }
+           $today[$key]['money'] = $value;
+        }
+        return self::configs(['info' => json_encode($today)],$miniapp_id);
+    }
+}

+ 47 - 0
application/ais/model/AisCoupon.php

@@ -0,0 +1,47 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 优惠券管理
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisCoupon extends Model{
+
+    protected $pk = 'id';
+
+    public function getTypesnameAttr($value,$data){
+        $status = [0 =>'代金券',1 =>'折扣券',2 =>'兑换券',3 =>'储值券'];
+        return $status[$data['types']];
+    }
+
+    public function getDegreeAttr($value,$data){
+        $status = [0 =>'¥'.$data['price'],1 => $data['discount'].' 折',2 => $data['price'].' 次',3 => '¥'.$data['amount']];
+        return $status[$data['types']];
+    }
+
+    /**
+     * 好店信息
+     * @return void
+     */
+    public function store(){
+        return $this->hasOne('AisStore','id','store_id');
+    }
+    
+    /**
+     * 用户已领油
+     * @return void
+     */
+    public function couponuser(){
+        return $this->hasOne('AisCouponUser','coupon_id','id');
+    }
+
+    //搜索好店名称
+    public function searchNameAttr($query,$value){
+        if(!empty($value)){
+            $query->where('name','like', '%'.$value .'%');
+        }
+    }
+}

+ 23 - 0
application/ais/model/AisCouponSubsidize.php

@@ -0,0 +1,23 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 关联优惠券ID用于补贴
+ */
+namespace app\ais\model;
+use think\Model;
+use util\Util;
+
+class AisCouponSubsidize extends Model
+{
+
+    /**
+     * 补贴优惠券
+     * @return void
+     */
+    public function coupon(){
+        return $this->hasOne('AisCoupon','id','coupon_id');
+    }
+
+}

+ 74 - 0
application/ais/model/AisCouponUser.php

@@ -0,0 +1,74 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 用户优惠券管理
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisCouponUser extends Model{
+
+
+    /**
+     * 好店
+     * @return void
+     */
+    public function store(){
+        return $this->hasOne('AisStore','id','store_id');
+    }
+
+    /**
+     * 用户
+     * @return void
+     */
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','uid');
+    } 
+    
+    /**
+     * 优惠券
+     * @return void
+     */
+    public function coupon(){
+        return $this->hasOne('AisCoupon','id','coupon_id');
+    }
+
+    /**
+     * 批量添加优惠券
+     * @param array $ids  优惠券的ID
+     * @param integer $uid  用户ID
+     * @return void
+     */
+    public static function addUserCoupon($ids,int $uid){
+        $ids = json_decode($ids,true);
+        if(empty($ids)){
+            return;
+        }
+        $coupon = new AisCoupon();
+        $lists = $coupon->where(['id' => $ids])->select();
+        if(empty($lists)){
+            return;
+        }
+        $data = [];
+        foreach ($lists as $key => $value) {
+            $data[$key]['member_miniapp_id'] = $value['member_miniapp_id'];
+            $data[$key]['store_id']          = $value['store_id'];
+            $data[$key]['coupon_id']         = $value['id'];
+            $data[$key]['uid']               = $uid;
+            $data[$key]['parent_store_id']   = 0;
+            $data[$key]['is_end']            = 0;
+            $data[$key]['types']             = $value['types'];
+            $data[$key]['name']              = $value['name'];
+            $data[$key]['price']             = $value['price'];
+            $data[$key]['amount']            = $value['amount'];
+            $data[$key]['discount']          = $value['discount'];
+            $data[$key]['howmuch']           = $value['howmuch'];
+            $data[$key]['tips']              = $value['tips'];
+            $data[$key]['update_time']       = time();
+            $data[$key]['create_time']       = time();
+        }
+        return self::insertAll($data);
+    }
+}

+ 56 - 0
application/ais/model/AisFund.php

@@ -0,0 +1,56 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 采购基金
+ */
+namespace app\ais\model;
+use think\Model;
+use util\Util;
+
+class AisFund extends Model{
+
+    /**
+     * 基金账户充值
+     * @param integer $miniapp_id
+     * @param integer $money(元)
+     * @return void
+     */
+    public function recharge(int $miniapp_id,float $money){
+        $info = self::where(['member_miniapp_id' => $miniapp_id])->find();
+        if(empty($info)){
+            $data['member_miniapp_id'] = $miniapp_id;
+            $data['balance']           = floatval($money);
+            $data['subsidize']         = 0;
+            $data['subsidize_num']     = 0;
+            return self::insert($data);
+        }else{
+            $info->balance = floatval($info->balance+$money);
+            return $info->save();
+        }
+    }
+
+    /**
+     * 账务补贴
+     * @param integer $miniapp_id
+     * @param integer $money(元)
+     * @return void
+     */
+    public function subsidy(int $miniapp_id,float $money){
+        $rel = self::where(['member_miniapp_id' => $miniapp_id])->find();
+        if(empty($rel)){
+            return;
+        }else{
+            if($rel->balance <= 0){
+                return;
+            } 
+            $subsidize = ($rel->balance-$money) < 0 ? $rel->balance : $money;
+            $rel->balance       = ['dec',$subsidize];
+            $rel->subsidize     = ['inc',$subsidize];
+            $rel->subsidize_num = ['inc',1];
+            $rel->save();
+            return $subsidize;
+        }
+    }
+}

+ 34 - 0
application/ais/model/AisFundBill.php

@@ -0,0 +1,34 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 采购基金账单
+ */
+namespace app\ais\model;
+use think\Model;
+use util\Util;
+
+class AisFundBill extends Model
+{
+
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','uid');
+    } 
+
+
+   /**
+     * [log 增加财务日志]
+     * @param  [array]  $param
+     */
+    public static function add(array $param){
+        $data['member_miniapp_id'] = intval($param['miniapp_id']);
+        $data['store_id']          = intval($param['store_id']);
+        $data['types']             = intval($param['types']);
+        $data['uid']               = intval($param['uid']);
+        $data['order_no']          = $param['order_no'];
+        $data['money']             = floatval($param['money']);
+        $data['update_time']       = time();
+        return self::insert($data);
+    }
+}

+ 33 - 0
application/ais/model/AisIncome.php

@@ -0,0 +1,33 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 收益记录表
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisIncome extends Model{
+    
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','pay_uid');
+    }
+
+    /**
+     * [log 增加财务日志]
+     * @param  [array]  $param['miniapp_id = '1'',uid=>'1',store_id=>'1','pay_uid' => 0]
+     * @return [boolean]          [增加成功ID]
+     */
+    public static function add(array $param,$message){
+        $data['member_miniapp_id'] = intval($param['member_miniapp_id']);
+        $data['uid']               = intval($param['uid']);
+        $data['store_id']          = intval($param['store_id']);
+        $data['pay_uid']           = intval($param['pay_uid']);
+        $data['types']             = intval($param['types']);
+        $data['money']             = money($param['money']);
+        $data['message']           = $message;
+        $data['update_time']       = time();
+        return self::create($data);
+    }
+}

+ 147 - 0
application/ais/model/AisInfo.php

@@ -0,0 +1,147 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 分类信息管理
+ */
+namespace app\ais\model;
+use app\common\facade\Inform;
+use app\ais\model\Levels;
+use app\ais\model\Vip;
+use think\Model;
+use util\Util;
+use filter\Filter;
+use think\db\Where;
+
+class AisInfo extends Model{
+
+    protected $pk = 'id';
+
+
+    //用户
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','uid');
+    }
+    
+    //一对多管理回复的评论
+    public function comments(){
+        return $this->hasMany('AisInfoReply','info_id','id');
+    }
+
+    //所属栏目
+    public function cate(){
+        return $this->hasOne('AisInfoCate','id','cate_id');
+    }
+
+    //是否关注
+    public function follow(){
+        return $this->hasOne('AisInfoFollow','like_uid','uid');
+    }
+    
+    //是否认证号
+    public function mp(){
+        return $this->hasOne('AisInfoMp','uid','uid');
+    }
+
+    //搜索器
+    public function searchThemesAttr($query,$value){
+        $value = Filter::filter_escape($value);
+        if(!empty($value)){
+            $query->where('themes','like', '%'. $value .'%');
+        }
+    }
+
+    //Tags字符串转数组
+//    public function getImagesAttr($value){
+//        $imga = [];
+//        foreach ($value as $key => $img) {
+//            $imga[$key] = $img;
+//        }
+//        return $imga;
+//    }
+
+    /**
+     * 锁定
+     * @param integer $id
+     */
+    public static function lock(int $id,$member_miniapp_id){
+        $result = self::where('id',$id)->find();
+        $result->is_lock = $result->is_lock ? 0 : 1;
+        return $result->save();
+    }
+
+   /**
+     * 指定
+     * @param integer $id
+     */
+    public static function top(int $id){
+        $result = self::where('id',$id)->find();
+        $result->is_top = $result->is_top ? 0 : 1;
+        return $result->save();
+    }
+
+
+   /**
+     * API的信息列表查询
+     * @param integer $id
+     */
+    public static function apiLists($where,$order,$user,$keyword = ''){
+        $rel = AisInfo::with([
+            'user' => function($query) {
+                $query->field('id,nickname,face');
+            },
+            'cate' => function($query) {
+                $query->field('id,tpl_id,title');
+            },
+            'mp'   => function($query) {
+                $query->field('id,uid,logo,title,is_vip');
+            }
+        ])->withSearch(['themes'],['themes' => $keyword])->where($where)->order($order)->paginate(10);
+        $data = [];
+        foreach ($rel as $key => $value) {
+            $data[$key]                = $value;
+            if(empty($value->cate->tpl)){
+                $data[$key]['button_name'] = '立即下单';
+                $data[$key]['tips']        = '任何有用户发布,下单后请电话再次确认';
+                $data[$key]['is_shop']     = 0;
+            }else{
+                $data[$key]['button_name'] = $value->cate->tpl->button_name;
+                $data[$key]['tips']        = $value->cate->tpl->tips;
+                $data[$key]['is_shop']     = $value->cate->tpl->is_shop;
+            }
+            $data[$key]['images']      = $value->images;
+            $data[$key]['images_len']  = count($value->images);
+            $data[$key]['fields']      = empty($value->fields) ? [] : json_decode($value->fields,true);
+            $data[$key]['create_time'] = util::ftime($value->create_time);
+            $data[$key]['is_mp']       = empty($value->mp)?0:1;
+            //是否点赞
+            $data[$key]['is_like']     = 0; 
+            $data[$key]['like_face']   = empty($value->like_face) ? [] : json_decode($value->like_face,true);
+            //判断是否被关注
+            $data[$key]['is_follow']   = !empty($value->follow) && ! empty($user)  && $value->follow->uid = $user->id ? 1:0;  
+        }
+        return $data;  
+    }
+
+    //添加或编辑
+    public static function postThemes($param){
+        $data['themes']            = $param['content'];
+        $data['telphone']          = $param['telphone'];
+        $data['top_money']         = $param['top_money'];
+        $data['topday']            = $param['topday'];
+        $data['fields']            = $param['fields'];
+        $data['images']            = $param['imgs'];
+        $data['uid']               = $param['uid'];
+        $data['cate_id']           = $param['cate_id'];
+        $data['store_id']          = $param['store_id'];
+        $data['order_no']          = $param['order_no'];
+        $data['price']             = (int)$param['price'];
+        $data['is_get']            = $param['is_get'];
+        $data['create_time']       = time();
+        $data['views']             = rand(1,500);
+        $data['is_lock']           = 0;
+        $data['member_miniapp_id'] = $param['member_miniapp_id'];
+        return self::create($data);
+    } 
+}

+ 69 - 0
application/ais/model/AisInfoCate.php

@@ -0,0 +1,69 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 信息栏目
+ */
+namespace app\ais\model;
+use think\Model;
+use category\Tree;
+
+class AisInfoCate extends Model{
+
+    protected $pk = 'id';
+
+    //开通好店订单
+    public function tpl(){
+        return $this->hasOne('AisInfoTpl','id','tpl_id');
+    }
+
+    //添加或编辑
+    public static function edit($param){
+        $data['title']     = $param['title'];
+        $data['name']      = $param['name'];
+        $data['sort']      = $param['sort'];
+        $data['tpl_id']    = $param['tpl_id'];
+        $data['update_time']  = time();
+        if(empty($param['id'])){
+            $data['create_time']       = time();
+            $data['member_miniapp_id'] = $param['member_miniapp_id'];
+            return self::insert($data);
+        }else{
+            return self::update($data,['id'=>(int)$param['id']]);
+        }
+    } 
+
+   /**
+     * 获取当前栏目的模板
+     * @param type $parent_id
+     * @return type
+     */
+    public static function cateTpl(int $id){
+        $rel = self::where(['id' => $id])->field('tpl_id')->find();
+        $data = ['is_shop' => 0,'button_name' => '下单','users' => [],'fields' =>[]];
+        if(isset($rel->tpl)){
+            $fields = json_decode($rel->tpl->fields,true);
+            foreach ($fields as $key => $value) {
+                if($value['types'] == 'selector'){
+                    $fields[$key]['value'] = '';
+                }else{
+                    $fields[$key]['value'] = $value['values'];
+                }
+            } 
+            $users = json_decode($rel->tpl->users,true);
+            foreach ($users as $key => $value) {
+                if($value['types'] == 'selector'){
+                    $users[$key]['value'] = '';
+                }else{
+                    $users[$key]['value'] = $value['values'];
+                }
+            } 
+            $data['fields']      = $fields;
+            $data['users']       = $users;
+            $data['is_shop']     = $rel->tpl->is_shop;
+            $data['button_name'] = $rel->tpl->button_name;
+        }
+        return $data;
+    }
+}

+ 15 - 0
application/ais/model/AisInfoFollow.php

@@ -0,0 +1,15 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 评论管理
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisInfoFollow extends Model{
+
+    protected $pk = 'id';
+    
+}

+ 45 - 0
application/ais/model/AisInfoMp.php

@@ -0,0 +1,45 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 同城模板库
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisInfoMp extends Model{
+    
+    protected $pk    = 'id';
+    protected $autoWriteTimestamp = true;
+    
+    //关联用户信息
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','uid');
+    }
+
+    /**
+     * 保存数据
+     * @param  string $array 传入的保存数据的参数
+     * @return json
+     */
+    public static function edit(array $param){
+        $data = [
+            'uid'       => $param['uid'],
+            'logo'      => $param['logo'],
+            'title'     => $param['title'],
+            'note'      => $param['note'],
+            'is_vip'    => $param['is_vip'],
+            'vip_title' => $param['vip_title'],
+            'vip_about' => $param['vip_about'],
+            'vip_time'  => $param['vip_time']? strtotime($param['vip_time']):'',
+            'reg_time'  => time()
+        ];
+        if(empty($param['id'])){
+            $data['member_miniapp_id'] = $param['member_miniapp_id'];
+            return self::insertGetId($data);
+        }else{
+            return self::where(['id' => $param['id']])->update($data);
+        }        
+    } 
+}

+ 55 - 0
application/ais/model/AisInfoOrder.php

@@ -0,0 +1,55 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 订单数据
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisInfoOrder extends Model{
+    
+    protected $pk    = 'id';
+
+    /**
+     * @return \think\model\relation\HasOne
+     * 商品
+     */
+    public function info(){
+        return $this->hasOne('AisInfo','id','info_id');
+    }
+
+    /**
+     * @return \think\model\relation\HasOne
+     * 用户
+     */
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','uid');
+    }
+
+    /**
+     * @param $data
+     * @param $order_no
+     * 购买商品生成订单数据
+     */
+    public static function insertOrder($param,$order_no){
+        $order = [
+            'order_no'          => $order_no,
+            'info_id'           => $param['id'],
+            'info_uid'          => $param['info_uid'],
+            'member_miniapp_id' => $param['member_miniapp_id'],
+            'phone'             => $param['telphone'],
+            'message'           => $param['message'],
+            'uid'               => $param['uid'],
+            'amount'            => $param['amount'],
+            'cache'             => $param['cache'],
+            'fields'            => $param['fields'],
+            'status'            => 0,
+            'is_del'            => 0,
+            'paid_at'           => 0,
+            'create_time'       => time()
+        ];
+        return self::create($order);
+    }
+}

+ 47 - 0
application/ais/model/AisInfoReply.php

@@ -0,0 +1,47 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 评论管理
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisInfoReply extends Model{
+
+    protected $pk = 'id';
+    protected $autoWriteTimestamp = true;
+    protected $datetime_format = 'Y-m-d H:i:s.u';
+
+    //用户
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','uid');
+    }
+
+    //用户
+    public function info(){
+        return $this->hasOne('AisInfo','id','info_id');
+    }
+
+    //添加或编辑
+    public static function postReply($param){
+        $data['reply']             = trim($param['content']);
+        $data['member_miniapp_id'] = (int)$param['member_miniapp_id'];
+        $data['uid']               = (int)$param['uid'];
+        $data['info_id']           = (int)$param['info_id'];
+        $data['create_time']       = time();
+        $data['state']             = 0;
+        return self::create($data);
+    }
+
+    /**
+     * 锁定
+     * @param integer $id
+     */
+    public static function lock(int $id){
+        $result = self::where(['id' => $id])->find();
+        $result->state = $result->state ? 0 : 1;
+        return $result->save();;
+    }
+}

+ 56 - 0
application/ais/model/AisInfoShare.php

@@ -0,0 +1,56 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 分享记录
+ */
+namespace app\ais\model;
+use think\Model;
+use app\common\model\SystemUser;
+use think\helper\Time;
+use filter\Filter;
+
+class AisInfoShare extends Model{
+
+    protected $pk     = 'id';
+
+     /**
+     * 判断分享记录如果合规发红包
+     * @return void
+     */
+    public function redRocket(array $param,$ucode = null){
+        if(empty($ucode)){
+            return;
+        }
+        if ($param['paid_at'] <= 0 || $param['task_money'] <= 0) {
+            return;
+        }
+        $uid = SystemUser::isInvite(Filter::filter_escape($ucode));
+        if(empty($uid)){
+            return;
+        }
+        list($start,$end) = Time::today();
+        $condition[] = ['info_id','=',$param['id']];
+        $condition[] = ['times','>',$start];
+        $condition[] = ['uid','=',$uid];
+        $rel = self::where($condition)->find();
+        if($rel){
+            return self::where(['info_id'=> $param['id']])->setInc('views',1);
+        }else{
+            $data['uid']     = $uid;
+            $data['info_id'] = $param['id'];
+            $data['views']   = 1;
+            $data['times']   = time();
+            return self::insert($data);
+        }
+    }
+    
+     /**
+     * 发红包
+     * @return void
+     */
+    public function postRedRocket(array $param,$ucode = null){
+        
+    }
+}

+ 103 - 0
application/ais/model/AisInfoTpl.php

@@ -0,0 +1,103 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 同城模板库
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisInfoTpl extends Model{
+    
+    protected $pk    = 'id';
+    protected $autoWriteTimestamp = true;
+    
+    /**
+     * 保存数据
+     * @param  string $array 传入的保存数据的参数
+     * @return json
+     */
+    public static function edit(array $param){
+        //处理规格参数
+        $title       = $param['titles'];
+        $types       = $param['types'];
+        $values      = $param['values'];
+        $placeholder = $param['placeholder'];
+        //判断新增还是修改
+        $spec_value_data = [];
+        foreach ($param['titles'] as $key => $value) {
+            $spec_value_data[$key]['title']       = $title[$key];
+            $spec_value_data[$key]['types']       = $types[$key];
+            $spec_value_data[$key]['placeholder'] = $placeholder[$key];
+            if($types[$key] == 'selector'){
+                if(empty($values[$key])){
+                    $spec_value_data[$key]['values'] = [];
+                }else{
+                    $spec_value_data[$key]['values'] = explode('|',$values[$key]);
+                }
+            }else{
+                $spec_value_data[$key]['values'] = $values[$key];
+            }
+        }
+        $spec_data['fields']        = json_encode($spec_value_data);
+        $spec_data['name']          = $param['name'];
+        $spec_data['update_time']   = time();
+        if(empty($param['id'])){
+            $spec_data['member_miniapp_id'] = $param['member_miniapp_id'];
+            $spec_data['users'] = '[]';
+            $rel = self::insertGetId($spec_data);
+        }else{
+            $rel = self::where(['id' => $param['id']])->update($spec_data);
+        }
+        if(empty($rel)){
+            return enjson(403);
+        }
+        return enjson(200);
+    } 
+
+   /**
+     * 保存数据
+     * @param  string $array 传入的保存数据的参数
+     * @return json
+     */
+    public static function usersEdit(array $param){
+        //处理规格参数
+        $title       = $param['titles'];
+        $types       = $param['types'];
+        $values      = $param['values'];
+        $placeholder = $param['placeholder'];
+        //判断新增还是修改
+        $spec_value_data = [];
+        foreach ($param['titles'] as $key => $value) {
+            $spec_value_data[$key]['title']       = $title[$key];
+            $spec_value_data[$key]['types']       = $types[$key];
+            $spec_value_data[$key]['placeholder'] = $placeholder[$key];
+            if($types[$key] == 'selector'){
+                if(empty($values[$key])){
+                    $spec_value_data[$key]['values'] = [];
+                }else{
+                    $spec_value_data[$key]['values'] = explode('|',$values[$key]);
+                }
+            }else{
+                $spec_value_data[$key]['values'] = $values[$key];
+            }
+        }
+        $spec_data['users']         = json_encode($spec_value_data);
+        $spec_data['button_name']   = $param['name'];
+        $spec_data['tips']          = $param['tips'];
+        $spec_data['is_shop']       = $param['is_shop'];
+        $spec_data['update_time']   = time();
+        if(empty($param['id'])){
+            $spec_data['member_miniapp_id'] = $param['member_miniapp_id'];
+            $spec_data['fields'] = '[]';
+            $rel = self::insertGetId($spec_data);
+        }else{
+            $rel = self::where(['id' => $param['id']])->update($spec_data);
+        }
+        if(empty($rel)){
+            return enjson(403);
+        }
+        return enjson(200);
+    }
+}

+ 265 - 0
application/ais/model/AisOrder.php

@@ -0,0 +1,265 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 订单管理
+ */
+namespace app\ais\model;
+use app\common\model\SystemUserLevel;
+use app\common\facade\WechatPay;
+use think\Model;
+
+class AisOrder extends Model{
+
+
+    public function store(){
+        return $this->hasOne('AisStore','id','store_id');
+    }
+
+
+    public function conponUser(){
+        return $this->hasOne('AisCouponUser','id','coupon_user_id');
+    }
+
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','uid');
+    }
+    /**
+     * 创建订单
+     * @param array $param
+     * @return void
+     */
+    public static function addOrder(array $param){
+        $data                      = [];
+        $data['member_miniapp_id'] = $param['member_miniapp_id'];
+        $data['store_id']          = $param['store_id'];
+        $data['store_chain_id']    = $param['store_chain_id'];
+        $data['parent_store_id']   = $param['parent_store_id'] ?? 0;
+        $data['uid']               = $param['uid'];
+        $data['coupon_user_id']    = $param['user_couponr_id'];
+        $data['order_no']          = $param['order_no'];
+        $data['amount']            = $param['money'];   //输入金额
+        $data['price']             = $param['price'];   //实际金额
+        $data['coupon_cache']      = empty($param['coupon_cache'])?'':json_encode($param['coupon_cache']);  //留存优惠券
+        $data['state']             = 0;
+        $data['update_time']       = time();
+        return self::insertGetId($data);
+    }
+
+  /**
+     * 计算器付款价格
+     * @param array $param  [计算参数]
+     * @return type
+     */
+    public static function countPrice(array $param){
+        $money = floatval($param['money']);  //用户默认付款价
+        //我的优惠券
+        $coupon_user = [];
+        $coupon_user['member_miniapp_id'] = $param['member_miniapp_id'];
+        $coupon_user['store_id']          = $param['store_id'];
+        $coupon_user['id']                = $param['user_couponr_id'];
+        $coupon_user['uid']               = $param['uid'];
+        $coupon_user['is_end']            = 0;
+        $coupon_user_rel = AisCouponUser::where($coupon_user)->find();
+        //需要优惠的价格(分)
+        $coupon_user_price = 0;
+        if(!empty($coupon_user_rel)){
+            if($money < $coupon_user_rel->howmuch){
+                return false;
+            }
+            $config = AisConfig::getConfig($coupon_user['member_miniapp_id']);
+            if(!empty($config->coupon_longtime) && ($coupon_user_rel->create_time + $config->coupon_longtime * 60 * 60) <= time()){
+                return false;
+            }
+            if($coupon_user_rel->types){//折扣
+                $coupon_user_price = $money - $money * ($coupon_user_rel->discount/10); 
+            }else{//代金
+                $coupon_user_price = $coupon_user_rel->price;
+            }
+        }
+        $amount         = $money - $coupon_user_price;
+        $data['price']  = $amount <= 0 ? 0.01 : $amount;
+        $data['coupon'] = $coupon_user_rel;
+        return $data;
+    }
+
+
+    /**
+     * 微信买单收益分账
+     * @param array $order  订单信息
+     * @return void
+     */
+    public static function income($order,$allMoney,$flag){
+        $store = AisStore::where(['id' => $order->store_id])->find();
+        if(empty($store)){
+            return;
+        }
+        $setting = AisConfig::getConfig($store->member_miniapp_id);
+        $storeProfit = AisStore::where(['id' => $order->parent_store_id])->find();
+        //没有分帐直接返回
+        if($flag == 'N'){
+            //如果是店铺直接会员  只扣手续费
+            $order->parent_store_price = 0;
+            $order->real = money($allMoney - $allMoney * 6 / 1000);
+            return $order;
+        }
+        //平台所扣费率
+        $charge = $store->charge ?? $setting->charge;
+        $queen       = []; //分账队列参数
+        //会员买单奖励
+        if($flag == 'Y'  && !empty($setting) && !empty($setting->group_profit)){
+            //平台所需扣除总额
+            $profitMoney = money($allMoney * $charge);
+            //平台承担手续费
+            $charges =  money($allMoney * 6 / 1000);
+            //扣除平台收费后所余
+            $allMoney  = money($allMoney - $profitMoney);
+            //用户的直接上级会员
+            $level = SystemUserLevel::where(['user_id' => $order->uid,'level' => 1])->find();
+            if(!empty($level)){
+                //直接上级会员所属会员组
+                $storeLevel_1 = AisStore::where(['manage_uid' => $level->parent_id])->find();
+                $vipUser = AisVipUser::where(['member_miniapp_id' => $store->member_miniapp_id,'uid' => $level->parent_id,'is_lock' => 0])->find();
+                $ex = $profitMoney;  //临时用
+                //根据直接上级会员组配置开始分帐
+                if(!empty($vipUser)){
+                    $vip = AisVip::where(['member_miniapp_id' => $store->member_miniapp_id,'id' => $vipUser->vip_id,'is_lock' => 0])->find();
+                    if(!empty($vip)){
+                        $money = money($ex * $vip->pay_share_reward);
+                        //会员余额增加
+                        $bank = AisBank::where(['uid' => $level->parent_id])->find();
+                        if(empty($bank)){
+                            $bank = new AisBank;
+                            $bank->uid = $level->parent_id;
+                            $bank->member_miniapp_id = $order->member_miniapp_id;
+                            $bank->money = 0;
+                        }
+                        $bank->money = $bank->money + $money;
+                        $bank->save();
+                        AisBill::add(['member_miniapp_id' => $store->miniapp_id,'store_id' => $store->id,'money' => $money,'uid' => $level->parent_id],'微信支付[奖励]');
+                    }
+                }
+                //如果上级会员有店铺
+                if(!empty($storeLevel_1)){
+                    $level_2 = SystemUserLevel::where(['user_id' => $level->parent_id,'level' => 1])->find();
+                    if(empty($level_2)){
+                        $vipUser = AisVipUser::where(['member_miniapp_id' => $store->member_miniapp_id,'uid' => $level_2->parent_id,'is_lock' => 0])->find();
+                        if(!empty($vipUser)){
+                            $vip = AisVip::where(['member_miniapp_id' => $store->member_miniapp_id,'id' => $vipUser->vip_id,'is_lock' => 0])->find();
+                            if(!empty($vip)){
+                                $money = money($ex * $vip->pay_queue_reward);
+                                //会员余额增加
+                                $bank = AisBank::where(['uid' => $level_2->parent_id])->find();
+                                if(empty($bank)){
+                                    $bank = new AisBank;
+                                    $bank->uid = $level_2->parent_id;
+                                    $bank->member_miniapp_id = $order->member_miniapp_id;
+                                    $bank->money = 0;
+                                }
+                                $bank->money = $bank->money + $money;
+                                $bank->save();
+                                AisBill::add(['member_miniapp_id' => $store->miniapp_id,'store_id' => $store->id,'money' => $money,'uid' => $level_2->parent_id],'微信支付[奖励]');
+                            }
+                        }
+                    }
+                }
+            }
+            //引荐买单奖励
+            $profitMoney = 0;
+            if(!empty($storeProfit)){
+                $money = money($ex * $setting->group_profit);
+                $profitMoney  = money($profitMoney - $money);
+                $queen[] = [
+                    'member_miniapp_id' => $storeProfit->member_miniapp_id,
+                    'store_id'          => $storeProfit->id,
+                    'uid'               => 0,
+                    'mch_id'            => $storeProfit->mch_id,
+                    'amount'            => $money * 100,
+                    'transaction_id'    => $order->paid_no,
+                    'out_order_no'      => $order->order_no,
+                    'is_finish'         => 0,
+                    'types'             => 1,
+                    'msg'               =>'结算到商户号',
+                ];
+                AisStoreBill::add(['miniapp_id' => $storeProfit->member_miniapp_id,'uid' => $storeProfit->manage_uid,'store_id' => $storeProfit->id,'pay_uid' => $order['user_id'],'money' => $profitMoney],'引荐买单奖励'); //引荐商家账单
+            }
+            //平台收入
+            $profitMoney = money($profitMoney - $charges);
+            if(!empty($setting->config)){
+                $queen[] = [
+                    'member_miniapp_id' => $store->member_miniapp_id,
+                    'store_id'          => $store->id,
+                    'uid'               => 0,
+                    'mch_id'            => 0,
+                    'amount'            => $profitMoney * 100,
+                    'transaction_id'    => $order->paid_no,
+                    'out_order_no'      => $order->order_no,
+                    'is_finish'         => 0,
+                    'types'             => 2,
+                    'msg'               => '结算到平台',
+                ];
+            }
+            //分给商户
+            $queen[] = [
+                'member_miniapp_id' => $store->member_miniapp_id,
+                'store_id'          => $store->id,
+                'uid'               => 0,
+                'mch_id'            => $store->mch_id,
+                'amount'            => $allMoney * 100,
+                'transaction_id'    => $order->paid_no,
+                'out_order_no'      => $order->order_no,
+                'is_finish'         => 0,
+                'types'             => 1,
+                'msg'               => '结算到商户号',
+            ];
+            $order->parent_store_price = $profitMoney;
+            $order->real = $allMoney;
+            AisQueen::createQueen($queen);
+        }
+        return $order;
+    }
+
+    //优惠券补贴
+    public static function subsidy($order){
+        $subsideze = AisCouponSubsidize::where(['member_miniapp_id' =>$order->member_miniapp_id,'coupon_id' => $order->conponUser->coupon_id])->find();
+        if($subsideze){
+//            $setting   =    AisConfig::getConfig($order->member_miniapp_id);
+            //判断是否成功
+            $is_success                       = false;
+            $trade_no                         = $order->order_no . 'WE';
+            $subsidezeBill = AisFundBill::where(['member_miniapp_id' =>$order->member_miniapp_id,'order_no' => $trade_no])->find();
+            if(empty($subsidezeBill)){
+                $subsidezeBill                    = new AisFundBill;
+                $subsidezeBill->member_miniapp_id = $order->member_miniapp_id;
+                $subsidezeBill->store_id          = $order->store_id;
+                $subsidezeBill->uid               = $order->member_miniapp_id;
+                $subsidezeBill->types             = 1;
+                $subsidezeBill->money             = $subsideze->how_much;
+                $subsidezeBill->order_no          = $trade_no;
+            }
+            if(!empty($order->store->user->official_uid) && $subsideze->how_much < 5000){
+                    $app = WechatPay::doPay($order->member_miniapp_id,true);
+                    $rel = $app->transfer->toBalance(['partner_trade_no' => $trade_no,'openid' => $order->store->user->official_uid,'check_name' => 'NO_CHECK','amount' => $subsideze->how_much*100,'desc' => '优惠券补贴']);
+                    if ($rel['return_code'] === 'SUCCESS') {
+                        if ($rel['result_code'] === 'SUCCESS') {
+                            $is_success = true;
+                            $subsidezeBill->state      = 1;
+                            $subsidezeBill->message    = "优惠券补贴已结算到微信钱包";
+                        }else{
+                            $subsidezeBill->message    = $rel['err_code_des'];
+                        }
+                    }else{
+                        $subsidezeBill->message    = $rel['return_msg'];
+                    }
+            }
+            if(!$is_success){
+                $subsidezeBill->state      = 2;
+            }
+            $subsidezeBill->update_time       = time();
+            return $subsidezeBill->save();
+        }else{
+            return false;
+        }
+    }
+}

+ 76 - 0
application/ais/model/AisQueen.php

@@ -0,0 +1,76 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 分账队列
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisQueen extends Model{
+    
+    protected $pk     = 'id';
+    
+    //商家
+    public function store(){
+        return $this->hasOne('AisStore','id','store_id');
+    }
+    
+    //用户
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','uid');
+    }
+
+    /**
+     * 创建分账队列
+    * $data[] = [
+    *     'member_miniapp_id' => 应用ID,
+    *     'store_id'          => 店铺ID,
+    *     'uid'               => 0,
+    *     'mch_id'            => 商户ID,
+    *     'amount'            => 金额分
+    *     'transaction_id'    => 微信支付订单号,
+    *     'out_order_no'      => 支付订单号,
+    *     'is_finish'         => 0,
+    *     'types'             => 1, (0用户/1商家)
+    *     'msg'               => 日志内容,
+    * ];
+     */
+    public static function createQueen(array $data){
+        $mch_queen = [];
+        $uid_queen = [];
+        foreach ($data as $value) {
+            switch ($value['types']) {
+                case 0:  //个人
+                    if(!isset($uid_queen[$value['uid']])){
+                        $uid_queen[$value['uid']] = $value;
+                        $uid_queen[$value['uid']]['msg'] = $value['msg'].'(¥'.money($value['amount']/100).')';
+                    }else{
+                        $uid_queen[$value['uid']]['amount'] += $value['amount'];
+                        $uid_queen[$value['uid']]['msg'] .= ' | '.$value['msg'].'(¥'.money($value['amount']/100).')';
+                    }
+                    break;
+                case 1:   //商家
+                    if(!isset($mch_queen[$value['mch_id']])){
+                        $mch_queen[$value['mch_id']] = $value;
+                        $mch_queen[$value['mch_id']]['msg'] = $value['msg'].'(¥'.money($value['amount']/100).')';
+                    }else{
+                        $mch_queen[$value['mch_id']]['amount'] += $value['amount'];
+                        $mch_queen[$value['mch_id']]['msg'] .= ' | '.$value['msg'].'(¥'.money($value['amount']/100).')';
+                    }
+                    break;
+                default:
+                    $mch_queen[$value['mch_id']] = $value;
+                    break;
+            }
+        }
+        $mch = array_values($mch_queen);
+        $uid = array_values($uid_queen);
+        $queen = array_merge($mch,$uid);
+        if(empty($queen)){
+            return;
+        }
+        return self::insertAll($queen);
+    } 
+}

+ 220 - 0
application/ais/model/AisShop.php

@@ -0,0 +1,220 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 商品管理(SPU)
+ */
+namespace app\ais\model;
+use app\ais\model\AisCoupon;
+use app\ais\model\AisCouponUser;
+use app\ais\model\AisVipUser;
+use think\Model;
+
+class AisShop extends Model{
+    
+    protected $pk    = 'id';
+    protected $autoWriteTimestamp = true;
+    protected $json               = ['imgs'];
+    //店铺
+    public function store(){
+        return $this->hasOne('AisStore','id','store_id');
+    }
+
+    //栏目名称
+    public function cate(){
+        return $this->hasOne('AisShopCate','id','category_id');
+    }
+
+    //选择优惠券
+    public function coupon(){
+        return $this->hasOne('AisCoupon','id','coupon_id');
+    }
+
+    //搜索器
+    public function searchNameAttr($query,$value){
+        if(!empty($value)){
+            $query->where('name','like', '%'.$value .'%');
+        }
+    }
+
+    //Tags字符串转数组
+    public function getImgsAttr($value){
+        $imga = [];
+        foreach ($value as $key => $img) {
+            $imga[$key] = $img;
+        }
+        return $imga;
+    }
+
+    //图片转换
+    public function getImgAttr($value){
+       return $value;
+    } 
+
+
+    //上下架状态返回
+    public function getSaleAttr($value,$data){
+        $status = [0 =>'下架',1 =>'在售'];
+        return $status[$data['is_sale']];
+    }
+
+    //状态返回
+    public function getTypesnameAttr($value,$data){
+        $status = [0 =>'默认属性',1 =>'首页推荐',2 =>'首页专题',3 =>'精选专栏'];
+        return $status[$data['types']];
+    }
+
+    //添加或编辑
+    public static function edit(array $param){
+        $data['category_id']       = $param['category_id'];
+        $data['store_id']          = $param['store_id'];
+        $data['citycode']         = $param['citycode'];
+        $data['name']              = $param['name'];
+        $data['title']             = $param['title'];
+        $data['types']             = $param['types'];
+        $data['market_price']      = $param['market_price'];
+        $data['sell_price']        = $param['sell_price'];
+        $data['cost_price']        = $param['cost_price'];
+        $data['vip_price']         = $param['vip_price'];
+        $data['share_price']       = $param['share_price'];
+        $data['share_vip_price']   = $param['share_vip_price'];
+        $data['points_price']      = $param['points_price'];
+        $data['warehouse_num']     = $param['warehouse_num'];
+        $data['warehouse_sellnum'] = $param['warehouse_sellnum'];
+        $data['coupon_id']         = $param['coupon_id'];
+        $data['content']           = $param['content'];
+        $data['img']               = $param['img'];
+        $data['imgs']              = $param['imgs'];
+        $data['types']             = $param['types'];
+        $data['group_title']       = $param['group_title'];
+        $data['group_note']        = $param['group_note'];
+        $data['group_img']         = $param['group_img'];
+        $data['keyword']           = $param['keyword'];
+        $data['notice']            = $param['notice'];
+        $data['end_time']          = empty($param['end_time']) ? '' : strtotime($param['end_time']);
+        $data['update_time']       = time();
+        if(empty($param['id'])){
+            $data['is_sale']           = 0;
+            $data['member_miniapp_id'] = $param['member_miniapp_id'];
+            return self::insertGetId($data);
+        }else{
+            self::where('id',$param['id'])->update($data);
+            return $param['id'];
+        }
+    }
+    
+    //批量操作
+    public static function ids_action(int $is_sale,string $ids){
+        switch ($is_sale) {
+            case 1:
+                $data['is_sale'] = 1; //在售
+                break;
+            case 2:
+                $data['is_del']  = 1;  //删除
+                break;
+            default:
+                $data['is_sale'] = 0;
+                $data['is_del']  = 0;
+                break;
+        }
+        return self::whereIn('id',ids($ids))->data($data)->update(); //操作所有SPU商品
+    }  
+
+    /**
+     * 删除SPU商品
+     * @param [type] $id
+     * @param [type] $ids
+     * @return void
+     */
+    public static function ids_delete(int $id,$ids){
+        if(empty($ids)){
+            $ids = (int)$id;
+        }else{
+            $ids = ids($ids);
+        }
+        $rel = self::whereIn('id',$ids)->field('is_del,id')->select()->toArray();
+        if(!empty($rel)){
+            $del_data = [];
+            $up_data  = [];
+            foreach ($rel as $value) {
+                if($value['is_del'] == 1){
+                    $del_data[] = $value['id'];
+                }else{
+                    $up_data[]  = $value['id'];
+                }
+            }
+            if(!empty($del_data)){
+               self::whereIn('id',$del_data)->delete();
+            }
+            if(!empty($up_data)){
+                self::whereIn('id',$up_data)->update(['is_del' => 1]);
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 如果使用了优惠券的默认价格
+     * [0 =>'代金券',1 =>'折扣券',2 =>'兑换券',3 =>'储值券'];
+     */
+    public static function couponPrice($sell_price,$coupon){
+        if(empty($coupon)){
+            return 0;
+        }
+        switch ($coupon->types) {
+            case 1:
+                return money($sell_price - $sell_price * $coupon->discount/10); 
+                break;
+            case 2:
+                return money($coupon->price);
+                break;
+            case 3:
+                return 0;
+                break;
+            default:
+                return money($coupon->price);
+                break;
+        }
+    }
+
+    /**
+     * 用户下单价格计算
+     */
+    public static function userPayPrice($item,$uid){
+        $item->coupon_price      = 0;
+        $item->coupon_user_price = 0;
+        if($item->coupon_id){
+            $item->coupon_price = self::couponPrice($item->sell_price,$item->coupon);
+            $coupon = AisCouponUser::where([['uid','=',$uid],['is_end','=',0],['coupon_id','=',$item->coupon_id]])->order('id desc')->find();
+            if($coupon){
+                $item->coupon_user_price = self::couponPrice($item->sell_price,$item->coupon);
+            }
+        }
+        //判断积分
+        $item->is_vip            = 0;
+        $item->user_points       = 0; //有多少积分
+        $item->user_point        = 0; //多少积分
+        $item->user_point_price  = 0; //抵多少钱
+        $item->user_vip_price    = 0; //会员实际节省多少钱
+        $vip_user = AisVipUser::where(['uid' => $uid,'is_lock' => 0])->find();
+        if($vip_user){
+            $item->user_vip_price = $item->vip_price;
+            $item->user_points    = $vip_user->point;
+            $item->is_vip         = 1;
+            //判断积分可以
+            if(!empty($vip_user->point)){
+                if($vip_user->point >= $item->points_price*100){
+                    $item->user_point       = $item->points_price*100;
+                    $item->user_point_price = money($item->points_price);
+                }else{
+                    $item->user_point       = $vip_user->point;
+                    $item->user_point_price = money($vip_user->point/100);
+                }
+            }
+        }
+        $item->amount  = $item->sell_price - $item->user_vip_price - $item->user_point_price - $item->coupon_user_price;
+        $item->thrifty = money($item->market_price - $item->amount) ?: 0;
+        return $item;
+    }
+}

+ 56 - 0
application/ais/model/AisShopCate.php

@@ -0,0 +1,56 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 商品分类管理
+ */
+namespace app\ais\model;
+use think\Model;
+use category\Tree;
+
+class AisShopCate extends Model{
+
+    protected $pk     = 'id';
+    
+    //添加或编辑
+    public static function edit($param){
+        $data['title']       = $param['title'];
+        $data['content']     = $param['content'];
+        $data['picture']     = $param['picture'];
+        $data['types']       = $param['types'];
+        $data['show_type']   = $param['show_type'];
+        $data['update_time'] = time();
+        if(empty($param['id'])){
+            $data['create_time']       = time();
+            $data['member_miniapp_id'] = $param['member_miniapp_id'];
+            return self::insert($data);
+        }else{
+            return self::update($data,['id'=>(int)$param['id']]);
+        }
+    } 
+
+    /**
+     * 获取访问路径
+     * @param int $parent_id
+     */
+    public static function selectPath(int $miniapp_id,$parent_id) {
+        $pathMaps[] = ['name'=>'根目录','url'=>url('ais/shopCate/index')];
+        $getPath = self::getPath($miniapp_id,$parent_id);
+        foreach ($getPath as $value) {
+            $pathMaps[] = ['name' => $value['title'],'url' => url('ais/shopCate/index',['parent_id'=>$value['id']])];
+        }
+        return $pathMaps;
+    }
+
+    /**
+     * 获取当前路径
+     * @param type $parent_id
+     * @return type
+     */
+    public static function getPath($miniapp_id,$parent_id){
+        $result = self::field('id,title,parent_id')->where(['member_miniapp_id' => $miniapp_id])->select();
+        $tree =  new Tree(array('id','parent_id','title','name'));
+        return $tree->getPath($result,$parent_id);
+    }
+}

+ 14 - 0
application/ais/model/AisShopCoupon.php

@@ -0,0 +1,14 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 广告位管理
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisShopCoupon extends Model{
+
+
+}

+ 182 - 0
application/ais/model/AisShopOrder.php

@@ -0,0 +1,182 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 订单数据
+ */
+namespace app\ais\model;
+use app\common\model\SystemUserLevel;
+use think\Model;
+
+class AisShopOrder extends Model{
+    
+    protected $pk    = 'id';
+    protected $type = [
+        'shop_cache' => 'array',
+    ];
+    
+    /**
+     * @return \think\model\relation\HasOne
+     * 商品
+     */
+    public function shop(){
+        return $this->hasOne('AisShop','id','shop_id');
+    }
+
+    /**
+     * @return \think\model\relation\HasOne
+     * 店铺
+     */
+    public function store(){
+        return $this->hasOne('AisStore','id','store_id');
+    }
+
+     /**
+     * @return \think\model\relation\hasMany
+     * 店铺管理员类别
+     */
+    public function storeWorker(){
+        return $this->hasMany('AisStoreWorker','store_id','store_id');
+    }
+
+    /**
+     * @return \think\model\relation\HasOne
+     * 用户
+     */
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','uid');
+    }
+
+    /**
+     * 订单是否核销
+     */
+    public function getStatuAttr($value,$data){
+        $statu = [0 =>'待核销',1 =>'已核销'];
+        return $statu[$data['status']];
+    }
+
+
+    /**
+     * @param $data
+     * @param $order_no
+     * 购买商品生成订单数据
+     */
+    public static function createOrder($param,$order_no){
+        $order = [
+            'shop_id'           => $param['id'],
+            'store_id'          => $param['store_id'],
+            'member_miniapp_id' => $param['member_miniapp_id'],
+            'phone'             => $param['telphone'],
+            'message'           => $param['message'],
+            'share_uid'         => $param['share_uid'] ?: 0,
+            'uid'               => $param['uid'],
+            'order_no'          => $order_no,
+            'points'            => $param['points'],
+            'amount'            => $param['amount'],
+            'sell_price'        => $param['sell_price'],
+            'thrifty'           => $param['thrifty'],
+            'shop_cache'        => $param['shop_cache'],
+            'status'            => 0,
+            'is_del'            => 0,
+            'paid_at'           => 0,
+            'create_time'       => time()
+        ];
+        return self::create($order);
+    }
+
+    public static function income($order,$total_fee,$flag){
+        $allMoney = money(($total_fee - $total_fee * 6 / 1000));
+        $ex = 0;
+        $order->real = $allMoney;
+        $store = AisStore::where(['id' => $order->store_id])->field('id,member_miniapp_id,charges,manage_uid,mch_id,name')->find();
+        if(empty($store) && $flag == 'N'){
+            return;
+        }
+        //商品信息
+        $shopItme = AisShop::where(['member_miniapp_id'=>$order->member_miniapp_id,'id' => $order->shop_id])->find();
+        $queen       = []; //分账队列参数
+        //上级会员
+        $level = SystemUserLevel::where(['user_id' => $order->uid,'level' => 1])->find();
+        //发放会员收益
+        if($store->manage_uid != $level->parent_id && $shopItme->share_vip_price){
+            if($level){
+                $money =  money($shopItme->sell_price * $shopItme->share_vip_price);
+                $allMoney -= $money;
+                $ex += $money;
+                if($money >= 0){
+                    //会员余额增加
+                    $bank = AisBank::where(['uid' => $level->parent_id])->find();
+                    if(empty($bank)){
+                        $bank = new AisBank;
+                        $bank->uid = $level->parent_id;
+                        $bank->member_miniapp_id = $order->member_miniapp_id;
+                        $bank->money = 0;
+                    }
+                    $bank->money = $bank->money + $money;
+                    $bank->save();
+                    AisBill::add(['miniapp_id'=>$order->member_miniapp_id,'store_id' => 0,'money' => $money,'uid'=>$level->parent_id], '优选下单会员收益');
+                }
+            }
+
+        }
+        //发放分享收益
+        if($order->share_uid){
+            $money =  money($shopItme->sell_price * $shopItme->share_price);
+            $allMoney -= $money;
+            $ex += $money;
+            if($money >= 0){
+                //会员余额增加
+                $bank = AisBank::where(['uid' => $order->share_uid])->find();
+                if(empty($bank)){
+                    $bank = new AisBank;
+                    $bank->uid = $order->share_uid;
+                    $bank->member_miniapp_id = $order->member_miniapp_id;
+                    $bank->money = 0;
+                }
+                $bank->money = $bank->money + $money;
+                $bank->save();
+                AisBill::add(['miniapp_id'=>$order->member_miniapp_id,'store_id' => 0,'money' => $money,'uid'=>$order->share_uid], '分享商品收益');
+            }
+        }
+        if($allMoney > 0){
+            if($store->mch_id){
+                //分给商户
+                $queen[] = [
+                    'member_miniapp_id' => $store->member_miniapp_id,
+                    'store_id'          => $store->id,
+                    'uid'               => 0,
+                    'mch_id'            => $store->mch_id,
+                    'amount'            => $allMoney  * 100,
+                    'transaction_id'    => $order->paid_no,
+                    'out_order_no'      => $order->order_no,
+                    'is_finish'         => 0,
+                    'types'             => 1,
+                    'msg'               => '结算到商户号',
+                ];
+            }
+            if($ex > 0){
+                //平台收入
+                $queen[] = [
+                    'member_miniapp_id' => $order->member_miniapp_id,
+                    'store_id'          => 0,
+                    'uid'               => 0,
+                    'mch_id'            => 0,
+                    'amount'            => $ex * 100,
+                    'transaction_id'    => $order->paid_no,
+                    'out_order_no'      => $order->order_no,
+                    'is_finish'         => 0,
+                    'types'             => 2,
+                    'msg'               => '结算到平台',
+                ];
+            }
+            AisQueen::createQueen($queen);
+            if($shopItme->warehouse_num >= 0){
+                $shopItme->warehouse_num = $shopItme->warehouse_num - 1;
+                $shopItme->save();
+            }
+        }
+        $order->real = $allMoney;
+        return $order;
+    }
+}

+ 109 - 0
application/ais/model/AisStore.php

@@ -0,0 +1,109 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 商家管理
+ */
+namespace app\ais\model;
+use app\common\facade\Inform;
+use think\Model;
+use util\Util;
+
+class AisStore extends Model{
+    
+    protected $autoWriteTimestamp = true;
+    protected $updateTime         = false;
+    protected $json               = ['citypath','imgs']; //数组存到数据库变JSON
+
+    //加入的群组
+    public function group(){
+        return $this->belongsToMany('AisStoreGroup','AisStoreUnion','group_id','store_id');
+    }
+
+    //所属管理员
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','manage_uid');
+    }
+
+    public function cate(){
+        return $this->hasOne('AisStoreCate','id','cate_id');
+    }
+
+    //连锁门店
+    public function chain(){
+        return $this->hasMany('AisStoreChain','store_id','id');
+    }
+
+    //Tags字符串转数组
+    public function getTagsAttr($value,$data){
+        if(empty($data['tags'])){
+            return [];
+        }
+        return explode(',',$data['tags']);
+    }
+
+    //搜索好店名称
+    public function searchNameAttr($query,$value){
+        if(!empty($value)){
+            $query->where('name','like', '%'.$value .'%');
+        }
+    }
+
+    //添加或编辑
+    public static function edit($param){
+        $data['manage_uid'] = $param['manage_uid'];
+        $data['cate_id']    = $param['cate_id'];
+        $data['cate_sid']   = $param['cate_sid'];
+        $data['name']       = $param['name'];
+        $data['address']    = $param['address'];
+        $data['longitude']  = $param['longitude'];
+        $data['latitude']   = $param['latitude'];
+        $data['telphone']   = $param['telphone'];
+        $data['citypath']   = $param['citypath'];
+        $data['citycode']   = $param['citycode'];
+        $data['img']        = $param['img'];
+        $data['mch_id']     = $param['mch_id'];
+        $data['charge']     = $param['charge'];
+        $data['tags']       = empty($param['tags']) ? '': sbc2Dbc($param['tags']);
+        $data['imgs']       = json_encode($param['imgs']);
+        if(empty($param['id'])){
+            $data['member_miniapp_id'] = $param['member_miniapp_id'];
+            $data['is_top']            = 0;
+            $data['create_time']       = time();
+            $data['sort']              = 0;
+            return self::insertGetId($data);
+        }else{
+            self::update($data,['id'=>(int)$param['id']]);
+            return $param['id']; 
+        }
+    }
+
+     /**
+     * 置顶或取消
+     * @param integer $id
+     */
+    public static function isTop(int $id){
+        $result = self::where(['id' => $id])->field('is_top')->find();
+        $result->is_top = $result->is_top ? 0 : 1;
+        return $result->save();
+    } 
+
+     /**
+     * 锁定或取消
+     * @param integer $id
+     */
+    public static function isLock(int $id,$member_miniapp_id){
+        $result = self::where(['id' => $id])->field('is_lock')->find();
+        $result->is_lock = $result->is_lock ? 0 : 1;
+        return $result->save();
+    } 
+    
+
+    //根据管理ID获取所属商户
+    public static function manageStore(int $uid){
+        return self::with(['chain'	=> function($query) {
+            $query->field('id,store_id,title,address,telphone,longitude,latitude');
+        }])->where(['manage_uid' => $uid])->field('citycode,id,name,address,img,telphone,longitude,latitude,mch_id')->find();  
+    }
+}

+ 33 - 0
application/ais/model/AisStoreBill.php

@@ -0,0 +1,33 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 好店收入日志 Table<ai_ais_store_bill>
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisStoreBill extends Model{
+    
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','pay_uid');
+    } 
+
+ 
+   /**
+     * [log 增加财务日志]
+     * @param  [array]  $param['miniapp_id = '1',uid=>'1',store_id=>'1','pay_uid' => 0]
+     * @return [boolean]          [增加成功ID]
+     */
+    public static function add(array $param,$message){
+        $data['member_miniapp_id'] = intval($param['member_miniapp_id']);
+        $data['store_id']          = intval($param['store_id']);
+        $data['pay_uid']           = intval($param['pay_uid']);
+        $data['store_chain_id']    = intval($param['store_chain_id']);
+        $data['money']             = floatval($param['money']);
+        $data['message']           = $message;
+        $data['update_time']       = time();
+        return self::insert($data);
+    }
+}

+ 64 - 0
application/ais/model/AisStoreCate.php

@@ -0,0 +1,64 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 行业分类
+ */
+namespace app\ais\model;
+use think\Model;
+use category\Tree;
+
+class AisStoreCate extends Model{
+    
+    //添加或编辑
+    public function edit($param){
+        $data['parent_id'] = $param['parent_id'];
+        $data['title']     = trim($param['title']);
+        $data['name']      = trim($param['name']);
+        $data['sort']      = trim($param['sort']);
+        $data['picture']   = trim($param['picture']);
+        $data['update_time']  = time();
+        if(isset($param['id'])){
+            return self::update($data,['id'=>(int)$param['id']]);
+        }else{
+            if($param['parent_id']){
+                $info =  self::get($param['parent_id']);
+                if($info['root_id']){
+                    $data['root_id'] = $info['root_id'];
+                }else{
+                    $data['root_id'] = $info['id'];
+                }
+            }else{
+                $data['root_id']     = 0;
+            }
+            $data['create_time']       = time();
+            $data['member_miniapp_id'] = $param['member_miniapp_id'];
+            return self::insert($data);
+        }
+    } 
+
+    /**
+     * 获取访问路径
+     * @param int $parent_id
+     */
+    public function selectPath($parent_id) {
+        $pathMaps[] = ['name'=>'行业分类','url'=>url('storeCate/index')];
+        $getPath = self::getPath($parent_id);
+        foreach ($getPath as $value) {
+            $pathMaps[] = ['name' => $value['title'],'url' => url('storeCate/index',['parent_id'=>$value['id']])];
+        }
+        return $pathMaps;
+    }
+
+    /**
+     * 获取当前路径
+     * @param type $parent_id
+     * @return type
+     */
+    public function getPath($parent_id){
+        $result = self::field('id,title,parent_id')->select();
+        $tree =  new Tree(array('id','parent_id','title','name'));
+        return $tree->getPath($result,$parent_id);
+    }
+}

+ 18 - 0
application/ais/model/AisStoreChain.php

@@ -0,0 +1,18 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 连锁门店
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisStoreChain extends Model{
+    
+    //总店
+    public function chain(){
+        return $this->hasOne('AisStore','id','store_id');
+    }
+
+}

+ 24 - 0
application/ais/model/AisStoreGroup.php

@@ -0,0 +1,24 @@
+<?php
+/**
+ * @copyright   Copyright (c) 2017 https://www.sapixx.com All rights reserved.
+ * @license     Licensed (http://www.apache.org/licenses/LICENSE-2.0).
+ * @author      pillar<ltmn@qq.com>
+ * 核销
+ */
+namespace app\ais\model;
+use think\Model;
+
+class AisStoreGroup extends Model{
+
+    protected $autoWriteTimestamp = true;
+    
+    //联盟城市
+    public function group(){
+        return $this->belongsToMany('AisStore','AisStoreUnion','store_id','group_id');
+    }
+
+    //用户
+    public function user(){
+        return $this->hasOne('app\common\model\SystemUser','id','uid');
+    }
+}

部分文件因为文件数量过多而无法显示