Mark 1 gadu atpakaļ
revīzija
e1749442f0
100 mainītis faili ar 8549 papildinājumiem un 0 dzēšanām
  1. 7 0
      .gitignore
  2. 26 0
      404.html
  3. 28 0
      dyu/application/admin/config.php
  4. 195 0
      dyu/application/admin/controller/Controller.php
  5. 30 0
      dyu/application/admin/controller/Index.php
  6. 52 0
      dyu/application/admin/controller/Passport.php
  7. 130 0
      dyu/application/admin/controller/Store.php
  8. 39 0
      dyu/application/admin/controller/admin/User.php
  9. 92 0
      dyu/application/admin/controller/setting/Cache.php
  10. 212 0
      dyu/application/admin/controller/setting/Science.php
  11. 102 0
      dyu/application/admin/controller/store/Access.php
  12. 47 0
      dyu/application/admin/extra/menus.php
  13. 39 0
      dyu/application/admin/model/Setting.php
  14. 111 0
      dyu/application/admin/model/Wxapp.php
  15. 36 0
      dyu/application/admin/model/WxappCategory.php
  16. 37 0
      dyu/application/admin/model/WxappHelp.php
  17. 83 0
      dyu/application/admin/model/WxappPage.php
  18. 89 0
      dyu/application/admin/model/admin/User.php
  19. 664 0
      dyu/application/admin/model/store/Access.php
  20. 54 0
      dyu/application/admin/model/store/User.php
  21. 55 0
      dyu/application/admin/view/admin/user/renew.php
  22. 12 0
      dyu/application/admin/view/index/index.php
  23. 104 0
      dyu/application/admin/view/layouts/layout.php
  24. 63 0
      dyu/application/admin/view/passport/login.php
  25. 78 0
      dyu/application/admin/view/setting/cache/clear.php
  26. 100 0
      dyu/application/admin/view/setting/science/index.php
  27. 67 0
      dyu/application/admin/view/store/access/add.php
  28. 69 0
      dyu/application/admin/view/store/access/edit.php
  29. 83 0
      dyu/application/admin/view/store/access/index.php
  30. 70 0
      dyu/application/admin/view/store/add.php
  31. 80 0
      dyu/application/admin/view/store/index.php
  32. 75 0
      dyu/application/admin/view/store/recycle.php
  33. 122 0
      dyu/application/api/behavior/order/PaySuccess.php
  34. 8 0
      dyu/application/api/config.php
  35. 120 0
      dyu/application/api/controller/Address.php
  36. 61 0
      dyu/application/api/controller/Article.php
  37. 104 0
      dyu/application/api/controller/Cart.php
  38. 37 0
      dyu/application/api/controller/Category.php
  39. 37 0
      dyu/application/api/controller/Comment.php
  40. 147 0
      dyu/application/api/controller/Controller.php
  41. 37 0
      dyu/application/api/controller/Coupon.php
  42. 89 0
      dyu/application/api/controller/Goods.php
  43. 33 0
      dyu/application/api/controller/Notify.php
  44. 149 0
      dyu/application/api/controller/Order.php
  45. 39 0
      dyu/application/api/controller/Page.php
  46. 75 0
      dyu/application/api/controller/Recharge.php
  47. 49 0
      dyu/application/api/controller/Shop.php
  48. 94 0
      dyu/application/api/controller/Upload.php
  49. 51 0
      dyu/application/api/controller/User.php
  50. 47 0
      dyu/application/api/controller/Wxapp.php
  51. 36 0
      dyu/application/api/controller/balance/Log.php
  52. 92 0
      dyu/application/api/controller/bargain/Active.php
  53. 109 0
      dyu/application/api/controller/bargain/Order.php
  54. 99 0
      dyu/application/api/controller/bargain/Task.php
  55. 34 0
      dyu/application/api/controller/live/Room.php
  56. 36 0
      dyu/application/api/controller/points/Log.php
  57. 36 0
      dyu/application/api/controller/recharge/Order.php
  58. 46 0
      dyu/application/api/controller/sharing/Active.php
  59. 76 0
      dyu/application/api/controller/sharing/Comment.php
  60. 91 0
      dyu/application/api/controller/sharing/Goods.php
  61. 34 0
      dyu/application/api/controller/sharing/Index.php
  62. 250 0
      dyu/application/api/controller/sharing/Order.php
  63. 117 0
      dyu/application/api/controller/sharing/Refund.php
  64. 33 0
      dyu/application/api/controller/sharing/Setting.php
  65. 78 0
      dyu/application/api/controller/sharp/Goods.php
  66. 40 0
      dyu/application/api/controller/sharp/Index.php
  67. 122 0
      dyu/application/api/controller/sharp/Order.php
  68. 88 0
      dyu/application/api/controller/shop/Order.php
  69. 61 0
      dyu/application/api/controller/user/Comment.php
  70. 82 0
      dyu/application/api/controller/user/Coupon.php
  71. 123 0
      dyu/application/api/controller/user/Dealer.php
  72. 52 0
      dyu/application/api/controller/user/Index.php
  73. 187 0
      dyu/application/api/controller/user/Order.php
  74. 117 0
      dyu/application/api/controller/user/Refund.php
  75. 52 0
      dyu/application/api/controller/user/Wallet.php
  76. 54 0
      dyu/application/api/controller/user/dealer/Apply.php
  77. 64 0
      dyu/application/api/controller/user/dealer/Order.php
  78. 65 0
      dyu/application/api/controller/user/dealer/Qrcode.php
  79. 68 0
      dyu/application/api/controller/user/dealer/Team.php
  80. 80 0
      dyu/application/api/controller/user/dealer/Withdraw.php
  81. 41 0
      dyu/application/api/controller/wxapp/Formid.php
  82. 96 0
      dyu/application/api/model/Article.php
  83. 300 0
      dyu/application/api/model/Cart.php
  84. 36 0
      dyu/application/api/model/Category.php
  85. 237 0
      dyu/application/api/model/Comment.php
  86. 31 0
      dyu/application/api/model/CommentImage.php
  87. 94 0
      dyu/application/api/model/Coupon.php
  88. 32 0
      dyu/application/api/model/Delivery.php
  89. 32 0
      dyu/application/api/model/DeliveryRule.php
  90. 34 0
      dyu/application/api/model/Express.php
  91. 184 0
      dyu/application/api/model/Goods.php
  92. 31 0
      dyu/application/api/model/GoodsImage.php
  93. 32 0
      dyu/application/api/model/GoodsSku.php
  94. 22 0
      dyu/application/api/model/GoodsSpecRel.php
  95. 390 0
      dyu/application/api/model/Order.php
  96. 31 0
      dyu/application/api/model/OrderAddress.php
  97. 23 0
      dyu/application/api/model/OrderExtract.php
  98. 43 0
      dyu/application/api/model/OrderGoods.php
  99. 179 0
      dyu/application/api/model/OrderRefund.php
  100. 31 0
      dyu/application/api/model/OrderRefundAddress.php

+ 7 - 0
.gitignore

@@ -0,0 +1,7 @@
+web/uploads
+dyu/vendor
+dyu/runtime
+.idea
+.vscode
+.env
+

+ 26 - 0
404.html

@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
+<title>404</title>
+<style>
+	body{
+		background-color:#444;
+		font-size:14px;
+	}
+	h3{
+		font-size:60px;
+		color:#eee;
+		text-align:center;
+		padding-top:30px;
+		font-weight:normal;
+	}
+</style>
+</head>
+
+<body>
+<h3>404,您请求的文件不存在!</h3>
+</body>
+</html>

+ 28 - 0
dyu/application/admin/config.php

@@ -0,0 +1,28 @@
+<?php
+
+return [
+    // 默认输出类型
+    'default_return_type'    => 'html',
+
+    'template'               => [
+        // layout布局
+        'layout_on'     =>  true,
+        'layout_name'   =>  'layouts/layout',
+        // 模板引擎类型 支持 php think 支持扩展
+        'type'         => 'think',
+        // 模板路径
+        'view_path'    => '',
+        // 模板后缀
+        'view_suffix'  => 'php',
+        // 模板文件名分隔符
+        'view_depr'    => DS,
+        // 模板引擎普通标签开始标记
+        'tpl_begin'    => '{{',
+        // 模板引擎普通标签结束标记
+        'tpl_end'      => '}}',
+        // 标签库标签开始标记
+        'taglib_begin' => '{{',
+        // 标签库标签结束标记
+        'taglib_end'   => '}}',
+    ],
+];

+ 195 - 0
dyu/application/admin/controller/Controller.php

@@ -0,0 +1,195 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\controller;
+
+use think\Config;
+use think\Request;
+use think\Session;
+
+// use app\store\model\Setting;
+
+/**
+ * 超管后台控制器基类
+ * Class Controller
+ * @package app\admin\controller
+ */
+class Controller extends \think\Controller
+{
+    /* @var array $admin 商家登录信息 */
+    protected $admin;
+
+    /* @var string $route 当前控制器名称 */
+    protected $controller = '';
+
+    /* @var string $route 当前方法名称 */
+    protected $action = '';
+
+    /* @var string $route 当前路由uri */
+    protected $routeUri = '';
+
+    /* @var string $route 当前路由:分组名称 */
+    protected $group = '';
+
+    /* @var array $allowAllAction 登录验证白名单 */
+    protected $allowAllAction = [
+        // 登录页面
+        'passport/login',
+    ];
+
+    /* @var array $notLayoutAction 无需全局layout */
+    protected $notLayoutAction = [
+        // 登录页面
+        'passport/login',
+    ];
+
+    /**
+     * 后台初始化
+     * @throws \Exception
+     */
+    public function _initialize()
+    {
+        // 商家登录信息
+        $this->admin = Session::get('dyu_admin');
+        // 当前路由信息
+        $this->getRouteinfo();
+        // 验证登录
+        $this->checkLogin();
+        // 全局layout
+        $this->layout();
+    }
+
+    /**
+     * 全局layout模板输出
+     * @throws \Exception
+     */
+    private function layout()
+    {
+        // 验证当前请求是否在白名单
+        if (!in_array($this->routeUri, $this->notLayoutAction)) {
+            // 输出到view
+            $this->assign([
+                'base_url' => base_url(),                      // 当前域名
+                'admin_url' => url('/admin'),              // 后台模块url
+                'group' => $this->group,
+                'menus' => $this->menus(),                     // 后台菜单
+                'admin' => $this->admin,                       // 商家登录信息
+                'version' => get_version(),                    // 当前系统版本号
+                'request' => Request::instance()               // Request对象
+            ]);
+        }
+    }
+
+    /**
+     * 解析当前路由参数 (分组名称、控制器名称、方法名)
+     */
+    protected function getRouteinfo()
+    {
+        // 控制器名称
+        $this->controller = toUnderScore($this->request->controller());
+        // 方法名称
+        $this->action = $this->request->action();
+        // 控制器分组 (用于定义所属模块)
+        $groupstr = strstr($this->controller, '.', true);
+        $this->group = $groupstr !== false ? $groupstr : $this->controller;
+        // 当前uri
+        $this->routeUri = $this->controller . '/' . $this->action;
+    }
+
+    /**
+     * 后台菜单配置
+     * @return array
+     */
+    private function menus()
+    {
+        foreach ($data = Config::get('menus') as $group => $first) {
+            $data[$group]['active'] = $group === $this->group;
+            // 遍历:二级菜单
+            if (isset($first['submenu'])) {
+                foreach ($first['submenu'] as $secondKey => $second) {
+                    // 二级菜单所有uri
+                    $secondUris = isset($second['uris']) ? $second['uris'] : [$second['index']];
+                    // 二级菜单:active
+                    !isset($data[$group]['submenu'][$secondKey]['active'])
+                    && $data[$group]['submenu'][$secondKey]['active'] = in_array($this->routeUri, $secondUris);
+                }
+            }
+        }
+        return $data;
+    }
+
+    /**
+     * 验证登录状态
+     * @return bool
+     */
+    private function checkLogin()
+    {
+        // 验证当前请求是否在白名单
+        if (in_array($this->routeUri, $this->allowAllAction)) {
+            return true;
+        }
+        // 验证登录状态
+        if (empty($this->admin)
+            || (int)$this->admin['is_login'] !== 1
+        ) {
+            $this->redirect('passport/login');
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 返回封装后的 API 数据到客户端
+     * @param int $code
+     * @param string $msg
+     * @param string $url
+     * @param array $data
+     * @return array
+     */
+    protected function renderJson($code = 1, $msg = '', $url = '', $data = [])
+    {
+        return compact('code', 'msg', 'url', 'data');
+    }
+
+    /**
+     * 返回操作成功json
+     * @param string $msg
+     * @param string $url
+     * @param array $data
+     * @return array
+     */
+    protected function renderSuccess($msg = 'success', $url = '', $data = [])
+    {
+        return $this->renderJson(1, $msg, $url, $data);
+    }
+
+    /**
+     * 返回操作失败json
+     * @param string $msg
+     * @param string $url
+     * @param array $data
+     * @return array
+     */
+    protected function renderError($msg = 'error', $url = '', $data = [])
+    {
+        return $this->renderJson(0, $msg, $url, $data);
+    }
+
+    /**
+     * 获取post数据 (数组)
+     * @param $key
+     * @return mixed
+     */
+    protected function postData($key)
+    {
+        return $this->request->post($key . '/a');
+    }
+
+}

+ 30 - 0
dyu/application/admin/controller/Index.php

@@ -0,0 +1,30 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\controller;
+
+
+/**
+ * 后台首页
+ * Class Index
+ * @package app\admin\controller
+ */
+class Index extends Controller
+{
+    /**
+     * 后台首页
+     * @return mixed
+     */
+    public function index()
+    {
+        return $this->fetch('index');
+    }
+
+}

+ 52 - 0
dyu/application/admin/controller/Passport.php

@@ -0,0 +1,52 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\controller;
+
+use app\admin\model\admin\User as UserModel;
+use think\Session;
+
+/**
+ * 超管后台认证
+ * Class Passport
+ * @package app\store\controller
+ */
+class Passport extends Controller
+{
+    /**
+     * 超管后台登录
+     * @return array|mixed
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function login()
+    {
+        if ($this->request->isAjax()) {
+            $model = new UserModel;
+            if ($model->login($this->postData('User'))) {
+                return $this->renderSuccess('登录成功', url('index/index'));
+            }
+            return $this->renderError($model->getError() ?: '登录失败');
+        }
+        $this->view->engine->layout(false);
+        return $this->fetch('login');
+    }
+
+    /**
+     * 退出登录
+     */
+    public function logout()
+    {
+        Session::clear('dyu_admin');
+        $this->redirect('passport/login');
+    }
+
+}

+ 130 - 0
dyu/application/admin/controller/Store.php

@@ -0,0 +1,130 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\controller;
+
+use app\admin\model\Wxapp as WxappModel;
+use app\admin\model\store\User as StoreUser;
+
+/**
+ * 小程序商城管理
+ * Class Store
+ * @package app\admin\controller
+ */
+class Store extends Controller
+{
+    /**
+     * 小程序列表
+     * @return mixed
+     * @throws \think\exception\DbException
+     */
+    public function index()
+    {
+        $model = new WxappModel;
+        return $this->fetch('index', [
+            'list' => $list = $model->getList(),
+            'names' => $model->getStoreName($list)
+        ]);
+    }
+
+    /**
+     * 进入商城
+     * @param $wxapp_id
+     * @throws \think\Exception
+     * @throws \think\exception\DbException
+     */
+    public function enter($wxapp_id)
+    {
+        $model = new StoreUser;
+        $model->login($wxapp_id);
+        $this->redirect('store/index/index');
+    }
+
+    /**
+     * 回收站列表
+     * @return mixed
+     * @throws \think\exception\DbException
+     */
+    public function recycle()
+    {
+        $model = new WxappModel;
+        return $this->fetch('recycle', [
+            'list' => $list = $model->getList(true),
+            'names' => $model->getStoreName($list)
+        ]);
+    }
+
+    /**
+     * 添加小程序
+     * @return array|mixed
+     * @throws \think\exception\PDOException
+     */
+    public function add()
+    {
+        $model = new WxappModel;
+        if (!$this->request->isAjax()) {
+            return $this->fetch('add');
+        }
+        // 新增记录
+        if ($model->add($this->postData('store'))) {
+            return $this->renderSuccess('添加成功', url('store/index'));
+        }
+        return $this->renderError($model->getError() ?: '添加失败');
+    }
+
+    /**
+     * 回收小程序
+     * @param $wxapp_id
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function recovery($wxapp_id)
+    {
+        // 小程序详情
+        $model = WxappModel::detail($wxapp_id);
+        if (!$model->recycle()) {
+            return $this->renderError('操作失败');
+        }
+        return $this->renderSuccess('操作成功');
+    }
+
+    /**
+     * 移出回收站
+     * @param $wxapp_id
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function move($wxapp_id)
+    {
+        // 小程序详情
+        $model = WxappModel::detail($wxapp_id);
+        if (!$model->recycle(false)) {
+            return $this->renderError('操作失败');
+        }
+        return $this->renderSuccess('操作成功');
+    }
+
+    /**
+     * 删除小程序
+     * @param $wxapp_id
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function delete($wxapp_id)
+    {
+        // 小程序详情
+        $model = WxappModel::detail($wxapp_id);
+        if (!$model->setDelete()) {
+            return $this->renderError('操作失败');
+        }
+        return $this->renderSuccess('操作成功');
+    }
+
+}

+ 39 - 0
dyu/application/admin/controller/admin/User.php

@@ -0,0 +1,39 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\controller\admin;
+
+use app\admin\controller\Controller;
+use app\admin\model\admin\User as AdminUserModel;
+
+/**
+ * 超管后台管理员控制器
+ * Class User
+ * @package app\store\controller
+ */
+class User extends Controller
+{
+    /**
+     * 更新当前管理员信息
+     * @return array|mixed
+     * @throws \think\exception\DbException
+     */
+    public function renew()
+    {
+        $model = AdminUserModel::detail($this->admin['user']['admin_user_id']);
+        if ($this->request->isAjax()) {
+            if ($model->renew($this->postData('user'))) {
+                return $this->renderSuccess('更新成功');
+            }
+            return $this->renderError($model->getError() ?: '更新失败');
+        }
+        return $this->fetch('renew', compact('model'));
+    }
+}

+ 92 - 0
dyu/application/admin/controller/setting/Cache.php

@@ -0,0 +1,92 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\controller\setting;
+
+use app\admin\controller\Controller;
+use think\Cache as CacheDriver;
+
+/**
+ * 清理缓存
+ * Class Index
+ * @package app\admin\controller
+ */
+class Cache extends Controller
+{
+    /**
+     * 清理缓存
+     * @param bool $isForce
+     * @return mixed
+     */
+    public function clear($isForce = false)
+    {
+        if ($this->request->isAjax()) {
+            $this->rmCache($this->postData('cache'));
+            return $this->renderSuccess('操作成功');
+        }
+        return $this->fetch('clear', [
+            'isForce' => !!$isForce ?: config('app_debug'),
+        ]);
+    }
+
+    /**
+     * 删除缓存
+     * @param $data
+     */
+    private function rmCache($data)
+    {
+        // 数据缓存
+        if (in_array('data', $data['item'])) {
+            // 强制模式
+            $isForce = isset($data['isForce']) ? !!$data['isForce'] : false;
+            // 清除缓存
+            CacheDriver::clear($isForce ? null : 'cache');
+        }
+        // 临时文件
+        if (in_array('temp', $data['item'])) {
+            $paths = [
+                'temp' => WEB_PATH . 'temp/',
+                'runtime' => RUNTIME_PATH . 'image/'
+            ];
+            foreach ($paths as $path) {
+                $this->deleteFolder($path);
+            }
+        }
+    }
+
+    /**
+     * 递归删除指定目录下所有文件
+     * @param $path
+     * @return bool
+     */
+    private function deleteFolder($path)
+    {
+        if (!is_dir($path))
+            return false;
+        // 扫描一个文件夹内的所有文件夹和文件
+        foreach (scandir($path) as $val) {
+            // 排除目录中的.和..
+            if (!in_array($val, ['.', '..', '.gitignore'])) {
+                // 如果是目录则递归子目录,继续操作
+                if (is_dir($path . $val)) {
+                    // 子目录中操作删除文件夹和文件
+                    $this->deleteFolder($path . $val . '/');
+                    // 目录清空后删除空文件夹
+                    rmdir($path . $val . '/');
+                } else {
+                    // 如果是文件直接删除
+                    unlink($path . $val);
+                }
+            }
+        }
+        return true;
+    }
+
+}

+ 212 - 0
dyu/application/admin/controller/setting/Science.php

@@ -0,0 +1,212 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\controller\setting;
+
+use app\admin\controller\Controller;
+
+/**
+ * 环境检测
+ * Class Science
+ * @package app\admin\controller\setting
+ */
+class Science extends Controller
+{
+    /**
+     * 状态class
+     * @var array
+     */
+    private $statusClass = [
+        'normal' => '',
+        'warning' => 'am-active',
+        'danger' => 'am-danger'
+    ];
+
+    /**
+     * 环境检测
+     */
+    public function index()
+    {
+        return $this->fetch('index', [
+            'statusClass' => $this->statusClass,
+            'phpinfo' => $this->phpinfo(),  // PHP环境要求
+            'server' => $this->server(), // 服务器信息
+            'writeable' => $this->writeable(), // 目录权限监测
+        ]);
+    }
+
+    /**
+     * 服务器信息
+     * @return array
+     */
+    private function server()
+    {
+        return [
+            'system' => [
+                'name' => '服务器操作系统',
+                'value' => PHP_OS,
+                'status' => PHP_SHLIB_SUFFIX === 'dll' ? 'warning' : 'normal',
+                'remark' => '建议使用 Linux 系统以提升程序性能'
+            ],
+            'webserver' => [
+                'name' => 'Web服务器环境',
+                'value' => $this->request->server('SERVER_SOFTWARE'),
+                'status' => PHP_SAPI === 'isapi' ? 'warning' : 'normal',
+                'remark' => '建议使用 Apache 或 Nginx 以提升程序性能'
+            ],
+            'php' => [
+                'name' => 'PHP版本',
+                'value' => PHP_VERSION,
+                'status' => version_compare(PHP_VERSION, '5.4.0') === -1 ? 'danger' : 'normal',
+                'remark' => 'PHP版本必须为 5.4.0 以上'
+            ],
+            'upload_max' => [
+                'name' => '文件上传限制',
+                'value' => @ini_get('file_uploads') ? ini_get('upload_max_filesize') : 'unknow',
+                'status' => 'normal',
+                'remark' => ''
+            ],
+            'web_path' => [
+                'name' => '程序运行目录',
+                'value' => str_replace('\\', '/', WEB_PATH),
+                'status' => 'normal',
+                'remark' => ''
+            ],
+        ];
+    }
+
+    /**
+     * PHP环境要求
+     * @return array
+     */
+    private function phpinfo()
+    {
+//        pre(  get_loaded_extensions() );
+        return [
+            'php_version' => [
+                'name' => 'PHP版本',
+                'value' => '5.4.0及以上',
+                'status' => version_compare(PHP_VERSION, '5.4.0') === -1 ? 'danger' : 'normal',
+                'remark' => 'PHP版本必须为 5.4.0及以上'
+            ],
+            'curl' => [
+                'name' => 'CURL',
+                'value' => '支持',
+                'status' => extension_loaded('curl') && function_exists('curl_init') ? 'normal' : 'danger',
+                'remark' => '您的PHP环境不支持CURL, 系统无法正常运行'
+            ],
+            'openssl' => [
+                'name' => 'OpenSSL',
+                'value' => '支持',
+                'status' => extension_loaded('openssl') ? 'normal' : 'danger',
+                'remark' => '没有启用OpenSSL, 将无法访问微信平台的接口'
+            ],
+            'pdo' => [
+                'name' => 'PDO',
+                'value' => '支持',
+                'status' => extension_loaded('PDO') && extension_loaded('pdo_mysql') ? 'normal' : 'danger',
+                'remark' => '您的PHP环境不支持PDO, 系统无法正常运行'
+            ],
+            'gd' => [
+                'name' => 'GD',
+                'value' => '支持',
+                'status' => extension_loaded('gd') ? 'normal' : 'danger',
+                'remark' => '您的PHP环境不支持GD, 系统无法正常生成图片'
+            ],
+            'bcmath' => [
+                'name' => 'BCMath',
+                'value' => '支持',
+                'status' => extension_loaded('bcmath') ? 'normal' : 'danger',
+                'remark' => '您的PHP环境不支持BCMath, 系统无法正常运行'
+            ],
+            'mbstring' => [
+                'name' => 'mbstring',
+                'value' => '支持',
+                'status' => extension_loaded('mbstring') ? 'normal' : 'danger',
+                'remark' => '您的PHP环境不支持mbstring, 系统无法正常运行'
+            ],
+            'SimpleXML' => [
+                'name' => 'SimpleXML',
+                'value' => '支持',
+                'status' => extension_loaded('SimpleXML') ? 'normal' : 'danger',
+                'remark' => '您的PHP环境不支持SimpleXML, 系统无法解析xml 无法使用微信支付'
+            ],
+        ];
+
+    }
+
+    /**
+     * 目录权限监测
+     */
+    private function writeable()
+    {
+        $paths = [
+            'uploads' => realpath(WEB_PATH) . '/uploads/',
+            'temp' => realpath(WEB_PATH) . '/temp/',
+            'wxpay_log' => realpath(APP_PATH) . '/common/library/wechat/logs/',
+            'wxpay_cert' => realpath(APP_PATH) . '/common/library/wechat/cert/',
+            'behavior_log' => realpath(APP_PATH) . '/task/behavior/logs/',
+        ];
+        return [
+            'uploads' => [
+                'name' => '文件上传目录',
+                'value' => str_replace('\\', '/', $paths['uploads']),
+                'status' => $this->checkWriteable($paths['uploads']) ? 'normal' : 'danger',
+                'remark' => '目录不可写,系统将无法正常上传文件'
+            ],
+            'temp' => [
+                'name' => '临时文件目录',
+                'value' => str_replace('\\', '/', $paths['temp']),
+                'status' => $this->checkWriteable($paths['temp']) ? 'normal' : 'danger',
+                'remark' => '目录不可写,系统将无法正常写入文件'
+            ],
+            'wxpay_log' => [
+                'name' => '微信支付日志目录',
+                'value' => str_replace('\\', '/', $paths['wxpay_log']),
+                'status' => $this->checkWriteable($paths['wxpay_log']) ? 'normal' : 'danger',
+                'remark' => '目录不可写,系统将无法正常写入文件'
+            ],
+            'wxpay_cert' => [
+                'name' => '微信支付证书目录',
+                'value' => str_replace('\\', '/', $paths['wxpay_cert']),
+                'status' => $this->checkWriteable($paths['wxpay_cert']) ? 'normal' : 'danger',
+                'remark' => '目录不可写,系统将无法正常写入文件'
+            ],
+//            'behavior_log' => [
+//                'name' => '自动任务日志目录',
+//                'value' => str_replace('\\', '/', $paths['behavior_log']),
+//                'status' => $this->checkWriteable($paths['behavior_log']) ? 'normal' : 'danger',
+//                'remark' => '目录不可写,系统将无法正常上传文件'
+//            ],
+        ];
+
+    }
+
+    /**
+     * 检查目录是否可写
+     * @param $path
+     * @return bool
+     */
+    private function checkWriteable($path)
+    {
+        try {
+            !is_dir($path) && mkdir($path, 0755);
+            if (!is_dir($path))
+                return false;
+            $fileName = $path . '/_test_write.txt';
+            if ($fp = fopen($fileName, 'w')) {
+                return fclose($fp) && unlink($fileName);
+            }
+        } catch (\Exception $e) {
+        }
+        return false;
+    }
+
+}

+ 102 - 0
dyu/application/admin/controller/store/Access.php

@@ -0,0 +1,102 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\controller\store;
+
+use app\admin\controller\Controller;
+use app\admin\model\store\Access as AccesscModel;
+
+/**
+ * 商家用户权限控制器
+ * Class StoreUser
+ * @package app\store\controller
+ */
+class Access extends Controller
+{
+    /**
+     * 权限列表
+     * @return mixed
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function index()
+    {
+        $model = new AccesscModel;
+        $list = $model->getList();
+        return $this->fetch('index', compact('list'));
+    }
+
+    /**
+     * 添加权限
+     * @return array|mixed
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function add()
+    {
+        $model = new AccesscModel;
+        if (!$this->request->isAjax()) {
+            // 权限列表
+            $accessList = $model->getList();
+            return $this->fetch('add', compact('accessList'));
+        }
+        // 新增记录
+        if ($model->add($this->postData('access'))) {
+            return $this->renderSuccess('添加成功', url('store.access/index'));
+        }
+        return $this->renderError($model->getError() ?: '添加失败');
+    }
+
+    /**
+     * 更新权限
+     * @param $access_id
+     * @return array|mixed
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function edit($access_id)
+    {
+        // 权限详情
+        $model = AccesscModel::detail($access_id);
+        if (!$this->request->isAjax()) {
+            // 权限列表
+            $accessList = $model->getList();
+            return $this->fetch('edit', compact('model', 'accessList'));
+        }
+        // 更新记录
+        if ($model->edit($this->postData('access'))) {
+            return $this->renderSuccess('更新成功', url('store.access/index'));
+        }
+        return $this->renderError($model->getError() ?: '更新失败');
+    }
+
+    /**
+     * 删除权限
+     * @param $access_id
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function delete($access_id)
+    {
+        // 权限详情
+        $model = AccesscModel::detail($access_id);
+        if (!$model->remove()) {
+            return $this->renderError($model->getError() ?: '删除失败');
+        }
+        return $this->renderSuccess('删除成功');
+    }
+
+}

+ 47 - 0
dyu/application/admin/extra/menus.php

@@ -0,0 +1,47 @@
+<?php
+/**
+ * 后台菜单配置
+ *    'home' => [
+ *       'name' => '首页',                // 菜单名称
+ *       'icon' => 'icon-home',          // 图标 (class)
+ *       'index' => 'index/index',         // 链接
+ *     ],
+ */
+return [
+    'store' => [
+        'name' => '小程序商城',
+        'icon' => 'icon-shangcheng',
+        'submenu' => [
+            [
+                'name' => '商城列表',
+                'index' => 'store/index',
+                'uris' => [
+                    'store/index',
+                    'store/add',
+                ]
+            ],
+            [
+                'name' => '回收站',
+                'index' => 'store/recycle'
+            ],
+            [
+                'name' => '权限管理',
+                'index' => 'store.access/index'
+            ]
+        ],
+    ],
+    'setting' => [
+        'name' => '系统设置',
+        'icon' => 'icon-shezhi',
+        'submenu' => [
+            [
+                'name' => '清理缓存',
+                'index' => 'setting.cache/clear'
+            ],
+            [
+                'name' => '环境检测',
+                'index' => 'setting.science/index'
+            ],
+        ],
+    ],
+];

+ 39 - 0
dyu/application/admin/model/Setting.php

@@ -0,0 +1,39 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\model;
+
+use app\common\model\Setting as SettingModel;
+
+/**
+ * 商城设置模型
+ * Class Setting
+ * @package app\admin\model
+ */
+class Setting extends SettingModel
+{
+    /**
+     * 新增默认配置
+     * @param $wxapp_id
+     * @param $store_name
+     * @return array|false
+     * @throws \Exception
+     */
+    public function insertDefault($wxapp_id, $store_name)
+    {
+        // 添加商城默认设置记录
+        $data = [];
+        foreach ($this->defaultData($store_name) as $key => $item) {
+            $data[] = array_merge($item, ['wxapp_id' => $wxapp_id]);
+        }
+        return $this->saveAll($data);
+    }
+
+}

+ 111 - 0
dyu/application/admin/model/Wxapp.php

@@ -0,0 +1,111 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\model;
+
+use app\common\model\Wxapp as WxappModel;
+use app\admin\model\store\User as StoreUser;
+
+/**
+ * 微信小程序模型
+ * Class Wxapp
+ * @package app\admin\model
+ */
+class Wxapp extends WxappModel
+{
+    /**
+     * 获取小程序列表
+     * @param boolean $is_recycle
+     * @return \think\Paginator
+     * @throws \think\exception\DbException
+     */
+    public function getList($is_recycle = false)
+    {
+        return $this->where('is_recycle', '=', (int)$is_recycle)
+            ->where('is_delete', '=', 0)
+            ->order(['create_time' => 'desc'])
+            ->paginate(15, false, [
+                'query' => request()->request()
+            ]);
+    }
+
+    /**
+     * 从缓存中获取商城名称
+     * @param $data
+     * @return array
+     */
+    public function getStoreName($data)
+    {
+        $names = [];
+        foreach ($data as $wxapp) {
+            $names[$wxapp['wxapp_id']] = Setting::getItem('store', $wxapp['wxapp_id'])['name'];
+        }
+        return $names;
+    }
+
+    /**
+     * 新增记录
+     * @param $data
+     * @return bool
+     * @throws \think\exception\PDOException
+     */
+    public function add($data)
+    {
+        if ($data['password'] !== $data['password_confirm']) {
+            $this->error = '确认密码不正确';
+            return false;
+        }
+        $this->startTrans();
+        try {
+            // 添加小程序记录
+            $this->allowField(true)->save($data);
+            // 商城默认设置
+            (new Setting)->insertDefault($this['wxapp_id'], $data['store_name']);
+            // 新增商家用户信息
+            $StoreUser = new StoreUser;
+            if (!$StoreUser->add($this['wxapp_id'], $data)) {
+                $this->error = $StoreUser->error;
+                return false;
+            }
+            // 新增小程序默认帮助
+            (new WxappHelp)->insertDefault($this['wxapp_id']);
+            // 新增小程序diy配置
+            (new WxappPage)->insertDefault($this['wxapp_id']);
+            // 新增小程序分类页模板
+            (new WxappCategory)->insertDefault($this['wxapp_id']);
+            $this->commit();
+            return true;
+        } catch (\Exception $e) {
+            $this->error = $e->getMessage();
+            $this->rollback();
+            return false;
+        }
+    }
+
+    /**
+     * 移入移出回收站
+     * @param bool $is_recycle
+     * @return false|int
+     */
+    public function recycle($is_recycle = true)
+    {
+        return $this->save(['is_recycle' => (int)$is_recycle]);
+    }
+
+    /**
+     * 软删除
+     * @return false|int
+     */
+    public function setDelete()
+    {
+        return $this->save(['is_delete' => 1]);
+    }
+
+}

+ 36 - 0
dyu/application/admin/model/WxappCategory.php

@@ -0,0 +1,36 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\model;
+
+use app\common\model\WxappCategory as WxappCategoryModel;
+
+/**
+ * 微信小程序分类页模板
+ * Class WxappCategory
+ * @package app\store\model
+ */
+class WxappCategory extends WxappCategoryModel
+{
+    /**
+     * 新增分类页模板
+     * @param $wxapp_id
+     * @return false|int
+     */
+    public function insertDefault($wxapp_id)
+    {
+        return $this->save([
+            'wxapp_id' => $wxapp_id,
+            'category_style' => '11',
+            'share_title' => '',
+        ]);
+    }
+
+}

+ 37 - 0
dyu/application/admin/model/WxappHelp.php

@@ -0,0 +1,37 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\model;
+
+use app\common\model\WxappHelp as WxappHelpModel;
+
+/**
+ * 小程序帮助中心
+ * Class WxappHelp
+ * @package app\admin\model
+ */
+class WxappHelp extends WxappHelpModel
+{
+    /**
+     * 新增默认帮助
+     * @param $wxapp_id
+     * @return false|int
+     */
+    public function insertDefault($wxapp_id)
+    {
+        return $this->save([
+            'title' => '关于小程序',
+            'content' => '小程序本身无需下载,无需注册,不占用手机内存,可以跨平台使用,响应迅速,体验接近原生APP。',
+            'sort' => 100,
+            'wxapp_id' => $wxapp_id
+        ]);
+    }
+
+}

+ 83 - 0
dyu/application/admin/model/WxappPage.php

@@ -0,0 +1,83 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\model;
+
+use app\common\model\WxappPage as WxappPageModel;
+
+/**
+ * 微信小程序diy页面模型
+ * Class WxappPage
+ * @package app\admin\model
+ */
+class WxappPage extends WxappPageModel
+{
+    /**
+     * 新增小程序首页diy默认设置
+     * @param $wxapp_id
+     * @return false|int
+     */
+    public function insertDefault($wxapp_id)
+    {
+        return $this->save([
+            'page_type' => 10,
+            'page_name' => '小程序首页',
+            'page_data' => [
+                'page' => [
+                    'type' => 'page',
+                    'name' => '页面设置',
+                    'params' => [
+                        'name' => '页面标题',
+                        'title' => '页面标题',
+                        'share_title' => '分享标题'
+                    ],
+                    'style' => [
+                        'titleTextColor' => 'black',
+                        'titleBackgroundColor' => '#ffffff',
+                    ]
+                ],
+                'items' => [
+                    [
+                        'type' => 'search',
+                        'name' => '搜索框',
+                        'params' => ['placeholder' => '搜索商品'],
+                        'style' => [
+                            'textAlign' => 'center',
+                            'searchStyle' => 'radius',
+                        ],
+                    ],
+                    [
+                        'type' => 'banner',
+                        'name' => '图片轮播',
+                        'style' => [
+                            'btnColor' => '#ffffff',
+                            'btnShape' => 'round',
+                        ],
+                        'params' => [
+                            'interval' => '2800'
+                        ],
+                        'data' => [
+                            [
+                                'imgUrl' => self::$base_url . 'static/store/img/diy/banner/01.png',
+                                'linkUrl' => '',
+                            ],
+                            [
+                                'imgUrl' => self::$base_url . 'static/store/img/diy/banner/01.png',
+                                'linkUrl' => '',
+                            ],
+                        ],
+                    ]
+                ],
+            ],
+            'wxapp_id' => $wxapp_id
+        ]);
+    }
+
+}

+ 89 - 0
dyu/application/admin/model/admin/User.php

@@ -0,0 +1,89 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\model\admin;
+
+use think\Session;
+use app\common\model\admin\User as UserModel;
+
+/**
+ * 超管后台用户模型
+ * Class User
+ * @package app\admin\model\admin
+ */
+class User extends UserModel
+{
+    /**
+     * 超管后台用户登录
+     * @param $data
+     * @return bool
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function login($data)
+    {
+        // 验证用户名密码是否正确
+        if (!$user = self::useGlobalScope(false)->where([
+            'user_name' => $data['user_name'],
+            'password' => dyu_hash($data['password'])
+        ])->find()) {
+            $this->error = '登录失败, 用户名或密码错误';
+            return false;
+        }
+        // 保存登录状态
+        Session::set('dyu_admin', [
+            'user' => [
+                'admin_user_id' => $user['admin_user_id'],
+                'user_name' => $user['user_name'],
+            ],
+            'is_login' => true,
+        ]);
+        return true;
+    }
+
+    /**
+     * 超管用户信息
+     * @param $admin_user_id
+     * @return null|static
+     * @throws \think\exception\DbException
+     */
+    public static function detail($admin_user_id)
+    {
+        return self::get($admin_user_id);
+    }
+
+    /**
+     * 更新当前管理员信息
+     * @param $data
+     * @return bool
+     */
+    public function renew($data)
+    {
+        if ($data['password'] !== $data['password_confirm']) {
+            $this->error = '确认密码不正确';
+            return false;
+        }
+        // 更新管理员信息
+        if ($this->save([
+                'user_name' => $data['user_name'],
+                'password' => dyu_hash($data['password']),
+            ]) === false) {
+            return false;
+        }
+        // 更新session
+        Session::set('dyu_admin.user', [
+            'admin_user_id' => $this['admin_user_id'],
+            'user_name' => $data['user_name'],
+        ]);
+        return true;
+    }
+
+}

+ 664 - 0
dyu/application/admin/model/store/Access.php

@@ -0,0 +1,664 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\model\store;
+
+use app\common\model\store\Access as AccessModel;
+
+/**
+ * 商家用户权限模型
+ * Class Access
+ * @package app\admin\model\store
+ */
+class Access extends AccessModel
+{
+    /**
+     * 获取权限列表
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function getList()
+    {
+        $all = static::getAll();
+        return $this->formatTreeData($all);
+    }
+
+    /**
+     * 新增记录
+     * @param $data
+     * @return false|int
+     */
+    public function add($data)
+    {
+        $data['wxapp_id'] = self::$wxapp_id;
+        return $this->allowField(true)->save($data);
+    }
+
+    /**
+     * 更新记录
+     * @param $data
+     * @return bool
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function edit($data)
+    {
+        // 判断上级角色是否为当前子级
+        if ($data['parent_id'] > 0) {
+            // 获取所有上级id集
+            $parentIds = $this->getTopAccessIds($data['parent_id']);
+            if (in_array($this['access_id'], $parentIds)) {
+                $this->error = '上级权限不允许设置为当前子权限';
+                return false;
+            }
+        }
+        return $this->allowField(true)->save($data) !== false;
+    }
+
+    /**
+     * 删除权限
+     * @return bool|int
+     * @throws \think\exception\DbException
+     */
+    public function remove()
+    {
+        // 判断是否存在下级权限
+        if (self::detail(['parent_id' => $this['access_id']])) {
+            $this->error = '当前权限下存在子权限,请先删除';
+            return false;
+        }
+        return $this->delete();
+    }
+
+    /**
+     * 获取所有上级id集
+     * @param $access_id
+     * @param null $all
+     * @return array
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    private function getTopAccessIds($access_id, &$all = null)
+    {
+        static $ids = [];
+        is_null($all) && $all = $this->getAll();
+        foreach ($all as $item) {
+            if ($item['access_id'] == $access_id && $item['parent_id'] > 0) {
+                $ids[] = $item['parent_id'];
+                $this->getTopAccessIds($item['parent_id'], $all);
+            }
+        }
+        return $ids;
+    }
+
+    /**
+     * 获取权限列表
+     * @param $all
+     * @param int $parent_id
+     * @param int $deep
+     * @return array
+     */
+    private function formatTreeData(&$all, $parent_id = 0, $deep = 1)
+    {
+        static $tempTreeArr = [];
+        foreach ($all as $key => $val) {
+            if ($val['parent_id'] == $parent_id) {
+                // 记录深度
+                $val['deep'] = $deep;
+                // 根据角色深度处理名称前缀
+                $val['name_h1'] = $this->htmlPrefix($deep) . $val['name'];
+                $tempTreeArr[] = $val;
+                $this->formatTreeData($all, $val['access_id'], $deep + 1);
+            }
+        }
+        return $tempTreeArr;
+    }
+
+    private function htmlPrefix($deep)
+    {
+        // 根据角色深度处理名称前缀
+        $prefix = '';
+        if ($deep > 1) {
+            for ($i = 1; $i <= $deep - 1; $i++) {
+                $prefix .= '&nbsp;&nbsp;&nbsp;├ ';
+            }
+            $prefix .= '&nbsp;';
+        }
+        return $prefix;
+    }
+
+    /**
+     * 新增默认权限
+     */
+    public function insertDefault()
+    {
+        $defaultData = $this->defaultData();
+        $this->buildData($defaultData);
+    }
+
+    /**
+     * 生成并写入默认数据
+     * @param $defaultData
+     * @param int $parent_id
+     */
+    private function buildData(&$defaultData, $parent_id = 0)
+    {
+        foreach ($defaultData as $key => $item) {
+            // 保存数据
+            $model = new static;
+            $model->save([
+                'name' => $item['name'],
+                'url' => $item['url'],
+                'parent_id' => $parent_id,
+                'sort' => 100,
+            ]);
+            if (isset($item['subset']) && !empty($item['subset'])) {
+                $this->buildData($item['subset'], $model['access_id']);
+            }
+        }
+    }
+
+    /**
+     * 默认权限数据
+     * @return array
+     */
+    private function defaultData()
+    {
+        return [
+            [
+                'name' => '首页',
+                'url' => 'index/index'
+            ],
+            [
+                'name' => '管理员',
+                'url' => 'store',
+                'subset' => [
+                    [
+                        'name' => '管理员管理',
+                        'url' => 'store.user',
+                        'subset' => [
+                            [
+                                'name' => '管理员列表',
+                                'url' => 'store.user/index'
+                            ],
+                            [
+                                'name' => '添加管理员',
+                                'url' => 'store.user/add'
+                            ],
+                            [
+                                'name' => '编辑管理员',
+                                'url' => 'store.user/edit'
+                            ],
+                            [
+                                'name' => '删除管理员',
+                                'url' => 'store.user/delete'
+                            ],
+                        ]
+                    ],
+                    [
+                        'name' => '角色管理',
+                        'url' => 'store.role',
+                        'subset' => [
+                            [
+                                'name' => '角色列表',
+                                'url' => 'store.role/index'
+                            ],
+                            [
+                                'name' => '添加角色',
+                                'url' => 'store.role/add'
+                            ],
+                            [
+                                'name' => '编辑角色',
+                                'url' => 'store.role/edit'
+                            ],
+                            [
+                                'name' => '删除角色',
+                                'url' => 'store.role/delete'
+                            ],
+                        ]
+                    ],
+                    [
+                        'name' => '权限管理',
+                        'url' => 'store.access',
+                        'subset' => [
+                            [
+                                'name' => '权限列表',
+                                'url' => 'store.access/index'
+                            ],
+                            [
+                                'name' => '添加权限',
+                                'url' => 'store.access/add'
+                            ],
+                            [
+                                'name' => '编辑权限',
+                                'url' => 'store.access/edit'
+                            ],
+                            [
+                                'name' => '删除权限',
+                                'url' => 'store.access/delete'
+                            ],
+                        ]
+                    ],
+                ]
+            ],
+            [
+                'name' => '商品管理',
+                'url' => 'goods',
+                'subset' => [
+                    [
+                        'name' => '商品管理',
+                        'url' => 'goods',
+                        'subset' => [
+                            [
+                                'name' => '商品列表',
+                                'url' => 'goods/index',
+                            ],
+                            [
+                                'name' => '添加商品',
+                                'url' => 'goods/add',
+                            ],
+                            [
+                                'name' => '编辑商品',
+                                'url' => 'goods/edit',
+                            ],
+                            [
+                                'name' => '复制商品',
+                                'url' => 'goods/copy',
+                            ],
+                            [
+                                'name' => '删除商品',
+                                'url' => 'goods/delete',
+                            ],
+                            [
+                                'name' => '商品上下架',
+                                'url' => 'goods/state',
+                            ],
+                        ]
+                    ],
+                    [
+                        'name' => '商品分类',
+                        'url' => 'goods.category',
+                        'subset' => [
+                            [
+                                'name' => '分类列表',
+                                'url' => 'goods.category/index',
+                            ],
+                            [
+                                'name' => '添加分类',
+                                'url' => 'goods.category/add',
+                            ],
+                            [
+                                'name' => '编辑分类',
+                                'url' => 'goods.category/edit',
+                            ],
+                            [
+                                'name' => '删除分类',
+                                'url' => 'goods.category/delete',
+                            ],
+                        ],
+                    ],
+                    [
+                        'name' => '商品评价',
+                        'url' => 'goods.comment',
+                        'subset' => [
+                            [
+                                'name' => '评价列表',
+                                'url' => 'goods.comment/index',
+                            ],
+                            [
+                                'name' => '评价详情',
+                                'url' => 'goods.comment/detail',
+                            ],
+                            [
+                                'name' => '删除评价',
+                                'url' => 'goods.comment/delete',
+                            ],
+                        ],
+                    ],
+                ]
+            ],
+            [
+                'name' => '订单管理',
+                'url' => 'order',
+                'subset' => [
+                    [
+                        'name' => '订单列表',
+                        'url' => '',
+                        'subset' => [
+                            [
+                                'name' => '待发货',
+                                'url' => 'order/delivery_list'
+                            ],
+                            [
+                                'name' => '待收货',
+                                'url' => 'order/receipt_list'
+                            ],
+                            [
+                                'name' => '待付款',
+                                'url' => 'order/pay_list'
+                            ],
+                            [
+                                'name' => '已完成',
+                                'url' => 'order/complete_list'
+                            ],
+                            [
+                                'name' => '已取消',
+                                'url' => 'order/cancel_list'
+                            ],
+                            [
+                                'name' => '全部订单',
+                                'url' => 'order/all_list',
+                            ],
+                        ]
+                    ],
+                    [
+                        'name' => '订单详情',
+                        'url' => '',
+                        'subset' => [
+                            [
+                                'name' => '详情信息',
+                                'url' => 'order/detail',
+                            ],
+                            [
+                                'name' => '确认发货',
+                                'url' => 'order/delivery',
+                            ],
+                            [
+                                'name' => '修改订单价格',
+                                'url' => 'order/updateprice',
+                            ],
+                        ]
+                    ],
+                    [
+                        'name' => '订单导出',
+                        'url' => 'order.operate/export',
+                    ],
+                    [
+                        'name' => '批量发货',
+                        'url' => 'order.operate/batchdelivery',
+                    ],
+                ]
+            ],
+            [
+                'name' => '用户管理',
+                'url' => 'user',
+                'subset' => [
+                    [
+                        'name' => '用户列表',
+                        'url' => 'user/index'
+                    ],
+                    [
+                        'name' => '删除用户',
+                        'url' => 'user/delete'
+                    ],
+                ]
+            ],
+            [
+                'name' => '营销设置',
+                'url' => 'market',
+                'subset' => [
+                    [
+                        'name' => '优惠券',
+                        'url' => 'coupon',
+                        'subset' => [
+                            [
+                                'name' => '优惠券列表',
+                                'url' => 'market.coupon/index',
+                            ],
+                            [
+                                'name' => '新增优惠券',
+                                'url' => 'market.coupon/add',
+                            ],
+                            [
+                                'name' => '编辑优惠券',
+                                'url' => 'market.coupon/edit',
+                            ],
+                            [
+                                'name' => '删除优惠券',
+                                'url' => 'market.coupon/delete',
+                            ],
+                            [
+                                'name' => '领取记录',
+                                'url' => 'market.coupon/receive',
+                            ]
+                        ]
+                    ]
+                ]
+            ],
+            [
+                'name' => '小程序',
+                'url' => 'wxapp',
+                'subset' => [
+                    [
+                        'name' => '小程序设置',
+                        'url' => 'wxapp/setting',
+                    ],
+                    [
+                        'name' => '页面管理',
+                        'url' => 'wxapp.page',
+                        'subset' => [
+                            [
+                                'name' => '页面设计',
+                                'url' => '',
+                                'subset' => [
+                                    [
+                                        'name' => '页面列表',
+                                        'url' => 'wxapp.page/index',
+                                    ],
+                                    [
+                                        'name' => '新增页面',
+                                        'url' => 'wxapp.page/add',
+                                    ],
+                                    [
+                                        'name' => '编辑页面',
+                                        'url' => 'wxapp.page/edit',
+                                    ],
+                                    [
+                                        'name' => '设为首页',
+                                        'url' => 'wxapp.page/sethome',
+                                    ],
+                                ]
+                            ],
+                            [
+                                'name' => '分类页模板',
+                                'url' => 'wxapp.page/category',
+                            ],
+                            [
+                                'name' => '页面链接',
+                                'url' => 'wxapp.page/links',
+                            ],
+                        ]
+                    ],
+                    [
+                        'name' => '帮助中心',
+                        'url' => 'wxapp.help',
+                        'subset' => [
+                            [
+                                'name' => '帮助列表',
+                                'url' => 'wxapp.help/index',
+                            ],
+                            [
+                                'name' => '新增帮助',
+                                'url' => 'wxapp.help/add',
+                            ],
+                            [
+                                'name' => '编辑帮助',
+                                'url' => 'wxapp.help/edit',
+                            ],
+                            [
+                                'name' => '删除帮助',
+                                'url' => 'wxapp.help/delete',
+                            ],
+                        ]
+                    ],
+                ]
+            ],
+            [
+                'name' => '应用中心',
+                'url' => 'apps',
+                'subset' => [
+                    [
+                        'name' => '分销中心',
+                        'url' => 'apps.dealer',
+                        'subset' => [
+                            [
+                                'name' => '入驻申请',
+                                'url' => 'apps.dealer.apply',
+                                'subset' => [
+                                    [
+                                        'name' => '申请列表',
+                                        'url' => 'apps.dealer.apply/index'
+                                    ],
+                                    [
+                                        'name' => '分销商审核',
+                                        'url' => 'apps.dealer.apply/submit'
+                                    ]
+                                ]
+                            ],
+                            [
+                                'name' => '分销商用户',
+                                'url' => 'apps.dealer.user',
+                                'subset' => [
+                                    [
+                                        'name' => '分销商列表',
+                                        'url' => 'apps.dealer.user/index',
+                                    ],
+                                    [
+                                        'name' => '删除分销商',
+                                        'url' => 'apps.dealer.user/delete'
+                                    ],
+                                    [
+                                        'name' => '分销商二维码',
+                                        'url' => 'apps.dealer.user/qrcode'
+                                    ]
+                                ]
+                            ],
+                            [
+                                'name' => '分销订单',
+                                'url' => 'apps.dealer.order/index',
+                            ],
+                            [
+                                'name' => '提现申请',
+                                'url' => 'apps.dealer.withdraw',
+                                'subset' => [
+                                    [
+                                        'name' => '申请列表',
+                                        'url' => 'apps.dealer.withdraw/index',
+                                    ],
+                                    [
+                                        'name' => '提现审核',
+                                        'url' => 'apps.dealer.withdraw/submit'
+                                    ],
+                                    [
+                                        'name' => '确认打款',
+                                        'url' => 'apps.dealer.withdraw/money'
+                                    ]
+                                ]
+                            ],
+                            [
+                                'name' => '分销设置',
+                                'url' => 'apps.dealer.setting/index',
+                            ],
+                            [
+                                'name' => '分销海报',
+                                'url' => 'apps.dealer.setting/qrcode',
+                            ],
+                        ]
+                    ],
+                ]
+            ],
+            [
+                'name' => '设置',
+                'url' => 'setting',
+                'subset' => [
+                    [
+                        'name' => '商城设置',
+                        'url' => 'setting/store',
+                    ],
+                    [
+                        'name' => '交易设置',
+                        'url' => 'setting/trade',
+                    ],
+                    [
+                        'name' => '配送设置',
+                        'url' => 'setting.delivery',
+                        'subset' => [
+                            [
+                                'name' => '运费模板列表',
+                                'url' => 'setting.delivery/index'
+                            ],
+                            [
+                                'name' => '新增运费模板',
+                                'url' => 'setting.delivery/add'
+                            ],
+                            [
+                                'name' => '编辑运费模板',
+                                'url' => 'setting.delivery/edit'
+                            ],
+                            [
+                                'name' => '删除运费模板',
+                                'url' => 'setting.delivery/delete'
+                            ],
+                        ]
+                    ],
+                    [
+                        'name' => '物流公司',
+                        'url' => 'setting.express',
+                        'subset' => [
+                            [
+                                'name' => '物流公司列表',
+                                'url' => 'setting.express/index'
+                            ],
+                            [
+                                'name' => '新增物流公司',
+                                'url' => 'setting.express/add'
+                            ],
+                            [
+                                'name' => '编辑物流公司',
+                                'url' => 'setting.express/edit'
+                            ],
+                            [
+                                'name' => '删除物流公司',
+                                'url' => 'setting.express/delete'
+                            ],
+                        ]
+                    ],
+                    [
+                        'name' => '短信通知',
+                        'url' => 'setting/sms',
+                    ],
+                    [
+                        'name' => '模板消息',
+                        'url' => 'setting/tplmsg',
+                    ],
+                    [
+                        'name' => '上传设置',
+                        'url' => 'setting/storage',
+                    ],
+                    [
+                        'name' => '其他',
+                        'url' => '',
+                        'subset' => [
+                            [
+                                'name' => '清理缓存',
+                                'url' => 'setting.cache/clear',
+                            ],
+                        ]
+                    ]
+                ]
+            ],
+        ];
+    }
+
+}

+ 54 - 0
dyu/application/admin/model/store/User.php

@@ -0,0 +1,54 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\admin\model\store;
+
+use app\common\model\store\User as StoreUserModel;
+
+/**
+ * 商家用户模型
+ * Class StoreUser
+ * @package app\admin\model
+ */
+class User extends StoreUserModel
+{
+    /**
+     * 新增商家用户记录
+     * @param $wxapp_id
+     * @param $data
+     * @return bool|false|int
+     */
+    public function add($wxapp_id, $data)
+    {
+        if (self::checkExist($data['user_name'])) {
+            $this->error = '商家用户名已存在';
+            return false;
+        }
+        return $this->save([
+            'user_name' => $data['user_name'],
+            'password' => dyu_hash($data['password']),
+            'wxapp_id' => $wxapp_id,
+        ]);
+    }
+
+    /**
+     * 商家用户登录
+     * @param $wxapp_id
+     * @throws \think\Exception
+     * @throws \think\exception\DbException
+     */
+    public function login($wxapp_id)
+    {
+        // 验证用户名密码是否正确
+        $user = self::detail(['wxapp_id' => $wxapp_id], ['wxapp']);
+        $this->loginState($user);
+    }
+
+}

+ 55 - 0
dyu/application/admin/view/admin/user/renew.php

@@ -0,0 +1,55 @@
+<div class="row-content am-cf">
+    <div class="row">
+        <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+            <div class="widget am-cf">
+                <form id="my-form" class="am-form tpl-form-line-form" enctype="multipart/form-data" method="post">
+                    <div class="widget-body">
+                        <fieldset>
+                            <div class="widget-head am-cf">
+                                <div class="widget-title am-fl">管理员设置</div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-form-label form-require"> 用户名 </label>
+                                <div class="am-u-sm-9">
+                                    <input type="text" class="tpl-form-input" name="user[user_name]"
+                                           value="<?= $model['user_name'] ?>" required>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-form-label form-require"> 登录密码 </label>
+                                <div class="am-u-sm-9">
+                                    <input type="password" class="tpl-form-input" name="user[password]"
+                                           value="" required>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-form-label form-require"> 确认密码 </label>
+                                <div class="am-u-sm-9">
+                                    <input type="password" class="tpl-form-input" name="user[password_confirm]"
+                                           value="" required>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <div class="am-u-sm-9 am-u-sm-push-3 am-margin-top-lg">
+                                    <button type="submit" class="j-submit am-btn am-btn-secondary">提交
+                                    </button>
+                                </div>
+                            </div>
+                        </fieldset>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    $(function () {
+
+        /**
+         * 表单验证提交
+         * @type {*}
+         */
+        $('#my-form').superForm();
+
+    });
+</script>

+ 12 - 0
dyu/application/admin/view/index/index.php

@@ -0,0 +1,12 @@
+
+    <div class="widget am-cf">
+        <div class="widget-body">
+            <div class="tpl-page-state am-margin-top-xl">
+                <div class="tpl-page-state-title am-text-center">小程序运营管理系统</div>
+                <div class="tpl-page-state-content tpl-error-content">
+                    <p>平台运营管理后台</p>
+                </div>
+            </div>
+        </div>
+    </div>
+

+ 104 - 0
dyu/application/admin/view/layouts/layout.php

@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="utf-8"/>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <title>运营管理系统</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1"/>
+    <meta name="renderer" content="webkit"/>
+    <meta http-equiv="Cache-Control" content="no-siteapp"/>
+    <link rel="icon" type="image/png" href="static/common/i/favicon.ico"/>
+    <meta name="apple-mobile-web-app-title" content="运营管理系统"/>
+    <link rel="stylesheet" href="static/common/css/amazeui.min.css"/>
+    <link rel="stylesheet" href="static/admin/css/app.css"/>
+    <link rel="stylesheet" href="//at.alicdn.com/t/font_783249_c9du3u6ahxp.css">
+    <script src="static/common/js/jquery.min.js"></script>
+    <script>
+        BASE_URL = '<?= isset($base_url) ? $base_url : '' ?>';
+        ADMIN_URL = '<?= isset($admin_url) ? $admin_url : '' ?>';
+    </script>
+</head>
+
+<body data-type="">
+<div class="am-g tpl-g">
+    <!-- 头部 -->
+    <header class="tpl-header">
+        <!-- 右侧内容 -->
+        <div class="tpl-header-fluid">
+            <!-- 其它功能-->
+            <div class="am-fr tpl-header-navbar">
+                <ul>
+                    <!-- 欢迎语 -->
+                    <li class="am-text-sm tpl-header-navbar-welcome">
+                        <a href="<?= url('admin.user/renew') ?>">欢迎你,<span><?= $admin['user']['user_name'] ?></span>
+                        </a>
+                    </li>
+                    <!-- 退出 -->
+                    <li class="am-text-sm">
+                        <a href="<?= url('passport/logout') ?>">
+                            <i class="iconfont icon-tuichu"></i> 退出
+                        </a>
+                    </li>
+                </ul>
+            </div>
+        </div>
+    </header>
+
+    <!-- 内容区域 start -->
+    <div class="tpl-content-wrapper dis-flex">
+        <!-- 左侧菜单 -->
+        <?php $menus = $menus ?: []; ?>
+        <?php $group = $group ?: 0; ?>
+        <div class="left-sidebar">
+            <ul class="sidebar-nav">
+                <?php foreach ($menus as $key => $item): ?>
+                    <li class="sidebar-nav-link">
+                        <a href="<?= isset($item['index']) ? url($item['index']) : 'javascript:void(0);' ?>"
+                           class="sidebar-nav-link-disabled">
+                            <?php if (isset($item['is_svg']) && $item['is_svg'] == true): ?>
+                                <svg class="icon sidebar-nav-link-logo" aria-hidden="true">
+                                    <use xlink:href="#<?= $item['icon'] ?>"></use>
+                                </svg>
+                            <?php else: ?>
+                                <i class="iconfont sidebar-nav-link-logo <?= $item['icon'] ?>"
+                                   style="<?= isset($item['color']) ? "color:{$item['color']};" : '' ?>"></i>
+                            <?php endif; ?>
+                            <?= $item['name'] ?>
+                        </a>
+                        <!-- 子级菜单-->
+                        <?php if (isset($item['submenu']) && !empty($item['submenu'])) : ?>
+                            <ul class="sidebar-third-nav-sub">
+                                <?php foreach ($item['submenu'] as $second) : ?>
+                                    <li class="sidebar-nav-link <?= $second['active'] ? 'active' : '' ?>">
+                                        <a class="" href="<?= url($second['index']) ?>">
+                                            <?= $second['name'] ?></a>
+                                    </li>
+                                <?php endforeach; ?>
+                            </ul>
+                        <?php endif; ?>
+                    </li>
+                <?php endforeach; ?>
+            </ul>
+        </div>
+        <!-- 内容区域 -->
+        <div class="row-content am-cf">
+            {__CONTENT__}
+        </div>
+
+    </div>
+    <!-- 内容区域 end -->
+
+    <div class="help-block am-text-center am-padding-sm">
+        <small>当前系统版本号:v<?= $version ?></small>
+    </div>
+</div>
+<script src="static/common/plugins/layer/layer.js"></script>
+<script src="static/common/js/jquery.form.min.js"></script>
+<script src="static/common/js/amazeui.min.js"></script>
+<script src="static/common/js/webuploader.html5only.js"></script>
+<script src="static/common/js/art-template.js"></script>
+<script src="static/admin/js/app.js"></script>
+</body>
+
+</html>

+ 63 - 0
dyu/application/admin/view/passport/login.php

@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <meta content="IE=edge" http-equiv="X-UA-Compatible">
+    <title>商城系统登录</title>
+    <link rel="icon" type="image/png" href="static/common/i/favicon.ico"/>
+    <link rel="stylesheet" href="static/admin/css/login/style.css"/>
+</head>
+<body class="page-login-v3">
+<div class="container">
+    <div id="wrapper" class="login-body">
+        <div class="login-content">
+            <div class="brand">
+                <h2 class="brand-text">小程序运营管理系统</h2>
+            </div>
+            <form id="login-form" class="login-form">
+                <div class="form-group">
+                    <input class="" name="User[user_name]" placeholder="请输入用户名" type="text" required>
+                </div>
+                <div class="form-group">
+                    <input class="" name="User[password]" placeholder="请输入密码" type="password" required>
+                </div>
+                <div class="form-group">
+                    <button id="btn-submit" type="submit">
+                        登录
+                    </button>
+                </div>
+            </form>
+        </div>
+    </div>
+</div>
+</body>
+<script src="static/common/js/jquery.min.js"></script>
+<script src="static/common/plugins/layer/layer.js"></script>
+<script src="static/common/js/jquery.form.min.js"></script>
+<script>
+    $(function () {
+        // 表单提交
+        var $form = $('#login-form');
+        $form.submit(function () {
+            var $btn_submit = $('#btn-submit');
+            $btn_submit.attr("disabled", true);
+            $form.ajaxSubmit({
+                type: "post",
+                dataType: "json",
+                // url: '',
+                success: function (result) {
+                    $btn_submit.attr('disabled', false);
+                    if (result.code === 1) {
+                        layer.msg(result.msg, {time: 1500, anim: 1}, function () {
+                            window.location = result.url;
+                        });
+                        return true;
+                    }
+                    layer.msg(result.msg, {time: 1500, anim: 6});
+                }
+            });
+            return false;
+        });
+    });
+</script>
+</html>

+ 78 - 0
dyu/application/admin/view/setting/cache/clear.php

@@ -0,0 +1,78 @@
+<div class="row">
+    <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+        <div class="widget am-cf">
+            <form id="my-form" class="am-form tpl-form-line-form" enctype="multipart/form-data" method="post">
+                <div class="widget-body">
+                    <fieldset>
+                        <div class="widget-head am-cf">
+                            <div class="widget-title am-fl">清理缓存</div>
+                        </div>
+                        <div class="am-form-group">
+                            <label class="am-u-sm-3 am-form-label form-require">
+                                缓存项
+                            </label>
+                            <div class="am-u-sm-9">
+                                <label class="am-checkbox-inline">
+                                    <input type="checkbox" name="cache[item][]" value="data"
+                                           data-am-ucheck checked required>
+                                    数据缓存
+                                </label>
+                                <label class="am-checkbox-inline">
+                                    <input type="checkbox" name="cache[item][]" value="temp"
+                                           data-am-ucheck checked required>
+                                    临时图片
+                                </label>
+                            </div>
+                        </div>
+                        <?php if (isset($isForce) && $isForce === true): ?>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-form-label form-require"> 强制模式 </label>
+                                <div class="am-u-sm-9">
+                                    <label class="am-radio-inline">
+                                        <input type="radio" name="cache[isForce]" value="0" checked
+                                               data-am-ucheck>
+                                        否
+                                    </label>
+                                    <label class="am-radio-inline">
+                                        <input type="radio" name="cache[isForce]" value="1" data-am-ucheck>
+                                        是
+                                    </label>
+                                    <div class="help-block">
+                                        <small class="x-color-red">此操作将会强制清空所有缓存文件,包含用户授权登录状态、用户购物车数据,仅允许在开发环境中使用
+                                        </small>
+                                    </div>
+                                </div>
+                            </div>
+                        <?php else: ?>
+                            <div class="am-form-group">
+                                <div class="am-u-sm-9 am-u-sm-push-3">
+                                    <small>
+                                        <a href="<?= url('', ['isForce' => true]) ?>">
+                                            进入强制模式</a>
+                                    </small>
+                                </div>
+                            </div>
+                        <?php endif; ?>
+                        <div class="am-form-group">
+                            <div class="am-u-sm-9 am-u-sm-push-3 am-margin-top-lg">
+                                <button type="submit" class="j-submit am-btn am-btn-secondary">提交
+                                </button>
+                            </div>
+                        </div>
+                    </fieldset>
+                </div>
+            </form>
+        </div>
+    </div>
+</div>
+<script>
+    $(function () {
+
+        /**
+         * 表单验证提交
+         * @type {*}
+         */
+        $('#my-form').superForm();
+
+    });
+</script>

+ 100 - 0
dyu/application/admin/view/setting/science/index.php

@@ -0,0 +1,100 @@
+<div class="row">
+    <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+        <div class="widget am-cf">
+            <form class="am-form tpl-form-line-form">
+                <div class="widget-body">
+                    <fieldset>
+                        <div class="widget-head am-cf">
+                            <div class="widget-title am-fl">服务器信息</div>
+                        </div>
+                        <div class="am-form-group">
+                            <div class="am-scrollable-horizontal">
+                                <table class="am-table am-table-centered">
+                                    <tbody>
+                                    <tr>
+                                        <th width="30%">参数</th>
+                                        <th>值</th>
+                                        <th></th>
+                                    </tr>
+                                    <?php if (isset($server)): foreach ($server as $item): ?>
+                                        <tr class="<?= isset($statusClass) ? $statusClass[$item['status']] : '' ?>">
+                                            <td><?= $item['name'] ?></td>
+                                            <td><?= $item['value'] ?> </td>
+                                            <td><?= $item['status'] !== 'normal' ? $item['remark'] : '' ?> </td>
+                                        </tr>
+                                    <?php endforeach; endif; ?>
+                                    </tbody>
+                                </table>
+                            </div>
+                        </div>
+
+                        <div class="widget-head am-cf">
+                            <div class="widget-title am-fl">PHP环境要求</div>
+                        </div>
+                        <div class="am-form-group">
+                            <div class="am-scrollable-horizontal">
+                                <table class="am-table am-table-centered">
+                                    <tbody>
+                                    <tr>
+                                        <th width="30%">选项</th>
+                                        <th>要求</th>
+                                        <th>状态</th>
+                                        <th></th>
+                                    </tr>
+                                    <?php if (isset($phpinfo)): foreach ($phpinfo as $item): ?>
+                                        <tr class="<?= isset($statusClass) ? $statusClass[$item['status']] : '' ?>">
+                                            <td><?= $item['name'] ?></td>
+                                            <td><?= $item['value'] ?> </td>
+                                            <td>
+                                                <?php if ($item['status'] !== 'danger'): ?>
+                                                    <i class="am-icon-check x-color-green"></i>
+                                                <?php else: ?>
+                                                    <i class="am-icon-times x-color-red"></i>
+                                                <?php endif; ?>
+                                            </td>
+                                            <td><?= $item['status'] !== 'normal' ? $item['remark'] : '' ?> </td>
+                                        </tr>
+                                    <?php endforeach; endif; ?>
+                                    </tbody>
+                                </table>
+                            </div>
+                        </div>
+
+                        <div class="widget-head am-cf">
+                            <div class="widget-title am-fl">目录权限监测</div>
+                        </div>
+                        <div class="am-form-group">
+                            <div class="am-scrollable-horizontal">
+                                <table class="am-table am-table-centered">
+                                    <tbody>
+                                    <tr>
+                                        <th width="30%">名称</th>
+                                        <th class="am-text-left">路径</th>
+                                        <th>状态</th>
+                                        <th></th>
+                                    </tr>
+                                    <?php if (isset($writeable)): foreach ($writeable as $item): ?>
+                                        <tr class="<?= isset($statusClass) ? $statusClass[$item['status']] : '' ?>">
+                                            <td><?= $item['name'] ?></td>
+                                            <td class="am-text-left"><?= $item['value'] ?> </td>
+                                            <td>
+                                                <?php if ($item['status'] !== 'danger'): ?>
+                                                    <i class="am-icon-check x-color-green"></i>
+                                                <?php else: ?>
+                                                    <i class="am-icon-times x-color-red"></i>
+                                                <?php endif; ?>
+                                            </td>
+                                            <td><?= $item['status'] !== 'normal' ? $item['remark'] : '' ?> </td>
+                                        </tr>
+                                    <?php endforeach; endif; ?>
+                                    </tbody>
+                                </table>
+                            </div>
+                        </div>
+
+                    </fieldset>
+                </div>
+            </form>
+        </div>
+    </div>
+</div>

+ 67 - 0
dyu/application/admin/view/store/access/add.php

@@ -0,0 +1,67 @@
+<div class="row-content am-cf">
+    <div class="row">
+        <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+            <div class="widget am-cf">
+                <form id="my-form" class="am-form tpl-form-line-form" method="post">
+                    <div class="widget-body">
+                        <fieldset>
+                            <div class="widget-head am-cf">
+                                <div class="widget-title am-fl">添加权限</div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">权限名称 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="access[name]"
+                                           value="" placeholder="请输入权限名称" required>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">上级权限 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <select name="access[parent_id]" data-am-selected="{searchBox: 1, btnSize: 'sm', maxHeight: 420}">
+                                        <option value="0"> 顶级权限 </option>
+                                        <?php if (isset($accessList)): foreach ($accessList as $access): ?>
+                                            <option value="<?= $access['access_id'] ?>"> <?= $access['name_h1'] ?></option>
+                                        <?php endforeach; endif; ?>
+                                    </select>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">权限url </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="access[url]"
+                                           value="" placeholder="请输入权限url" required>
+                                    <small>例如:index/index</small>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label">排序 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="number" min="0" class="tpl-form-input" name="access[sort]"
+                                           value="100">
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <div class="am-u-sm-9 am-u-sm-push-3 am-margin-top-lg">
+                                    <button type="submit" class="j-submit am-btn am-btn-secondary">提交
+                                    </button>
+                                </div>
+                            </div>
+                        </fieldset>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    $(function () {
+
+        /**
+         * 表单验证提交
+         * @type {*}
+         */
+        $('#my-form').superForm();
+
+    });
+</script>

+ 69 - 0
dyu/application/admin/view/store/access/edit.php

@@ -0,0 +1,69 @@
+<div class="row-content am-cf">
+    <div class="row">
+        <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+            <div class="widget am-cf">
+                <form id="my-form" class="am-form tpl-form-line-form" method="post">
+                    <div class="widget-body">
+                        <fieldset>
+                            <div class="widget-head am-cf">
+                                <div class="widget-title am-fl">编辑权限</div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">权限名称 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="access[name]"
+                                           value="<?= $model['name'] ?>" placeholder="请输入权限名称" required>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">上级权限 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <select name="access[parent_id]" data-am-selected="{searchBox: 1, btnSize: 'sm', maxHeight: 420}">
+                                        <option value="0"> 顶级权限</option>
+                                        <?php if (isset($accessList)): foreach ($accessList as $access): ?>
+                                            <option value="<?= $access['access_id'] ?>"
+                                                <?= $model['parent_id'] == $access['access_id'] ? 'selected' : '' ?>
+                                                <?= $model['access_id'] == $access['access_id'] ? 'disabled' : '' ?>>
+                                                <?= $access['name_h1'] ?></option>
+                                        <?php endforeach; endif; ?>
+                                    </select>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">权限url </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="access[url]"
+                                           value="<?= $model['url'] ?>" placeholder="请输入权限url" required>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label">排序 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="number" min="0" class="tpl-form-input" name="access[sort]"
+                                           value="<?= $model['sort'] ?>">
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <div class="am-u-sm-9 am-u-sm-push-3 am-margin-top-lg">
+                                    <button type="submit" class="j-submit am-btn am-btn-secondary">提交
+                                    </button>
+                                </div>
+                            </div>
+                        </fieldset>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    $(function () {
+
+        /**
+         * 表单验证提交
+         * @type {*}
+         */
+        $('#my-form').superForm();
+
+    });
+</script>

+ 83 - 0
dyu/application/admin/view/store/access/index.php

@@ -0,0 +1,83 @@
+<div class="row-content am-cf">
+    <div class="row">
+        <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+            <div class="widget am-cf">
+                <div class="widget-head am-cf">
+                    <div class="widget-title a m-cf">权限列表</div>
+                </div>
+                <div class="widget-body am-fr">
+                    <div class="tips am-margin-bottom-sm am-u-sm-12">
+                        <div class="pre">
+                            <p> 1:此处数据为商城商户后台的页面url,用于给管理员角色设置操作权限</p>
+                            <p> 2:如非二次开发需求,本页面数据无需更改</p>
+                            <p> 3:商户后台菜单配置文件:source/application/store/extra/menus.php</p>
+                        </div>
+                    </div>
+                    <!-- 工具栏 -->
+                    <div class="page_toolbar am-margin-bottom-xs am-cf">
+                        <div class="am-form-group">
+                            <div class="am-btn-group am-btn-group-xs">
+                                <a class="am-btn am-btn-default am-btn-success"
+                                   href="<?= url('store.access/add') ?>">
+                                    <span class="am-icon-plus"></span> 新增
+                                </a>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="am-scrollable-horizontal am-u-sm-12">
+                        <table width="100%" class="am-table am-table-compact am-table-striped
+                         tpl-table-black am-text-nowrap">
+                            <thead>
+                            <tr>
+                                <th>权限ID</th>
+                                <th>权限名称</th>
+                                <th>权限url</th>
+                                <th>排序</th>
+                                <th>添加时间</th>
+                                <th>操作</th>
+                            </tr>
+                            </thead>
+                            <tbody>
+                            <?php if (!empty($list)): foreach ($list as $item): ?>
+                                <tr>
+                                    <td class="am-text-middle"><?= $item['access_id'] ?></td>
+                                    <td class="am-text-middle"><?= $item['name_h1'] ?></td>
+                                    <td class="am-text-middle"><?= $item['url'] ?></td>
+                                    <td class="am-text-middle"><?= $item['sort'] ?></td>
+                                    <td class="am-text-middle"><?= $item['create_time'] ?></td>
+                                    <td class="am-text-middle">
+                                        <div class="tpl-table-black-operation">
+                                            <a href="<?= url('store.access/edit', ['access_id' => $item['access_id']]) ?>">
+                                                <i class="am-icon-pencil"></i> 编辑
+                                            </a>
+                                            <a href="javascript:void(0);"
+                                               class="item-delete tpl-table-black-operation-del"
+                                               data-id="<?= $item['access_id'] ?>">
+                                                <i class="am-icon-trash"></i> 删除
+                                            </a>
+                                        </div>
+                                    </td>
+                                </tr>
+                            <?php endforeach; else: ?>
+                                <tr>
+                                    <td colspan="6" class="am-text-center">暂无记录</td>
+                                </tr>
+                            <?php endif; ?>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    $(function () {
+
+        // 删除元素
+        var url = "<?= url('store.access/delete') ?>";
+        $('.item-delete').delete('access_id', url, '删除后不可恢复,确定要删除吗?');
+
+    });
+</script>
+

+ 70 - 0
dyu/application/admin/view/store/add.php

@@ -0,0 +1,70 @@
+<div class="row">
+    <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+        <div class="widget am-cf">
+            <form id="my-form" class="am-form tpl-form-line-form" method="post">
+                <div class="widget-body">
+                    <fieldset>
+                        <div class="widget-head am-cf">
+                            <div class="widget-title am-fl">新增小程序商城</div>
+                        </div>
+                        <div class="am-form-group">
+                            <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require"> 商城名称 </label>
+                            <div class="am-u-sm-9 am-u-end">
+                                <input type="text" class="tpl-form-input" name="store[store_name]" value=""
+                                       required>
+                            </div>
+                        </div>
+                        <div class="am-form-group">
+                            <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">排序 </label>
+                            <div class="am-u-sm-9 am-u-end">
+                                <input type="number" min="0" class="tpl-form-input" name="store[sort]" value="100"
+                                       required>
+                                <small>数字越小越靠前</small>
+                            </div>
+                        </div>
+                        <div class="am-form-group am-padding-top-sm">
+                            <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require"> 商家账户名 </label>
+                            <div class="am-u-sm-9 am-u-end">
+                                <input type="text" class="tpl-form-input" name="store[user_name]" value=""
+                                       required>
+                                <small>商家后台用户名</small>
+                            </div>
+                        </div>
+                        <div class="am-form-group">
+                            <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require"> 商家账户密码 </label>
+                            <div class="am-u-sm-9 am-u-end">
+                                <input type="password" class="tpl-form-input" name="store[password]" value=""
+                                       required>
+                                <small>商家后台用户密码</small>
+                            </div>
+                        </div>
+                        <div class="am-form-group">
+                            <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require"> 确认密码 </label>
+                            <div class="am-u-sm-9 am-u-end">
+                                <input type="password" class="tpl-form-input" name="store[password_confirm]" value=""
+                                       required>
+                            </div>
+                        </div>
+                        <div class="am-form-group">
+                            <div class="am-u-sm-9 am-u-sm-push-3 am-margin-top-lg">
+                                <button type="submit" class="j-submit am-btn am-btn-secondary">提交
+                                </button>
+                            </div>
+                        </div>
+                    </fieldset>
+                </div>
+            </form>
+        </div>
+    </div>
+</div>
+<script>
+    $(function () {
+
+        /**
+         * 表单验证提交
+         * @type {*}
+         */
+        $('#my-form').superForm();
+
+    });
+</script>

+ 80 - 0
dyu/application/admin/view/store/index.php

@@ -0,0 +1,80 @@
+<div class="row">
+    <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+        <div class="widget am-cf">
+            <div class="widget-head am-cf">
+                <div class="widget-title am-cf">商城列表</div>
+            </div>
+            <div class="widget-body am-fr">
+                <div class="am-u-sm-12 am-u-md-6 am-u-lg-6">
+                    <div class="am-form-group">
+                        <div class="am-btn-toolbar">
+                            <div class="am-btn-group am-btn-group-xs">
+                                <a class="am-btn am-btn-default am-btn-success am-radius"
+                                   href="<?= url('store/add') ?>">
+                                    <span class="am-icon-plus"></span> 新增
+                                </a>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="am-u-sm-12">
+                    <table width="100%" class="am-table am-table-compact am-table-striped tpl-table-black ">
+                        <thead>
+                        <tr>
+                            <th>商城ID</th>
+                            <th>商城名称</th>
+                            <th>添加时间</th>
+                            <th>操作</th>
+                        </tr>
+                        </thead>
+                        <tbody>
+                        <?php if (!$list->isEmpty()): foreach ($list as $item): ?>
+                            <tr>
+                                <td class="am-text-middle">
+                                    <p class="item-title"><?= $item['wxapp_id'] ?></p>
+                                </td>
+                                <td class="am-text-middle">
+                                    <p class="item-title"><?= $names[$item['wxapp_id']] ?></p>
+                                </td>
+                                <td class="am-text-middle"><?= $item['create_time'] ?></td>
+                                <td class="am-text-middle">
+                                    <div class="tpl-table-black-operation">
+                                        <a href="<?= url('store/enter', ['wxapp_id' => $item['wxapp_id']]) ?>"
+                                           class="j-move" data-id="<?= $item['wxapp_id'] ?>" target="_blank">
+                                            <i class="am-icon-arrow-right"></i> 进入商城
+                                        </a>
+                                        <a href="javascript:void(0);" class="j-delete tpl-table-black-operation-del"
+                                           data-id="<?= $item['wxapp_id'] ?>">
+                                            <i class="am-icon-trash"></i> 删除
+                                        </a>
+                                    </div>
+                                </td>
+                            </tr>
+                        <?php endforeach; else: ?>
+                            <tr>
+                                <td colspan="4" class="am-text-center">暂无记录</td>
+                            </tr>
+                        <?php endif; ?>
+                        </tbody>
+                    </table>
+                </div>
+                <div class="am-u-lg-12 am-cf">
+                    <div class="am-fr"><?= $list->render() ?> </div>
+                    <div class="am-fr pagination-total am-margin-right">
+                        <div class="am-vertical-align-middle">总记录:<?= $list->total() ?></div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    $(function () {
+
+        // 删除元素
+        var url = "<?= url('store/recovery') ?>";
+        $('.j-delete').delete('wxapp_id', url, '确定要删除吗?可在回收站中恢复');
+
+    });
+</script>
+

+ 75 - 0
dyu/application/admin/view/store/recycle.php

@@ -0,0 +1,75 @@
+<div class="row">
+    <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+        <div class="widget am-cf">
+            <div class="widget-head am-cf">
+                <div class="widget-title am-cf">回收站列表</div>
+            </div>
+            <div class="widget-body am-fr">
+                <div class="am-u-sm-12 am-u-md-6 am-u-lg-6">
+                    <div class="am-form-group">
+                        <div class="am-btn-toolbar">
+                        </div>
+                    </div>
+                </div>
+                <div class="am-u-sm-12">
+                    <table width="100%" class="am-table am-table-compact am-table-striped tpl-table-black ">
+                        <thead>
+                        <tr>
+                            <th>商城ID</th>
+                            <th>商城名称</th>
+                            <th>添加时间</th>
+                            <th>操作</th>
+                        </tr>
+                        </thead>
+                        <tbody>
+                        <?php if (!$list->isEmpty()): foreach ($list as $item): ?>
+                            <tr>
+                                <td class="am-text-middle">
+                                    <p class="item-title"><?= $item['wxapp_id'] ?></p>
+                                </td>
+                                <td class="am-text-middle">
+                                    <p class="item-title"><?= $names[$item['wxapp_id']] ?></p>
+                                </td>
+                                <td class="am-text-middle"><?= $item['create_time'] ?></td>
+                                <td class="am-text-middle">
+                                    <div class="tpl-table-black-operation">
+                                        <a href="javascript:void(0);" class="j-move"
+                                           data-id="<?= $item['wxapp_id'] ?>">
+                                            <i class="am-icon-undo"></i> 还原
+                                        </a>
+                                        <a href="javascript:void(0);" class="j-delete tpl-table-black-operation-del"
+                                           data-id="<?= $item['wxapp_id'] ?>">
+                                            <i class="am-icon-trash"></i> 删除
+                                        </a>
+                                    </div>
+                                </td>
+                            </tr>
+                        <?php endforeach; else: ?>
+                            <tr>
+                                <td colspan="4" class="am-text-center">暂无记录</td>
+                            </tr>
+                        <?php endif; ?>
+                        </tbody>
+                    </table>
+                </div>
+                <div class="am-u-lg-12 am-cf">
+                    <div class="am-fr"><?= $list->render() ?> </div>
+                    <div class="am-fr pagination-total am-margin-right">
+                        <div class="am-vertical-align-middle">总记录:<?= $list->total() ?></div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    $(function () {
+
+        // 移出回收站
+        $('.j-move').delete('wxapp_id', "<?= url('store/move') ?>", '确定要还原吗?');
+
+        // 删除小程序
+        $('.j-delete').delete('wxapp_id', "<?= url('store/delete') ?>", '确定要删除吗?删除后无法恢复');
+    });
+</script>
+

+ 122 - 0
dyu/application/api/behavior/order/PaySuccess.php

@@ -0,0 +1,122 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\behavior\order;
+
+use app\common\service\Message as MessageService;
+use app\common\service\order\Printer as PrinterService;
+use app\common\service\wechat\wow\Order as WowOrder;
+use app\common\enum\OrderType as OrderTypeEnum;
+use app\common\enum\OrderStatus as OrderStatusEnum;
+use app\common\enum\order\OrderSource as OrderSourceEnum;
+
+/**
+ * 订单支付成功后扩展类
+ * Class PaySuccess
+ * @package app\api\behavior\order
+ */
+class PaySuccess
+{
+    // 订单信息
+    private $order;
+
+    // 订单类型
+    private $orderType;
+
+    private $wxappId;
+
+    /**
+     * 订单来源回调业务映射类
+     * @var array
+     */
+    protected $sourceCallbackClass = [
+        OrderSourceEnum::MASTER => 'app\api\service\master\order\PaySuccess',
+        OrderSourceEnum::BARGAIN => 'app\api\service\bargain\order\PaySuccess',
+        OrderSourceEnum::SHARP => 'app\api\service\sharp\order\PaySuccess',
+    ];
+
+    /**
+     * 执行入口
+     * @param $order
+     * @param int $orderType
+     * @return bool
+     * @throws \app\common\exception\BaseException
+     * @throws \think\Exception
+     * @throws \think\exception\DbException
+     */
+    public function run($order, $orderType = OrderTypeEnum::MASTER)
+    {
+        // 设置当前类的属性
+        $this->setAttribute($order, $orderType);
+        // 订单公共业务
+        $this->onCommonEvent();
+        // 普通订单业务
+        if ($orderType == OrderTypeEnum::MASTER) {
+            $this->onMasterEvent();
+        }
+        // 订单来源回调业务
+        $this->onSourceCallback();
+        return true;
+    }
+
+    /**
+     * 设置当前类的属性
+     * @param $order
+     * @param int $orderType
+     */
+    private function setAttribute($order, $orderType = OrderTypeEnum::MASTER)
+    {
+        $this->order = $order;
+        $this->wxappId = $this->order['wxapp_id'];
+        $this->orderType = $orderType;
+    }
+
+    /**
+     * 订单公共业务
+     * @throws \app\common\exception\BaseException
+     * @throws \think\Exception
+     * @throws \think\exception\DbException
+     */
+    private function onCommonEvent()
+    {
+        // 发送消息通知
+        (new MessageService)->payment($this->order, $this->orderType);
+        // 小票打印
+        (new PrinterService)->printTicket($this->order, OrderStatusEnum::ORDER_PAYMENT);
+    }
+
+    /**
+     * 普通订单业务
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    private function onMasterEvent()
+    {
+        // 同步好物圈
+        (new WowOrder($this->wxappId))->import([$this->order], true);
+    }
+
+    /**
+     * 订单来源回调业务
+     * @return bool
+     */
+    private function onSourceCallback()
+    {
+        if (!isset($this->order['order_source'])) {
+            return false;
+        }
+        if (!isset($this->sourceCallbackClass[$this->order['order_source']])) {
+            return false;
+        }
+        $class = $this->sourceCallbackClass[$this->order['order_source']];
+        return !is_null($class) ? (new $class)->onPaySuccess($this->order) : false;
+    }
+
+}

+ 8 - 0
dyu/application/api/config.php

@@ -0,0 +1,8 @@
+<?php
+
+return [
+    // 默认输出类型
+    'default_return_type' => 'json',
+    // 默认全局过滤方法 用逗号分隔多个
+    'default_filter' => 'trim,htmlspecialchars,filter_emoji',
+];

+ 120 - 0
dyu/application/api/controller/Address.php

@@ -0,0 +1,120 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\api\model\UserAddress;
+
+/**
+ * 收货地址管理
+ * Class Address
+ * @package app\api\controller
+ */
+class Address extends Controller
+{
+    /**
+     * 收货地址列表
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function lists()
+    {
+        $user = $this->getUser();
+        $model = new UserAddress;
+        $list = $model->getList($user['user_id']);
+        return $this->renderSuccess([
+            'list' => $list,
+            'default_id' => $user['address_id'],
+        ]);
+    }
+
+    /**
+     * 添加收货地址
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function add()
+    {
+        $model = new UserAddress;
+        if ($model->add($this->getUser(), $this->request->post())) {
+            return $this->renderSuccess([], '添加成功');
+        }
+        return $this->renderError($model->getError() ?: '添加失败');
+    }
+
+    /**
+     * 收货地址详情
+     * @param $address_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function detail($address_id)
+    {
+        $user = $this->getUser();
+        $detail = UserAddress::detail($user['user_id'], $address_id);
+        $region = array_values($detail['region']);
+        return $this->renderSuccess(compact('detail', 'region'));
+    }
+
+    /**
+     * 编辑收货地址
+     * @param $address_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function edit($address_id)
+    {
+        $user = $this->getUser();
+        $model = UserAddress::detail($user['user_id'], $address_id);
+        if ($model->edit($this->request->post())) {
+            return $this->renderSuccess([], '更新成功');
+        }
+        return $this->renderError($model->getError() ?: '更新失败');
+    }
+
+    /**
+     * 设为默认地址
+     * @param $address_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function setDefault($address_id)
+    {
+        $user = $this->getUser();
+        $model = UserAddress::detail($user['user_id'], $address_id);
+        if ($model->setDefault($user)) {
+            return $this->renderSuccess([], '设置成功');
+        }
+        return $this->renderError($model->getError() ?: '设置失败');
+    }
+
+    /**
+     * 删除收货地址
+     * @param $address_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function delete($address_id)
+    {
+        $user = $this->getUser();
+        $model = UserAddress::detail($user['user_id'], $address_id);
+        if ($model->remove($user)) {
+            return $this->renderSuccess([], '删除成功');
+        }
+        return $this->renderError($model->getError() ?: '删除失败');
+    }
+
+}

+ 61 - 0
dyu/application/api/controller/Article.php

@@ -0,0 +1,61 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\api\model\Article as ArticleModel;
+use app\api\model\article\Category as CategoryModel;
+
+/**
+ * 文章控制器
+ * Class Article
+ * @package app\api\controller
+ */
+class Article extends Controller
+{
+    /**
+     * 文章首页
+     * @return array
+     */
+    public function index()
+    {
+        // 文章分类列表
+        $categoryList = CategoryModel::getAll();
+        return $this->renderSuccess(compact('categoryList'));
+    }
+
+    /**
+     * 文章列表
+     * @param int $category_id
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function lists($category_id = 0)
+    {
+        $model = new ArticleModel;
+        $list = $model->getList($category_id);
+        return $this->renderSuccess(compact('list'));
+    }
+
+    /**
+     * 文章详情
+     * @param $article_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\Exception
+     * @throws \think\exception\DbException
+     */
+    public function detail($article_id)
+    {
+        $detail = ArticleModel::detail($article_id);
+        return $this->renderSuccess(compact('detail'));
+    }
+
+}

+ 104 - 0
dyu/application/api/controller/Cart.php

@@ -0,0 +1,104 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\api\model\Cart as CartModel;
+use app\api\service\order\Checkout as CheckoutModel;
+
+/**
+ * 购物车管理
+ * Class Cart
+ * @package app\api\controller
+ */
+class Cart extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    /* @var \app\api\model\Cart $model */
+    private $model;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->user = $this->getUser();
+        $this->model = new CartModel($this->user);
+    }
+
+    /**
+     * 购物车列表
+     * @return array
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function lists()
+    {
+        // 请求参数
+        $param = $this->request->param();
+        $cartIds = isset($param['cart_ids']) ? $param['cart_ids'] : '';
+        // 购物车商品列表
+        $goodsList = $this->model->getList($cartIds);
+        // 获取订单结算信息
+        $Checkout = new CheckoutModel;
+        $orderInfo = $Checkout->onCheckout($this->user, $goodsList);
+        return $this->renderSuccess($orderInfo);
+    }
+
+    /**
+     * 加入购物车
+     * @param int $goods_id 商品id
+     * @param int $goods_num 商品数量
+     * @param string $goods_sku_id 商品sku索引
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function add($goods_id, $goods_num, $goods_sku_id)
+    {
+        if (!$this->model->add($goods_id, $goods_num, $goods_sku_id)) {
+            return $this->renderError($this->model->getError() ?: '加入购物车失败');
+        }
+        // 购物车商品总数量
+        $totalNum = $this->model->getGoodsNum();
+        return $this->renderSuccess(['cart_total_num' => $totalNum], '加入购物车成功');
+    }
+
+    /**
+     * 减少购物车商品数量
+     * @param $goods_id
+     * @param $goods_sku_id
+     * @return array
+     */
+    public function sub($goods_id, $goods_sku_id)
+    {
+        $this->model->sub($goods_id, $goods_sku_id);
+        return $this->renderSuccess();
+    }
+
+    /**
+     * 删除购物车中指定商品
+     * @param $goods_sku_id (支持字符串ID集)
+     * @return array
+     */
+    public function delete($goods_sku_id)
+    {
+        $this->model->delete($goods_sku_id);
+        return $this->renderSuccess();
+    }
+
+}

+ 37 - 0
dyu/application/api/controller/Category.php

@@ -0,0 +1,37 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\api\model\Category as CategoryModel;
+use app\api\model\WxappCategory as WxappCategoryModel;
+
+/**
+ * 商品分类控制器
+ * Class Goods
+ * @package app\api\controller
+ */
+class Category extends Controller
+{
+    /**
+     * 分类页面
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function index()
+    {
+        // 分类模板
+        $templet = WxappCategoryModel::detail();
+        // 商品分类列表
+        $list = array_values(CategoryModel::getCacheTree());
+        return $this->renderSuccess(compact('templet', 'list'));
+    }
+
+}

+ 37 - 0
dyu/application/api/controller/Comment.php

@@ -0,0 +1,37 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\api\model\Comment as CommentModel;
+
+/**
+ * 商品评价控制器
+ * Class Comment
+ * @package app\api\controller
+ */
+class Comment extends Controller
+{
+    /**
+     * 商品评价列表
+     * @param $goods_id
+     * @param int $scoreType
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function lists($goods_id, $scoreType = -1)
+    {
+        $model = new CommentModel;
+        $list = $model->getGoodsCommentList($goods_id, $scoreType);
+        $total = $model->getTotal($goods_id);
+        return $this->renderSuccess(compact('list', 'total'));
+    }
+
+}

+ 147 - 0
dyu/application/api/controller/Controller.php

@@ -0,0 +1,147 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\api\model\User as UserModel;
+use app\api\model\Wxapp as WxappModel;
+use app\common\exception\BaseException;
+
+/**
+ * API控制器基类
+ * Class BaseController
+ * @package app\store\controller
+ */
+class Controller extends \think\Controller
+{
+    const JSON_SUCCESS_STATUS = 1;
+    const JSON_ERROR_STATUS = 0;
+
+    /* @ver $wxapp_id 小程序id */
+    protected $wxapp_id;
+
+    /**
+     * API基类初始化
+     * @throws BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        // 当前小程序id
+        $this->wxapp_id = $this->getWxappId();
+        // 验证当前小程序状态
+        $this->checkWxapp();
+    }
+
+    /**
+     * 获取当前小程序ID
+     * @return mixed
+     * @throws BaseException
+     */
+    private function getWxappId()
+    {
+        if (!$wxapp_id = $this->request->param('wxapp_id')) {
+            throw new BaseException(['msg' => '缺少必要的参数:wxapp_id']);
+        }
+        return $wxapp_id;
+    }
+
+    /**
+     * 验证当前小程序状态
+     * @throws BaseException
+     * @throws \think\exception\DbException
+     */
+    private function checkWxapp()
+    {
+        $wxapp = WxappModel::detail($this->wxapp_id);
+        if (empty($wxapp)) {
+            throw new BaseException(['msg' => '当前小程序信息不存在']);
+        }
+        if ($wxapp['is_recycle'] || $wxapp['is_delete']) {
+            throw new BaseException(['msg' => '当前小程序已删除']);
+        }
+    }
+
+    /**
+     * 获取当前用户信息
+     * @param bool $is_force
+     * @return UserModel|bool|null
+     * @throws BaseException
+     * @throws \think\exception\DbException
+     */
+    protected function getUser($is_force = true)
+    {
+        if (!$token = $this->request->param('token')) {
+            $is_force && $this->throwError('缺少必要的参数:token', -1);
+            return false;
+        }
+        if (!$user = UserModel::getUser($token)) {
+            $is_force && $this->throwError('没有找到用户信息', -1);
+            return false;
+        }
+        return $user;
+    }
+
+    /**
+     * 输出错误信息
+     * @param int $code
+     * @param $msg
+     * @throws BaseException
+     */
+    protected function throwError($msg, $code = 0)
+    {
+        throw new BaseException(['code' => $code, 'msg' => $msg]);
+    }
+
+    /**
+     * 返回封装后的 API 数据到客户端
+     * @param int $code
+     * @param string $msg
+     * @param array $data
+     * @return array
+     */
+    protected function renderJson($code = self::JSON_SUCCESS_STATUS, $msg = '', $data = [])
+    {
+        return compact('code', 'msg', 'data');
+    }
+
+    /**
+     * 返回操作成功json
+     * @param array $data
+     * @param string|array $msg
+     * @return array
+     */
+    protected function renderSuccess($data = [], $msg = 'success')
+    {
+        return $this->renderJson(self::JSON_SUCCESS_STATUS, $msg, $data);
+    }
+
+    /**
+     * 返回操作失败json
+     * @param string $msg
+     * @param array $data
+     * @return array
+     */
+    protected function renderError($msg = 'error', $data = [])
+    {
+        return $this->renderJson(self::JSON_ERROR_STATUS, $msg, $data);
+    }
+
+    /**
+     * 获取post数据 (数组)
+     * @param $key
+     * @return mixed
+     */
+    protected function postData($key = null)
+    {
+        return $this->request->post(is_null($key) ? '' : $key . '/a');
+    }
+
+}

+ 37 - 0
dyu/application/api/controller/Coupon.php

@@ -0,0 +1,37 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\api\model\Coupon as CouponModel;
+
+/**
+ * 优惠券中心
+ * Class Coupon
+ * @package app\api\controller
+ */
+class Coupon extends Controller
+{
+    /**
+     * 优惠券列表
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function lists()
+    {
+        $model = new CouponModel;
+        $list = $model->getList($this->getUser(false));
+        return $this->renderSuccess(compact('list'));
+    }
+
+}

+ 89 - 0
dyu/application/api/controller/Goods.php

@@ -0,0 +1,89 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\api\model\Goods as GoodsModel;
+use app\api\model\Cart as CartModel;
+use app\common\service\qrcode\Goods as GoodsPoster;
+
+/**
+ * 商品控制器
+ * Class Goods
+ * @package app\api\controller
+ */
+class Goods extends Controller
+{
+    /**
+     * 商品列表
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function lists()
+    {
+        // 整理请求的参数
+        $param = array_merge($this->request->param(), [
+            'status' => 10
+        ]);
+        // 获取列表数据
+        $model = new GoodsModel;
+        $list = $model->getList($param, $this->getUser(false));
+        return $this->renderSuccess(compact('list'));
+    }
+
+    /**
+     * 获取商品详情
+     * @param $goods_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function detail($goods_id)
+    {
+        // 用户信息
+        $user = $this->getUser(false);
+        // 商品详情
+        $model = new GoodsModel;
+        $goods = $model->getDetails($goods_id, $this->getUser(false));
+        if ($goods === false) {
+            return $this->renderError($model->getError() ?: '商品信息不存在');
+        }
+        // 多规格商品sku信息, todo: 已废弃 v1.1.25
+        $specData = $goods['spec_type'] == 20 ? $model->getManySpecData($goods['spec_rel'], $goods['sku']) : null;
+        return $this->renderSuccess([
+            // 商品详情
+            'detail' => $goods,
+            // 购物车商品总数量
+            'cart_total_num' => $user ? (new CartModel($user))->getGoodsNum() : 0,
+            // 多规格商品sku信息
+            'specData' => $specData,
+        ]);
+    }
+
+    /**
+     * 生成商品海报
+     * @param $goods_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     * @throws \Exception
+     */
+    public function poster($goods_id)
+    {
+        // 商品详情
+        $detail = GoodsModel::detail($goods_id);
+        $Qrcode = new GoodsPoster($detail, $this->getUser(false));
+        return $this->renderSuccess([
+            'qrcode' => $Qrcode->getImage(),
+        ]);
+    }
+
+}

+ 33 - 0
dyu/application/api/controller/Notify.php

@@ -0,0 +1,33 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\common\library\wechat\WxPay;
+
+/**
+ * 支付成功异步通知接口
+ * Class Notify
+ * @package app\api\controller
+ */
+class Notify
+{
+    /**
+     * 支付成功异步通知
+     * @throws \think\Exception
+     * @throws \think\exception\DbException
+     */
+    public function order()
+    {
+        // 微信支付组件:验证异步通知
+        $WxPay = new WxPay();
+        $WxPay->notify();
+    }
+}

+ 149 - 0
dyu/application/api/controller/Order.php

@@ -0,0 +1,149 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\api\model\Cart as CartModel;
+use app\api\model\Order as OrderModel;
+use app\api\service\order\Checkout as CheckoutModel;
+use app\api\validate\order\Checkout as CheckoutValidate;
+
+/**
+ * 订单控制器
+ * Class Order
+ * @package app\api\controller
+ */
+class Order extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    /* @var CheckoutValidate $validate */
+    private $validate;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        // 用户信息
+        $this->user = $this->getUser();
+        // 验证类
+        $this->validate = new CheckoutValidate;
+    }
+
+    /**
+     * 订单确认-立即购买
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     * @throws \Exception
+     */
+    public function buyNow()
+    {
+        // 实例化结算台服务
+        $Checkout = new CheckoutModel;
+        // 订单结算api参数
+        $params = $Checkout->setParam($this->getParam([
+            'goods_id' => 0,
+            'goods_num' => 0,
+            'goods_sku_id' => '',
+        ]));
+        // 表单验证
+        if (!$this->validate->scene('buyNow')->check($params)) {
+            return $this->renderError($this->validate->getError());
+        }
+        // 立即购买:获取订单商品列表
+        $model = new OrderModel;
+        $goodsList = $model->getOrderGoodsListByNow(
+            $params['goods_id'],
+            $params['goods_sku_id'],
+            $params['goods_num']
+        );
+        // 获取订单确认信息
+        $orderInfo = $Checkout->onCheckout($this->user, $goodsList);
+        if ($this->request->isGet()) {
+            return $this->renderSuccess($orderInfo);
+        }
+        // 订单结算提交
+        if ($Checkout->hasError()) {
+            return $this->renderError($Checkout->getError());
+        }
+        // 创建订单
+        if (!$Checkout->createOrder($orderInfo)) {
+            return $this->renderError($Checkout->getError() ?: '订单创建失败');
+        }
+        // 构建微信支付请求
+        $payment = $model->onOrderPayment($this->user, $Checkout->model, $params['pay_type']);
+        // 返回结算信息
+        return $this->renderSuccess([
+            'order_id' => $Checkout->model['order_id'],   // 订单id
+            'pay_type' => $params['pay_type'],  // 支付方式
+            'payment' => $payment               // 微信支付参数
+        ], ['success' => '支付成功', 'error' => '订单未支付']);
+    }
+
+    /**
+     * 订单确认-购物车结算
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \Exception
+     */
+    public function cart()
+    {
+        // 实例化结算台服务
+        $Checkout = new CheckoutModel;
+        // 订单结算api参数
+        $params = $Checkout->setParam($this->getParam([
+            'cart_ids' => '',
+        ]));
+        // 商品结算信息
+        $CartModel = new CartModel($this->user);
+        // 购物车商品列表
+        $goodsList = $CartModel->getList($params['cart_ids']);
+        // 获取订单结算信息
+        $orderInfo = $Checkout->onCheckout($this->user, $goodsList);
+        if ($this->request->isGet()) {
+            return $this->renderSuccess($orderInfo);
+        }
+        // 创建订单
+        if (!$Checkout->createOrder($orderInfo)) {
+            return $this->renderError($Checkout->getError() ?: '订单创建失败');
+        }
+        // 移出购物车中已下单的商品
+        $CartModel->clearAll($params['cart_ids']);
+        // 构建微信支付请求
+        $payment = $Checkout->onOrderPayment();
+        // 返回状态
+        return $this->renderSuccess([
+            'order_id' => $Checkout->model['order_id'],   // 订单id
+            'pay_type' => $params['pay_type'],  // 支付方式
+            'payment' => $payment               // 微信支付参数
+        ], ['success' => '支付成功', 'error' => '订单未支付']);
+    }
+
+    /**
+     * 订单结算提交的参数
+     * @param array $define
+     * @return array
+     */
+    private function getParam($define = [])
+    {
+        return array_merge($define, $this->request->param());
+    }
+
+}

+ 39 - 0
dyu/application/api/controller/Page.php

@@ -0,0 +1,39 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\api\model\WxappPage;
+
+/**
+ * 页面控制器
+ * Class Index
+ * @package app\api\controller
+ */
+class Page extends Controller
+{
+    /**
+     * 页面数据
+     * @param null $page_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function index($page_id = null)
+    {
+        // 页面元素
+        $data = WxappPage::getPageData($this->getUser(false), $page_id);
+        return $this->renderSuccess($data);
+    }
+
+}

+ 75 - 0
dyu/application/api/controller/Recharge.php

@@ -0,0 +1,75 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\api\model\Setting as SettingModel;
+use app\api\model\recharge\Plan as PlanModel;
+use app\api\model\recharge\Order as OrderModel;
+use app\api\service\Payment as PaymentService;
+use app\common\enum\OrderType as OrderTypeEnum;
+
+/**
+ * 用户充值管理
+ * Class Recharge
+ * @package app\api\controller
+ */
+class Recharge extends Controller
+{
+    /**
+     * 充值中心
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function index()
+    {
+        // 用户信息
+        $userInfo = $this->getUser();
+        // 充值套餐列表
+        $planList = (new PlanModel)->getList();
+        // 充值设置
+        $setting = SettingModel::getItem('recharge');
+        return $this->renderSuccess(compact('userInfo', 'planList', 'setting'));
+    }
+
+    /**
+     * 确认充值
+     * @param null $planId
+     * @param int $customMoney
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function submit($planId = null, $customMoney = 0)
+    {
+        // 用户信息
+        $userInfo = $this->getUser();
+        // 生成充值订单
+        $model = new OrderModel;
+        if (!$model->createOrder($userInfo, $planId, $customMoney)) {
+            return $this->renderError($model->getError() ?: '充值失败');
+        }
+        // 构建微信支付
+        $payment = PaymentService::wechat(
+            $userInfo,
+            $model['order_id'],
+            $model['order_no'],
+            $model['pay_price'],
+            OrderTypeEnum::RECHARGE
+        );
+        // 充值状态提醒
+        $message = ['success' => '充值成功', 'error' => '订单未支付'];
+        return $this->renderSuccess(compact('payment', 'message'), $message);
+    }
+
+}

+ 49 - 0
dyu/application/api/controller/Shop.php

@@ -0,0 +1,49 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\api\model\store\Shop as ShopModel;
+
+
+/**
+ * 门店列表
+ * Class Shop
+ * @package app\api\controller
+ */
+class Shop extends Controller
+{
+    /**
+     * 门店列表
+     * @param string $longitude
+     * @param string $latitude
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function lists($longitude = '', $latitude = '')
+    {
+        $model = new ShopModel;
+        $list = $model->getList(true, $longitude, $latitude);
+        return $this->renderSuccess(compact('list'));
+    }
+
+    /**
+     * 门店详情
+     * @param $shop_id
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function detail($shop_id)
+    {
+        $detail = ShopModel::detail($shop_id);
+        return $this->renderSuccess(compact('detail'));
+    }
+
+}

+ 94 - 0
dyu/application/api/controller/Upload.php

@@ -0,0 +1,94 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\api\model\UploadFile;
+use app\api\model\Setting as SettingModel;
+use app\common\library\storage\Driver as StorageDriver;
+
+/**
+ * 文件库管理
+ * Class Upload
+ * @package app\api\controller
+ */
+class Upload extends Controller
+{
+    private $config;
+    private $user;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        // 存储配置信息
+        $this->config = SettingModel::getItem('storage');
+        // 验证用户
+        $this->user = $this->getUser();
+    }
+
+    /**
+     * 图片上传接口
+     * @return array
+     * @throws \think\Exception
+     */
+    public function image()
+    {
+        // 实例化存储驱动
+        $StorageDriver = new StorageDriver($this->config);
+        // 设置上传文件的信息
+        $StorageDriver->setUploadFile('iFile');
+        // 上传图片
+        if (!$StorageDriver->upload()) {
+            return json(['code' => 0, 'msg' => '图片上传失败' . $StorageDriver->getError()]);
+        }
+        // 图片上传路径
+        $fileName = $StorageDriver->getFileName();
+        // 图片信息
+        $fileInfo = $StorageDriver->getFileInfo();
+        // 添加文件库记录
+        $uploadFile = $this->addUploadFile($fileName, $fileInfo, 'image');
+        // 图片上传成功
+        return json(['code' => 1, 'msg' => '图片上传成功', 'data' => $uploadFile->visible(['file_id'])]);
+    }
+
+    /**
+     * 添加文件库上传记录
+     * @param $fileName
+     * @param $fileInfo
+     * @param $fileType
+     * @return UploadFile
+     */
+    private function addUploadFile($fileName, $fileInfo, $fileType)
+    {
+        // 存储引擎
+        $storage = $this->config['default'];
+        // 存储域名
+        $fileUrl = isset($this->config['engine'][$storage]['domain'])
+            ? $this->config['engine'][$storage]['domain'] : '';
+        // 添加文件库记录
+        $model = new UploadFile;
+        $model->add([
+            'storage' => $storage,
+            'file_url' => $fileUrl,
+            'file_name' => $fileName,
+            'file_size' => $fileInfo['size'],
+            'file_type' => $fileType,
+            'extension' => pathinfo($fileInfo['name'], PATHINFO_EXTENSION),
+            'is_user' => 1
+        ]);
+        return $model;
+    }
+
+}

+ 51 - 0
dyu/application/api/controller/User.php

@@ -0,0 +1,51 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\api\model\User as UserModel;
+
+/**
+ * 用户管理
+ * Class User
+ * @package app\api
+ */
+class User extends Controller
+{
+    /**
+     * 用户自动登录
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\Exception
+     * @throws \think\exception\DbException
+     */
+    public function login()
+    {
+        $model = new UserModel;
+        return $this->renderSuccess([
+            'user_id' => $model->login($this->request->post()),
+            'token' => $model->getToken()
+        ]);
+    }
+
+    /**
+     * 当前用户详情
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function detail()
+    {
+        // 当前用户信息
+        $userInfo = $this->getUser();
+        return $this->renderSuccess(compact('userInfo'));
+    }
+
+}

+ 47 - 0
dyu/application/api/controller/Wxapp.php

@@ -0,0 +1,47 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller;
+
+use app\api\model\Wxapp as WxappModel;
+use app\api\model\WxappHelp;
+
+/**
+ * 微信小程序
+ * Class Wxapp
+ * @package app\api\controller
+ */
+class Wxapp extends Controller
+{
+    /**
+     * 小程序基础信息
+     * @return array
+     */
+    public function base()
+    {
+//        $wxapp = WxappModel::getWxappCache();
+        return $this->renderSuccess([]);
+    }
+
+    /**
+     * 帮助中心
+     * @return array
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function help()
+    {
+        $model = new WxappHelp;
+        $list = $model->getList();
+        return $this->renderSuccess(compact('list'));
+    }
+
+}

+ 36 - 0
dyu/application/api/controller/balance/Log.php

@@ -0,0 +1,36 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\balance;
+
+use app\api\controller\Controller;
+use app\api\model\user\BalanceLog as BalanceLogModel;
+
+/**
+ * 余额账单明细
+ * Class Log
+ * @package app\api\controller\balance
+ */
+class Log extends Controller
+{
+    /**
+     * 余额账单明细列表
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function lists()
+    {
+        $user = $this->getUser();
+        $list = (new BalanceLogModel)->getList($user['user_id']);
+        return $this->renderSuccess(compact('list'));
+    }
+
+}

+ 92 - 0
dyu/application/api/controller/bargain/Active.php

@@ -0,0 +1,92 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\bargain;
+
+use app\api\controller\Controller;
+use app\api\model\Goods as GoodsModel;
+use app\api\model\bargain\Active as ActiveModel;
+use app\api\model\bargain\Setting as SettingModel;
+use app\common\service\qrcode\bargain\Goods as GoodsPoster;
+
+/**
+ * 砍价活动管理
+ * Class Active
+ * @package app\api\controller\bargain
+ */
+class Active extends Controller
+{
+    /**
+     * 砍价活动会场列表
+     * @return array
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function lists()
+    {
+        // 获取砍价活动会场列表
+        $model = new ActiveModel;
+        $activeList = $model->getHallList();
+        return $this->renderSuccess(compact('activeList'));
+    }
+
+    /**
+     * 砍价活动详情
+     * @param $active_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function detail($active_id)
+    {
+        // 获取砍价活动详情
+        $model = new ActiveModel;
+        $active = $model->getDetail($active_id);
+        if ($active === false) {
+            return $this->renderError($model->getError());
+        }
+        // 标记当前用户是否正在参与
+        $task_id = $model->getWhetherPartake($active_id, $this->getUser(false));
+        $is_partake = $task_id > 0;
+        // 获取商品详情
+        $goods = GoodsModel::detail($active['goods_id']);
+        // 砍价规则
+        $setting = SettingModel::getBasic();
+        return $this->renderSuccess(compact('active', 'goods', 'setting', 'is_partake', 'task_id'));
+    }
+
+    /**
+     * 生成商品海报
+     * @param $active_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     * @throws \Exception
+     */
+    public function poster($active_id)
+    {
+        // 获取砍价活动详情
+        $model = new ActiveModel;
+        $active = $model->getDetail($active_id);
+        if ($active === false) {
+            return $this->renderError($model->getError());
+        }
+        // 获取商品详情
+        $goods = GoodsModel::detail($active['goods_id']);
+        // 生成商品海报图
+        $Qrcode = new GoodsPoster($active, $goods, $this->getUser(false));
+        return $this->renderSuccess([
+            'qrcode' => $Qrcode->getImage(),
+        ]);
+    }
+
+}

+ 109 - 0
dyu/application/api/controller/bargain/Order.php

@@ -0,0 +1,109 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\bargain;
+
+use app\api\controller\Controller;
+use app\api\model\bargain\Task as TaskModel;
+use app\api\model\bargain\Setting as SettingModel;
+use app\api\service\order\Checkout as CheckoutModel;
+use app\common\enum\order\OrderSource as OrderSourceEnum;
+
+class Order extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        // 用户信息
+        $this->user = $this->getUser();
+    }
+
+    /**
+     * 砍价订单结算
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \Exception
+     */
+    public function checkout()
+    {
+        // 实例化结算台服务
+        $Checkout = new CheckoutModel;
+        // 订单结算api参数
+        $params = $Checkout->setParam($this->getParam([
+            'task_id' => 0
+        ]));
+        // 获取砍价任务详情
+        $task = TaskModel::detail($params['task_id']);
+        // 获取砍价商品信息
+        $goodsList = $task->getTaskGoods($params['task_id']);
+        if ($goodsList === false) {
+            return $this->renderError($task->getError());
+        }
+        // 设置订单来源
+        $Checkout->setOrderSource([
+            'source' => OrderSourceEnum::BARGAIN,
+            'source_id' => $params['task_id'],
+        ]);
+        // 砍价商品不参与 等级折扣和优惠券折扣
+        $Checkout->setCheckoutRule([
+            'is_user_grade' => false,
+            'is_coupon' => false,
+            'is_use_points' => false,
+            'is_dealer' => SettingModel::getIsDealer(),
+        ]);
+        // 获取订单结算信息
+        $orderInfo = $Checkout->onCheckout($this->user, $goodsList);
+        if ($this->request->isGet()) {
+            return $this->renderSuccess($orderInfo);
+        }
+        // submit:订单结算提交
+        if ($Checkout->hasError()) {
+            return $this->renderError($Checkout->getError());
+        }
+        // 创建订单
+        if (!$Checkout->createOrder($orderInfo)) {
+            return $this->renderError($Checkout->getError() ?: '订单创建失败');
+        }
+        // 订单创建后将砍价任务结束
+        $task->setTaskEnd();
+        // 构建微信支付请求
+        $payment = $Checkout->onOrderPayment();
+        // 支付状态提醒
+        $message = ['success' => '支付成功', 'error' => '订单未支付'];
+        return $this->renderSuccess([
+            'order_id' => $Checkout->model['order_id'],   // 订单id
+            'pay_type' => $params['pay_type'],  // 支付方式
+            'payment' => $payment               // 微信支付参数
+        ], $message);
+    }
+
+    /**
+     * 订单结算提交的参数
+     * @param array $define
+     * @return array
+     */
+    private function getParam($define = [])
+    {
+        return array_merge($define, $this->request->param());
+    }
+
+}

+ 99 - 0
dyu/application/api/controller/bargain/Task.php

@@ -0,0 +1,99 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\bargain;
+
+use app\api\controller\Controller;
+use app\api\model\bargain\Task as TaskModel;
+use app\api\model\bargain\Setting as SettingModel;
+use app\common\library\Lock;
+
+class Task extends Controller
+{
+    /**
+     * 我的砍价列表
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function lists()
+    {
+        $model = new TaskModel;
+        $myList = $model->getMyList($this->getUser()['user_id']);
+        return $this->renderSuccess(compact('myList'));
+    }
+
+    /**
+     * 创建砍价任务
+     * @param $active_id
+     * @param $goods_sku_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function partake($active_id, $goods_sku_id)
+    {
+        // 用户信息
+        $user = $this->getUser();
+        // 创建砍价任务
+        $model = new TaskModel;
+        if (!$model->partake($user['user_id'], $active_id, $goods_sku_id)) {
+            return $this->renderError($model->getError() ?: '砍价任务创建失败');
+        }
+        return $this->renderSuccess([
+            'task_id' => $model['task_id']
+        ]);
+    }
+
+    /**
+     * 获取砍价任务详情
+     * @param $task_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function detail($task_id)
+    {
+        $model = new TaskModel;
+        $detail = $model->getTaskDetail($task_id, $this->getUser(false));
+        if ($detail === false) {
+            return $this->renderError($model->getError());
+        }
+        // 砍价规则
+        $setting = SettingModel::getBasic();
+        return $this->renderSuccess(array_merge($detail, ['setting' => $setting]));
+    }
+
+    /**
+     * 帮砍一刀
+     * @param $task_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function help_cut($task_id)
+    {
+        // 加阻塞锁, 防止并发
+        Lock::lockUp("bargain_help_cut_{$task_id}");
+        // 砍价任务详情
+        $model = TaskModel::detail($task_id);
+        // 砍一刀的金额
+        $cut_money = $model->getCutMoney();
+        // 帮砍一刀事件
+        $status = $model->helpCut($this->getUser());
+        // 解除并发锁
+        Lock::unLock("bargain_help_cut_{$task_id}");
+        if ($status == true) {
+            return $this->renderSuccess(compact('cut_money'), '砍价成功');
+        }
+        return $this->renderError($model->getError() ?: '砍价失败');
+    }
+
+}

+ 34 - 0
dyu/application/api/controller/live/Room.php

@@ -0,0 +1,34 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\live;
+
+use app\api\controller\Controller;
+use app\api\model\wxapp\LiveRoom as LiveRoomModel;
+
+/**
+ * 微信小程序直播列表
+ * Class Room
+ * @package app\api\controller\live
+ */
+class Room extends Controller
+{
+    /**
+     * 获取直播间列表
+     * @return mixed
+     * @throws \think\exception\DbException
+     */
+    public function lists()
+    {
+        $model = new LiveRoomModel;
+        $list = $model->getList();
+        return $this->renderSuccess(compact('list'));
+    }
+}

+ 36 - 0
dyu/application/api/controller/points/Log.php

@@ -0,0 +1,36 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\points;
+
+use app\api\controller\Controller;
+use app\api\model\user\PointsLog as PointsLogModel;
+
+/**
+ * 余额账单明细
+ * Class Log
+ * @package app\api\controller\balance
+ */
+class Log extends Controller
+{
+    /**
+     * 积分明细列表
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function index()
+    {
+        $user = $this->getUser();
+        $list = (new PointsLogModel)->getList($user['user_id']);
+        return $this->renderSuccess(compact('list'));
+    }
+
+}

+ 36 - 0
dyu/application/api/controller/recharge/Order.php

@@ -0,0 +1,36 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\recharge;
+
+use app\api\controller\Controller;
+use app\api\model\recharge\Order as OrderModel;
+
+/**
+ * 充值记录
+ * Class Order
+ * @package app\api\controller\user\balance
+ */
+class Order extends Controller
+{
+    /**
+     * 我的充值记录列表
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function lists()
+    {
+        $user = $this->getUser();
+        $list = (new OrderModel)->getList($user['user_id']);
+        return $this->renderSuccess(compact('list'));
+    }
+
+}

+ 46 - 0
dyu/application/api/controller/sharing/Active.php

@@ -0,0 +1,46 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\sharing;
+
+use app\api\controller\Controller;
+use app\api\model\sharing\Active as ActiveModel;
+use app\api\model\sharing\Goods as GoodsModel;
+
+/**
+ * 拼团拼单控制器
+ * Class Active
+ * @package app\api\controller\sharing
+ */
+class Active extends Controller
+{
+    /**
+     * 拼单详情
+     * @param $active_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function detail($active_id)
+    {
+        // 拼单详情
+        $detail = ActiveModel::detail($active_id);
+        if (!$detail) {
+            return $this->renderError('很抱歉,拼单不存在');
+        }
+        // 拼团商品详情
+        $model = new GoodsModel;
+        $goods = $model->getDetails($detail['goods_id'], $this->getUser(false));
+        // 更多拼团商品
+        $goodsList = $model->getList([], $this->getUser(false));
+        return $this->renderSuccess(compact('detail', 'goods', 'goodsList'));
+    }
+
+}

+ 76 - 0
dyu/application/api/controller/sharing/Comment.php

@@ -0,0 +1,76 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\sharing;
+
+use app\api\controller\Controller;
+use app\api\model\sharing\Order as OrderModel;
+use app\api\model\sharing\OrderGoods as OrderGoodsModel;
+use app\api\model\sharing\Comment as CommentModel;
+
+/**
+ * 拼团订单评价管理
+ * Class Comment
+ * @package app\api\controller\sharing
+ */
+class Comment extends Controller
+{
+    /**
+     * 待评价订单商品列表
+     * @param $order_id
+     * @return array
+     * @throws \Exception
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function order($order_id)
+    {
+        // 用户信息
+        $user = $this->getUser();
+        // 订单信息
+        $order = OrderModel::getUserOrderDetail($order_id, $user['user_id']);
+        // 验证订单是否已完成
+        $model = new CommentModel;
+        if (!$model->checkOrderAllowComment($order)) {
+            return $this->renderError($model->getError());
+        }
+        // 待评价商品列表
+        /* @var \think\Collection $goodsList */
+        $goodsList = OrderGoodsModel::getNotCommentGoodsList($order_id);
+        if ($goodsList->isEmpty()) {
+            return $this->renderError('该订单没有可评价的商品');
+        }
+        // 提交商品评价
+        if ($this->request->isPost()) {
+            $formData = $this->request->post('formData', '', null);
+            if ($model->addForOrder($order, $goodsList, $formData)) {
+                return $this->renderSuccess([], '评价发表成功');
+            }
+            return $this->renderError($model->getError() ?: '评价发表失败');
+        }
+        return $this->renderSuccess(compact('goodsList'));
+    }
+
+    /**
+     * 商品评价列表
+     * @param $goods_id
+     * @param int $scoreType
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function lists($goods_id, $scoreType = -1)
+    {
+        $model = new CommentModel;
+        $list = $model->getGoodsCommentList($goods_id, $scoreType);
+        $total = $model->getTotal($goods_id);
+        return $this->renderSuccess(compact('list', 'total'));
+    }
+
+}

+ 91 - 0
dyu/application/api/controller/sharing/Goods.php

@@ -0,0 +1,91 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\sharing;
+
+use app\api\controller\Controller;
+use app\api\model\sharing\Goods as GoodsModel;
+use app\common\service\qrcode\Goods as GoodsPoster;
+use app\api\model\sharing\Active as ActiveModel;
+
+/**
+ * 商品控制器
+ * Class Goods
+ * @package app\api\controller
+ */
+class Goods extends Controller
+{
+    /**
+     * 商品列表
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function lists()
+    {
+        // 整理请求的参数
+        $param = array_merge($this->request->param(), [
+            'status' => 10
+        ]);
+        // 获取列表数据
+        $model = new GoodsModel;
+        $list = $model->getList($param, $this->getUser(false));
+        return $this->renderSuccess(compact('list'));
+    }
+
+    /**
+     * 获取商品详情
+     * @param $goods_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function detail($goods_id)
+    {
+        // 商品详情
+        $model = new GoodsModel;
+        $goods = $model->getDetails($goods_id, $this->getUser(false));
+        if ($goods === false) {
+            return $this->renderError($model->getError() ?: '商品信息不存在');
+        }
+        // 多规格商品sku信息, todo: 已废弃 v1.1.25
+        $specData = $goods['spec_type'] == 20 ? $model->getManySpecData($goods['spec_rel'], $goods['sku']) : null;
+        // 当前进行中的拼单
+        $activeList = ActiveModel::getActivityListByGoods($goods_id, 2);
+        return $this->renderSuccess([
+            // 商品详情
+            'detail' => $goods,
+            // 当前进行中的拼单
+            'activeList' => $activeList,
+            // 多规格商品sku信息
+            'specData' => $specData,
+        ]);
+    }
+
+    /**
+     * 生成商品海报
+     * @param $goods_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     * @throws \Exception
+     */
+    public function poster($goods_id)
+    {
+        // 商品详情
+        $detail = GoodsModel::detail($goods_id);
+        // 生成推广二维码
+        $Qrcode = new GoodsPoster($detail, $this->getUser(false), 20);
+        return $this->renderSuccess([
+            'qrcode' => $Qrcode->getImage(),
+        ]);
+    }
+
+}

+ 34 - 0
dyu/application/api/controller/sharing/Index.php

@@ -0,0 +1,34 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\sharing;
+
+use app\api\controller\Controller;
+use app\api\model\sharing\Category as CategoryModel;
+
+/**
+ * 拼团首页控制器
+ * Class Active
+ * @package app\api\controller\sharing
+ */
+class Index extends Controller
+{
+    /**
+     * 拼团首页
+     * @return array
+     */
+    public function index()
+    {
+        // 拼团分类列表
+        $categoryList = CategoryModel::getCacheAll();
+        return $this->renderSuccess(compact('categoryList'));
+    }
+
+}

+ 250 - 0
dyu/application/api/controller/sharing/Order.php

@@ -0,0 +1,250 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\sharing;
+
+use app\api\controller\Controller;
+use app\api\model\Setting as SettingModel;
+use app\api\model\sharing\Order as OrderModel;
+use app\api\service\sharing\order\Checkout as CheckoutModel;
+use app\api\validate\sharing\order\Checkout as CheckoutValidate;
+
+use app\common\enum\OrderType as OrderTypeEnum;
+use app\common\enum\order\PayType as PayTypeEnum;
+use app\common\service\qrcode\Extract as ExtractQRcode;
+
+/**
+ * 拼团订单控制器
+ * Class Order
+ * @package app\api\controller
+ */
+class Order extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    /* @var CheckoutValidate $validate */
+    private $validate;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        // 用户信息
+        $this->user = $this->getUser();
+        // 验证类
+        $this->validate = new CheckoutValidate;
+    }
+
+    /**
+     * 订单结算台
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \Exception
+     */
+    public function checkout()
+    {
+        // 实例化结算台服务
+        $Checkout = new CheckoutModel;
+        // 订单结算api参数
+        $params = $Checkout->setParam($this->getParam([
+            'goods_id' => 0,
+            'goods_num' => 0,
+            'goods_sku_id' => '',
+        ]));
+        // 表单验证
+        if (!$this->validate->scene('buyNow')->check($params)) {
+            return $this->renderError($this->validate->getError());
+        }
+        // 立即购买:获取订单商品列表
+        $model = new OrderModel;
+        $goodsList = $model->getOrderGoodsListByNow($params);
+        // 获取订单确认信息
+        $orderInfo = $Checkout->onCheckout($this->user, $goodsList);
+        if ($this->request->isGet()) {
+            return $this->renderSuccess($orderInfo);
+        }
+        // 订单结算提交
+        if ($Checkout->hasError()) {
+            return $this->renderError($Checkout->getError());
+        }
+        // 创建订单
+        if (!$Checkout->createOrder($orderInfo)) {
+            return $this->renderError($Checkout->getError() ?: '订单创建失败');
+        }
+        // 构建微信支付请求
+        $payment = $model->onOrderPayment($this->user, $Checkout->model, $params['pay_type']);
+        // 返回结算信息
+        return $this->renderSuccess([
+            'order_id' => $Checkout->model['order_id'],   // 订单id
+            'pay_type' => $params['pay_type'],  // 支付方式
+            'payment' => $payment               // 微信支付参数
+        ], ['success' => '支付成功', 'error' => '订单未支付']);
+    }
+
+    /**
+     * 订单结算提交的参数
+     * @param array $define
+     * @return array
+     */
+    private function getParam($define = [])
+    {
+        return array_merge($define, $this->request->param());
+    }
+
+    /**
+     * 我的拼团订单列表
+     * @param $dataType
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function lists($dataType)
+    {
+        $model = new OrderModel;
+        $list = $model->getList($this->user['user_id'], $dataType);
+        return $this->renderSuccess(compact('list'));
+    }
+
+    /**
+     * 拼团订单详情信息
+     * @param $order_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     */
+    public function detail($order_id)
+    {
+        // 订单详情
+        $model = OrderModel::getUserOrderDetail($order_id, $this->user['user_id']);
+        // 该订单是否允许申请售后
+        $model['isAllowRefund'] = $model->isAllowRefund();
+        return $this->renderSuccess([
+            'order' => $model,  // 订单详情
+            'setting' => [
+                // 积分名称
+                'points_name' => SettingModel::getPointsName(),
+            ],
+        ]);
+    }
+
+    /**
+     * 获取物流信息
+     * @param $order_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     */
+    public function express($order_id)
+    {
+        // 订单信息
+        $order = OrderModel::getUserOrderDetail($order_id, $this->user['user_id']);
+        if (!$order['express_no']) {
+            return $this->renderError('没有物流信息');
+        }
+        // 获取物流信息
+        /* @var \app\store\model\Express $model */
+        $model = $order['express'];
+        $express = $model->dynamic($model['express_name'], $model['express_code'], $order['express_no']);
+        if ($express === false) {
+            return $this->renderError($model->getError());
+        }
+        return $this->renderSuccess(compact('express'));
+    }
+
+    /**
+     * 取消订单
+     * @param $order_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     */
+    public function cancel($order_id)
+    {
+        $model = OrderModel::getUserOrderDetail($order_id, $this->user['user_id']);
+        if ($model->cancel($this->user)) {
+            return $this->renderSuccess($model->getError() ?: '订单取消成功');
+        }
+        return $this->renderError($model->getError() ?: '订单取消失败');
+    }
+
+    /**
+     * 确认收货
+     * @param $order_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     */
+    public function receipt($order_id)
+    {
+        $model = OrderModel::getUserOrderDetail($order_id, $this->user['user_id']);
+        if ($model->receipt()) {
+            return $this->renderSuccess();
+        }
+        return $this->renderError($model->getError());
+    }
+
+    /**
+     * 立即支付
+     * @param int $order_id 订单id
+     * @param int $payType 支付方式
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\Exception
+     * @throws \think\exception\DbException
+     */
+    public function pay($order_id, $payType = PayTypeEnum::WECHAT)
+    {
+        // 订单详情
+        $model = OrderModel::getUserOrderDetail($order_id, $this->user['user_id']);
+        // 订单支付事件
+        if (!$model->onPay($payType)) {
+            return $this->renderError($model->getError() ?: '订单支付失败');
+        }
+        // 构建微信支付请求
+        $payment = $model->onOrderPayment($this->user, $model, $payType);
+        // 支付状态提醒
+        return $this->renderSuccess([
+            'order_id' => $model['order_id'],   // 订单id
+            'pay_type' => $payType,             // 支付方式
+            'payment' => $payment               // 微信支付参数
+        ], ['success' => '支付成功', 'error' => '订单未支付']);
+    }
+
+    /**
+     * 获取订单核销二维码
+     * @param $order_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function extractQrcode($order_id)
+    {
+        // 订单详情
+        $order = OrderModel::getUserOrderDetail($order_id, $this->user['user_id']);
+        // 判断是否为待核销订单
+        if (!$order->checkExtractOrder($order)) {
+            return $this->renderError($order->getError());
+        }
+        $Qrcode = new ExtractQRcode(
+            $this->wxapp_id,
+            $this->user,
+            $order_id,
+            OrderTypeEnum::SHARING
+        );
+        return $this->renderSuccess([
+            'qrcode' => $Qrcode->getImage(),
+        ]);
+    }
+
+}

+ 117 - 0
dyu/application/api/controller/sharing/Refund.php

@@ -0,0 +1,117 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\sharing;
+
+use app\api\controller\Controller;
+use app\api\model\Express as ExpressModel;
+use app\api\model\sharing\OrderGoods as OrderGoodsModel;
+use app\api\model\sharing\OrderRefund as OrderRefundModel;
+
+/**
+ * 拼团订单售后服务
+ * Class Refund
+ * @package app\api\controller\user\order
+ */
+class Refund extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->user = $this->getUser();   // 用户信息
+    }
+
+    /**
+     * 用户售后单列表
+     * @param int $state
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function lists($state = -1)
+    {
+        $model = new OrderRefundModel;
+        $list = $model->getList($this->user['user_id'], (int)$state);
+        return $this->renderSuccess(compact('list'));
+    }
+
+    /**
+     * 申请售后
+     * @param $order_goods_id
+     * @return array
+     * @throws \think\exception\DbException
+     * @throws \Exception
+     */
+    public function apply($order_goods_id)
+    {
+        // 订单商品详情
+        $goods = OrderGoodsModel::detail($order_goods_id);
+        if (isset($goods['refund']) && !empty($goods['refund'])) {
+            return $this->renderError('当前商品已申请售后');
+        }
+        if (!$this->request->isPost()) {
+            return $this->renderSuccess(['detail' => $goods]);
+        }
+        // 新增售后单记录
+        $model = new OrderRefundModel;
+        if ($model->apply($this->user, $goods, $this->request->post())) {
+            return $this->renderSuccess([], '提交成功');
+        }
+        return $this->renderError($model->getError() ?: '提交失败');
+    }
+
+    /**
+     * 售后单详情
+     * @param $order_refund_id
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function detail($order_refund_id)
+    {
+        // 售后单详情
+        $detail = OrderRefundModel::detail([
+            'user_id' => $this->user['user_id'],
+            'order_refund_id' => $order_refund_id
+        ]);
+        if (empty($detail)) {
+            return $this->renderError('售后单不存在');
+        }
+        // 物流公司列表
+        $expressList = ExpressModel::getAll();
+        return $this->renderSuccess(compact('detail', 'expressList'));
+    }
+
+    /**
+     * 用户发货
+     * @param $order_refund_id
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function delivery($order_refund_id)
+    {
+        // 售后单详情
+        $model = OrderRefundModel::detail([
+            'user_id' => $this->user['user_id'],
+            'order_refund_id' => $order_refund_id
+        ]);
+        if ($model->delivery($this->postData())) {
+            return $this->renderSuccess([], '操作成功');
+        }
+        return $this->renderError($model->getError() ?: '提交失败');
+    }
+
+}

+ 33 - 0
dyu/application/api/controller/sharing/Setting.php

@@ -0,0 +1,33 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\sharing;
+
+use app\api\controller\Controller;
+use app\api\model\sharing\Setting as SettingModel;
+
+/**
+ * 拼团设置控制器
+ * Class Setting
+ * @package app\api\controller\sharing
+ */
+class Setting extends Controller
+{
+    /**
+     * 获取所有设置
+     * @return array
+     */
+    public function getAll()
+    {
+        $basic = SettingModel::getItem('basic');
+        return $this->renderSuccess(['setting' => compact('basic')]);
+    }
+
+}

+ 78 - 0
dyu/application/api/controller/sharp/Goods.php

@@ -0,0 +1,78 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\sharp;
+
+use app\api\controller\Controller;
+use app\api\service\sharp\Active as ActiveService;
+use app\common\service\qrcode\sharp\Goods as GoodsPoster;
+
+/**
+ * 整点秒杀-商品管理
+ * Class Goods
+ * @package app\api\controller\sharp
+ */
+class Goods extends Controller
+{
+    /**
+     * 秒杀活动商品列表
+     * @param $active_time_id
+     * @return array
+     */
+    public function lists($active_time_id)
+    {
+        // 获取秒杀活动会场首页数据
+        $service = new ActiveService;
+        $list = $service->getGoodsListByActiveTimeId($active_time_id);
+        return $this->renderSuccess(compact('list'));
+    }
+
+    /**
+     * 获取活动商品详情
+     * @param $active_time_id
+     * @param $sharp_goods_id
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function detail($active_time_id, $sharp_goods_id)
+    {
+        // 获取秒杀活动商品详情
+        $service = new ActiveService;
+        $data = $service->getyActiveGoodsDetail($active_time_id, $sharp_goods_id);
+        if ($data === false) {
+            return $this->renderError($service->getError());
+        }
+        return $this->renderSuccess($data);
+    }
+
+    /**
+     * 生成商品海报
+     * @param $active_time_id
+     * @param $sharp_goods_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function poster($active_time_id, $sharp_goods_id)
+    {
+        // 获取秒杀活动商品详情
+        $service = new ActiveService;
+        $data = $service->getyActiveGoodsDetail($active_time_id, $sharp_goods_id);
+        if ($data === false) {
+            return $this->renderError($service->getError());
+        }
+        // 生成商品海报图
+        $Qrcode = new GoodsPoster($data['active'], $data['goods'], $this->getUser(false));
+        return $this->renderSuccess([
+            'qrcode' => $Qrcode->getImage(),
+        ]);
+    }
+
+}

+ 40 - 0
dyu/application/api/controller/sharp/Index.php

@@ -0,0 +1,40 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\sharp;
+
+use app\api\controller\Controller;
+use app\api\service\sharp\Active as ActiveService;
+
+/**
+ * 整点秒杀-秒杀首页
+ * Class index
+ * @package app\api\controller\sharp
+ */
+class Index extends Controller
+{
+    /**
+     * 秒杀活动首页
+     * @return array
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function index()
+    {
+        // 获取秒杀活动会场首页数据
+        $service = new ActiveService;
+        $data = $service->getHallIndex();
+        if (empty($data['tabbar'])) {
+            return $this->renderError('很抱歉,暂无秒杀活动');
+        }
+        return $this->renderSuccess($data);
+    }
+}

+ 122 - 0
dyu/application/api/controller/sharp/Order.php

@@ -0,0 +1,122 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\sharp;
+
+use app\api\controller\Controller;
+use app\api\model\sharp\Setting as SettingModel;
+use app\api\service\order\Checkout as CheckoutModel;
+use app\api\service\sharp\Active as ActiveService;
+use app\common\enum\order\OrderSource as OrderSourceEnum;
+use app\common\library\Lock;
+
+class Order extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        // 用户信息
+        $this->user = $this->getUser();
+    }
+
+    /**
+     * 秒杀订单结算
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \Exception
+     */
+    public function checkout()
+    {
+        // 实例化结算台服务
+        $Checkout = new CheckoutModel;
+        // 订单结算api参数
+        $params = $Checkout->setParam($this->getParam([
+            'active_time_id' => 0,
+            'sharp_goods_id' => 0,
+            'goods_sku_id' => '',
+            'goods_num' => 0,
+        ]));
+        // 设置并发锁
+        $lockId = "sharp_order_{$params['active_time_id']}_{$params['sharp_goods_id']}";
+        Lock::lockUp($lockId);
+        // 获取秒杀商品信息
+        $service = new ActiveService;
+        $goodsList = $service->getCheckoutGoodsList(
+            $params['active_time_id'],
+            $params['sharp_goods_id'],
+            $params['goods_sku_id'],
+            $params['goods_num']
+        );
+        if ($goodsList === false) {
+            Lock::unLock($lockId);
+            return $this->renderError($service->getError());
+        }
+        // 设置订单来源
+        $Checkout->setOrderSource([
+            'source' => OrderSourceEnum::SHARP,
+            'source_id' => $params['active_time_id'],
+        ])
+            // 秒杀商品不参与 等级折扣和优惠券折扣
+            ->setCheckoutRule([
+                'is_user_grade' => false,
+                'is_coupon' => false,
+                'is_use_points' => false,
+                'is_dealer' => SettingModel::getIsDealer(),
+            ]);
+        // 获取订单结算信息
+        $orderInfo = $Checkout->onCheckout($this->user, $goodsList);
+        if ($this->request->isGet()) {
+            Lock::unLock($lockId);
+            return $this->renderSuccess($orderInfo);
+        }
+        // submit:订单结算提交
+        if ($Checkout->hasError()) {
+            Lock::unLock($lockId);
+            return $this->renderError($Checkout->getError());
+        }
+        // 创建订单
+        if (!$Checkout->createOrder($orderInfo)) {
+            Lock::unLock($lockId);
+            return $this->renderError($Checkout->getError() ?: '订单创建失败');
+        }
+        Lock::unLock($lockId);
+        // 构建微信支付请求
+        $payment = $Checkout->onOrderPayment();
+        // 支付状态提醒
+        return $this->renderSuccess([
+            'order_id' => $Checkout->model['order_id'],   // 订单id
+            'pay_type' => $params['pay_type'],  // 支付方式
+            'payment' => $payment               // 微信支付参数
+        ], ['success' => '支付成功', 'error' => '订单未支付']);
+    }
+
+    /**
+     * 订单结算提交的参数
+     * @param array $define
+     * @return array
+     */
+    private function getParam($define = [])
+    {
+        return array_merge($define, $this->request->param());
+    }
+
+}

+ 88 - 0
dyu/application/api/controller/shop/Order.php

@@ -0,0 +1,88 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\shop;
+
+use app\api\controller\Controller;
+use app\api\model\Setting as SettingModel;
+use app\common\service\Order as OrderService;
+use app\common\enum\OrderType as OrderTypeEnum;
+use app\api\model\store\shop\Clerk as ClerkModel;
+
+/**
+ * 自提订单管理
+ * Class Order
+ * @package app\api\controller\shop
+ */
+class Order extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->user = $this->getUser();   // 用户信息
+    }
+
+    /**
+     * 核销订单详情
+     * @param $order_id
+     * @param int $order_type
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function detail($order_id, $order_type = OrderTypeEnum::MASTER)
+    {
+        // 订单详情
+        $model = OrderService::getOrderDetail($order_id, $order_type);
+        // 验证是否为该门店的核销员
+        $clerkModel = ClerkModel::detail(['user_id' => $this->user['user_id']]);
+        return $this->renderSuccess([
+            'order' => $model,  // 订单详情
+            'clerkModel' => $clerkModel,
+            'setting' => [
+                // 积分名称
+                'points_name' => SettingModel::getPointsName(),
+            ],
+        ]);
+    }
+
+    /**
+     * 确认核销
+     * @param $order_id
+     * @param int $order_type
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function extract($order_id, $order_type = OrderTypeEnum::MASTER)
+    {
+        // 订单详情
+        $order = OrderService::getOrderDetail($order_id, $order_type);
+        // 验证是否为该门店的核销员
+        $ClerkModel = ClerkModel::detail(['user_id' => $this->user['user_id']]);
+        if (!$ClerkModel->checkUser($order['extract_shop_id'])) {
+            return $this->renderError($ClerkModel->getError());
+        }
+        // 确认核销
+        if ($order->verificationOrder($ClerkModel['clerk_id'])) {
+            return $this->renderSuccess([], '订单核销成功');
+        }
+        return $this->renderError($order->getError() ?: '核销失败');
+    }
+
+}

+ 61 - 0
dyu/application/api/controller/user/Comment.php

@@ -0,0 +1,61 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\user;
+
+use app\api\controller\Controller;
+use app\api\model\Order as OrderModel;
+use app\api\model\OrderGoods as OrderGoodsModel;
+use app\api\model\Comment as CommentModel;
+
+/**
+ * 订单评价管理
+ * Class Comment
+ * @package app\api\controller\user
+ */
+class Comment extends Controller
+{
+    /**
+     * 待评价订单商品列表
+     * @param $order_id
+     * @return array
+     * @throws \Exception
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function order($order_id)
+    {
+        // 用户信息
+        $user = $this->getUser();
+        // 订单信息
+        $order = OrderModel::getUserOrderDetail($order_id, $user['user_id']);
+        // 验证订单是否已完成
+        $model = new CommentModel;
+        if (!$model->checkOrderAllowComment($order)) {
+            return $this->renderError($model->getError());
+        }
+        // 待评价商品列表
+        /* @var \think\Collection $goodsList */
+        $goodsList = OrderGoodsModel::getNotCommentGoodsList($order_id);
+        if ($goodsList->isEmpty()) {
+            return $this->renderError('该订单没有可评价的商品');
+        }
+        // 提交商品评价
+        if ($this->request->isPost()) {
+            $post = $this->request->post('formData');
+            if ($model->addForOrder($order, $goodsList, $post)) {
+                return $this->renderSuccess([], '评价发表成功');
+            }
+            return $this->renderError($model->getError() ?: '评价发表失败');
+        }
+        return $this->renderSuccess(compact('goodsList'));
+    }
+
+}

+ 82 - 0
dyu/application/api/controller/user/Coupon.php

@@ -0,0 +1,82 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\user;
+
+use app\api\controller\Controller;
+use app\api\model\UserCoupon as UserCouponModel;
+
+/**
+ * 用户优惠券
+ * Class Coupon
+ * @package app\api\controller
+ */
+class Coupon extends Controller
+{
+    /* @var UserCouponModel $model */
+    private $model;
+
+    /* @var \app\api\model\User $model */
+    private $user;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = new UserCouponModel;
+        $this->user = $this->getUser();
+    }
+
+    /**
+     * 优惠券列表
+     * @param string $data_type
+     * @return array
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function lists($data_type = 'all')
+    {
+        $is_use = false;
+        $is_expire = false;
+        switch ($data_type) {
+            case 'not_use':
+                $is_use = false;
+                break;
+            case 'is_use':
+                $is_use = true;
+                break;
+            case 'is_expire':
+                $is_expire = true;
+                break;
+        }
+        $list = $this->model->getList($this->user['user_id'], $is_use, $is_expire);
+        return $this->renderSuccess(compact('list'));
+    }
+
+    /**
+     * 领取优惠券
+     * @param $coupon_id
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function receive($coupon_id)
+    {
+        if ($this->model->receive($this->user, $coupon_id)) {
+            return $this->renderSuccess([], '领取成功');
+        }
+        return $this->renderError($this->model->getError() ?: '添加失败');
+    }
+
+}

+ 123 - 0
dyu/application/api/controller/user/Dealer.php

@@ -0,0 +1,123 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\user;
+
+use app\api\controller\Controller;
+use app\api\model\dealer\Setting;
+use app\api\model\dealer\User as DealerUserModel;
+use app\api\model\dealer\Apply as DealerApplyModel;
+
+/**
+ * 分销中心
+ * Class Dealer
+ * @package app\api\controller\user
+ */
+class Dealer extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    private $dealer;
+    private $setting;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        // 用户信息
+        $this->user = $this->getUser();
+        // 分销商用户信息
+        $this->dealer = DealerUserModel::detail($this->user['user_id']);
+        // 分销商设置
+        $this->setting = Setting::getAll();
+    }
+
+    /**
+     * 分销商中心
+     * @return array
+     */
+    public function center()
+    {
+        return $this->renderSuccess([
+            // 当前是否为分销商
+            'is_dealer' => $this->isDealerUser(),
+            // 当前用户信息
+            'user' => $this->user,
+            // 分销商用户信息
+            'dealer' => $this->dealer,
+            // 背景图
+            'background' => $this->setting['background']['values']['index'],
+            // 页面文字
+            'words' => $this->setting['words']['values'],
+        ]);
+    }
+
+    /**
+     * 分销商申请状态
+     * @param null $referee_id
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function apply($referee_id = null)
+    {
+        // 推荐人昵称
+        $referee_name = '平台';
+        if ($referee_id > 0 && ($referee = DealerUserModel::detail($referee_id))) {
+            $referee_name = $referee['user']['nickName'];
+        }
+        return $this->renderSuccess([
+            // 当前是否为分销商
+            'is_dealer' => $this->isDealerUser(),
+            // 当前是否在申请中
+            'is_applying' => DealerApplyModel::isApplying($this->user['user_id']),
+            // 推荐人昵称
+            'referee_name' => $referee_name,
+            // 背景图
+            'background' => $this->setting['background']['values']['apply'],
+            // 页面文字
+            'words' => $this->setting['words']['values'],
+            // 申请协议
+            'license' => $this->setting['license']['values']['license'],
+        ]);
+    }
+
+    /**
+     * 分销商提现信息
+     * @return array
+     */
+    public function withdraw()
+    {
+        return $this->renderSuccess([
+            // 分销商用户信息
+            'dealer' => $this->dealer,
+            // 结算设置
+            'settlement' => $this->setting['settlement']['values'],
+            // 背景图
+            'background' => $this->setting['background']['values']['withdraw_apply'],
+            // 页面文字
+            'words' => $this->setting['words']['values'],
+        ]);
+    }
+
+    /**
+     * 当前用户是否为分销商
+     * @return bool
+     */
+    private function isDealerUser()
+    {
+        return !!$this->dealer && !$this->dealer['is_delete'];
+    }
+
+}

+ 52 - 0
dyu/application/api/controller/user/Index.php

@@ -0,0 +1,52 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\user;
+
+use app\api\controller\Controller;
+use app\api\model\User as UserModel;
+use app\api\model\Order as OrderModel;
+use app\api\model\Setting as SettingModel;
+
+/**
+ * 个人中心主页
+ * Class Index
+ * @package app\api\controller\user
+ */
+class Index extends Controller
+{
+    /**
+     * 获取当前用户信息
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\Exception
+     * @throws \think\exception\DbException
+     */
+    public function detail()
+    {
+        // 当前用户信息
+        $user = $this->getUser(false);
+        // 订单总数
+        $model = new OrderModel;
+        return $this->renderSuccess([
+            'userInfo' => $user,
+            'orderCount' => [
+                'payment' => $model->getCount($user, 'payment'),
+                'received' => $model->getCount($user, 'received'),
+                'comment' => $model->getCount($user, 'comment'),
+            ],
+            'setting' => [
+                'points_name' => SettingModel::getPointsName(),
+            ],
+            'menus' => (new UserModel)->getMenus()   // 个人中心菜单列表
+        ]);
+    }
+
+}

+ 187 - 0
dyu/application/api/controller/user/Order.php

@@ -0,0 +1,187 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\user;
+
+use app\api\controller\Controller;
+
+use app\api\model\Order as OrderModel;
+use app\api\model\Setting as SettingModel;
+use app\common\enum\OrderType as OrderTypeEnum;
+use app\common\enum\order\PayType as PayTypeEnum;
+use app\common\service\qrcode\Extract as ExtractQRcode;
+
+/**
+ * 用户订单管理
+ * Class Order
+ * @package app\api\controller\user
+ */
+class Order extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->user = $this->getUser();   // 用户信息
+    }
+
+    /**
+     * 我的订单列表
+     * @param $dataType
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function lists($dataType)
+    {
+        $model = new OrderModel;
+        $list = $model->getList($this->user['user_id'], $dataType);
+        return $this->renderSuccess(compact('list'));
+    }
+
+    /**
+     * 订单详情信息
+     * @param $order_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function detail($order_id)
+    {
+        // 订单详情
+        $model = OrderModel::getUserOrderDetail($order_id, $this->user['user_id']);
+        // 该订单是否允许申请售后
+        $model['isAllowRefund'] = $model->isAllowRefund();
+        return $this->renderSuccess([
+            'order' => $model,  // 订单详情
+            'setting' => [
+                // 积分名称
+                'points_name' => SettingModel::getPointsName(),
+            ],
+        ]);
+    }
+
+    /**
+     * 获取物流信息
+     * @param $order_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function express($order_id)
+    {
+        // 订单信息
+        $order = OrderModel::getUserOrderDetail($order_id, $this->user['user_id']);
+        if (!$order['express_no']) {
+            return $this->renderError('没有物流信息');
+        }
+        // 获取物流信息
+        /* @var \app\store\model\Express $model */
+        $model = $order['express'];
+        $express = $model->dynamic($model['express_name'], $model['express_code'], $order['express_no']);
+        if ($express === false) {
+            return $this->renderError($model->getError());
+        }
+        return $this->renderSuccess(compact('express'));
+    }
+
+    /**
+     * 取消订单
+     * @param $order_id
+     * @return array
+     * @throws \Exception
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function cancel($order_id)
+    {
+        $model = OrderModel::getUserOrderDetail($order_id, $this->user['user_id']);
+        if ($model->cancel($this->user)) {
+            return $this->renderSuccess($model->getError() ?: '订单取消成功');
+        }
+        return $this->renderError($model->getError() ?: '订单取消失败');
+    }
+
+    /**
+     * 确认收货
+     * @param $order_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function receipt($order_id)
+    {
+        $model = OrderModel::getUserOrderDetail($order_id, $this->user['user_id']);
+        if ($model->receipt()) {
+            return $this->renderSuccess();
+        }
+        return $this->renderError($model->getError());
+    }
+
+    /**
+     * 立即支付
+     * @param int $order_id 订单id
+     * @param int $payType 支付方式
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\Exception
+     * @throws \think\exception\DbException
+     */
+    public function pay($order_id, $payType = PayTypeEnum::WECHAT)
+    {
+        // 获取订单详情
+        $model = OrderModel::getUserOrderDetail($order_id, $this->user['user_id']);
+        // 订单支付事件
+        if (!$model->onPay($payType)) {
+            return $this->renderError($model->getError() ?: '订单支付失败');
+        }
+        // 构建微信支付请求
+        $payment = $model->onOrderPayment($this->user, $model, $payType);
+        // 支付状态提醒
+        return $this->renderSuccess([
+            'order_id' => $model['order_id'],   // 订单id
+            'pay_type' => $payType,             // 支付方式
+            'payment' => $payment               // 微信支付参数
+        ], ['success' => '支付成功', 'error' => '订单未支付']);
+    }
+
+    /**
+     * 获取订单核销二维码
+     * @param $order_id
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function extractQrcode($order_id)
+    {
+        // 订单详情
+        $order = OrderModel::getUserOrderDetail($order_id, $this->user['user_id']);
+        // 判断是否为待核销订单
+        if (!$order->checkExtractOrder($order)) {
+            return $this->renderError($order->getError());
+        }
+        $Qrcode = new ExtractQRcode(
+            $this->wxapp_id,
+            $this->user,
+            $order_id,
+            OrderTypeEnum::MASTER
+        );
+        return $this->renderSuccess([
+            'qrcode' => $Qrcode->getImage(),
+        ]);
+    }
+
+}

+ 117 - 0
dyu/application/api/controller/user/Refund.php

@@ -0,0 +1,117 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\user;
+
+use app\api\controller\Controller;
+use app\api\model\Express as ExpressModel;
+use app\api\model\OrderGoods as OrderGoodsModel;
+use app\api\model\OrderRefund as OrderRefundModel;
+
+/**
+ * 订单售后服务
+ * Class service
+ * @package app\api\controller\user\order
+ */
+class Refund extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->user = $this->getUser();   // 用户信息
+    }
+
+    /**
+     * 用户售后单列表
+     * @param int $state
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function lists($state = -1)
+    {
+        $model = new OrderRefundModel;
+        $list = $model->getList($this->user['user_id'], (int)$state);
+        return $this->renderSuccess(compact('list'));
+    }
+
+    /**
+     * 申请售后
+     * @param $order_goods_id
+     * @return array
+     * @throws \think\exception\DbException
+     * @throws \Exception
+     */
+    public function apply($order_goods_id)
+    {
+        // 订单商品详情
+        $goods = OrderGoodsModel::detail($order_goods_id);
+        if (isset($goods['refund']) && !empty($goods['refund'])) {
+            return $this->renderError('当前商品已申请售后');
+        }
+        if (!$this->request->isPost()) {
+            return $this->renderSuccess(['detail' => $goods]);
+        }
+        // 新增售后单记录
+        $model = new OrderRefundModel;
+        if ($model->apply($this->user, $goods, $this->request->post())) {
+            return $this->renderSuccess([], '提交成功');
+        }
+        return $this->renderError($model->getError() ?: '提交失败');
+    }
+
+    /**
+     * 售后单详情
+     * @param $order_refund_id
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function detail($order_refund_id)
+    {
+        // 售后单详情
+        $detail = OrderRefundModel::detail([
+            'user_id' => $this->user['user_id'],
+            'order_refund_id' => $order_refund_id
+        ]);
+        if (empty($detail)) {
+            return $this->renderError('售后单不存在');
+        }
+        // 物流公司列表
+        $expressList = ExpressModel::getAll();
+        return $this->renderSuccess(compact('detail', 'expressList'));
+    }
+
+    /**
+     * 用户发货
+     * @param $order_refund_id
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function delivery($order_refund_id)
+    {
+        // 售后单详情
+        $model = OrderRefundModel::detail([
+            'user_id' => $this->user['user_id'],
+            'order_refund_id' => $order_refund_id
+        ]);
+        if ($model->delivery($this->postData())) {
+            return $this->renderSuccess([], '操作成功');
+        }
+        return $this->renderError($model->getError() ?: '提交失败');
+    }
+
+}

+ 52 - 0
dyu/application/api/controller/user/Wallet.php

@@ -0,0 +1,52 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\user;
+
+use app\api\controller\Controller;
+use app\api\model\Setting as SettingModel;
+
+class Wallet extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->user = $this->getUser();   // 用户信息
+    }
+
+    /**
+     * 我的钱包信息
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function index()
+    {
+        // 当前用户信息
+        $user = $this->getUser();
+        // 获取充值设置
+        $setting = SettingModel::getItem('recharge');
+        return $this->renderSuccess([
+            'userInfo' => $user,
+            'setting' => [
+                'is_entrance' => (bool)$setting['is_entrance']
+            ]
+        ]);
+    }
+
+}

+ 54 - 0
dyu/application/api/controller/user/dealer/Apply.php

@@ -0,0 +1,54 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\user\dealer;
+
+use app\api\controller\Controller;
+use app\api\model\dealer\Apply as DealerApplyModel;
+
+/**
+ * 分销商申请
+ * Class Apply
+ * @package app\api\controller\user\dealer
+ */
+class Apply extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->user = $this->getUser();   // 用户信息
+    }
+
+    /**
+     * 提交分销商申请
+     * @param string $name
+     * @param string $mobile
+     * @return array
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function submit($name = '', $mobile = '')
+    {
+        $model = new DealerApplyModel;
+        if ($model->submit($this->user, $name, $mobile)) {
+            return $this->renderSuccess();
+        }
+        return $this->renderError($model->getError() ?: '提交失败');
+    }
+
+}

+ 64 - 0
dyu/application/api/controller/user/dealer/Order.php

@@ -0,0 +1,64 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\user\dealer;
+
+use app\api\controller\Controller;
+use app\api\model\dealer\Setting;
+use app\api\model\dealer\User as DealerUserModel;
+use app\api\model\dealer\Order as OrderModel;
+
+/**
+ * 分销商订单
+ * Class Order
+ * @package app\api\controller\user\dealer
+ */
+class Order extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    private $dealer;
+    private $setting;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        // 用户信息
+        $this->user = $this->getUser();
+        // 分销商用户信息
+        $this->dealer = DealerUserModel::detail($this->user['user_id']);
+        // 分销商设置
+        $this->setting = Setting::getAll();
+    }
+
+    /**
+     * 分销商订单列表
+     * @param int $settled
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function lists($settled = -1)
+    {
+        $model = new OrderModel;
+        return $this->renderSuccess([
+            // 提现明细列表
+            'list' => $model->getList($this->user['user_id'], (int)$settled),
+            // 页面文字
+            'words' => $this->setting['words']['values'],
+        ]);
+    }
+
+}

+ 65 - 0
dyu/application/api/controller/user/dealer/Qrcode.php

@@ -0,0 +1,65 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\user\dealer;
+
+use app\api\controller\Controller;
+use app\api\model\dealer\Setting;
+use app\api\model\dealer\User as DealerUserModel;
+use app\common\service\qrcode\Poster;
+
+/**
+ * 推广二维码
+ * Class Order
+ * @package app\api\controller\user\dealer
+ */
+class Qrcode extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    private $dealer;
+    private $setting;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        // 用户信息
+        $this->user = $this->getUser();
+        // 分销商用户信息
+        $this->dealer = DealerUserModel::detail($this->user['user_id']);
+        // 分销商设置
+        $this->setting = Setting::getAll();
+    }
+
+    /**
+     * 获取推广二维码
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     * @throws \Exception
+     */
+    public function poster()
+    {
+        $Qrcode = new Poster($this->dealer);
+        return $this->renderSuccess([
+            // 二维码图片地址
+            'qrcode' => $Qrcode->getImage(),
+            // 页面文字
+            'words' => $this->setting['words']['values'],
+        ]);
+    }
+
+}

+ 68 - 0
dyu/application/api/controller/user/dealer/Team.php

@@ -0,0 +1,68 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\user\dealer;
+
+use app\api\controller\Controller;
+use app\api\model\dealer\Setting;
+use app\api\model\dealer\User as DealerUserModel;
+use app\api\model\dealer\Referee as RefereeModel;
+
+/**
+ * 我的团队
+ * Class Order
+ * @package app\api\controller\user\dealer
+ */
+class Team extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    private $dealer;
+    private $setting;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        // 用户信息
+        $this->user = $this->getUser();
+        // 分销商用户信息
+        $this->dealer = DealerUserModel::detail($this->user['user_id']);
+        // 分销商设置
+        $this->setting = Setting::getAll();
+    }
+
+    /**
+     * 我的团队列表
+     * @param int $level
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function lists($level = -1)
+    {
+        $model = new RefereeModel;
+        return $this->renderSuccess([
+            // 分销商用户信息
+            'dealer' => $this->dealer,
+            // 我的团队列表
+            'list' => $model->getList($this->user['user_id'], (int)$level),
+            // 基础设置
+            'setting' => $this->setting['basic']['values'],
+            // 页面文字
+            'words' => $this->setting['words']['values'],
+        ]);
+    }
+
+}

+ 80 - 0
dyu/application/api/controller/user/dealer/Withdraw.php

@@ -0,0 +1,80 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\user\dealer;
+
+use app\api\controller\Controller;
+use app\api\model\dealer\Setting;
+use app\api\model\dealer\User as DealerUserModel;
+use app\api\model\dealer\Withdraw as WithdrawModel;
+
+/**
+ * 分销商提现
+ * Class Withdraw
+ * @package app\api\controller\user\dealer
+ */
+class Withdraw extends Controller
+{
+    /* @var \app\api\model\User $user */
+    private $user;
+
+    private $dealer;
+    private $setting;
+
+    /**
+     * 构造方法
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function _initialize()
+    {
+        parent::_initialize();
+        // 用户信息
+        $this->user = $this->getUser();
+        // 分销商用户信息
+        $this->dealer = DealerUserModel::detail($this->user['user_id']);
+        // 分销商设置
+        $this->setting = Setting::getAll();
+    }
+
+    /**
+     * 提交提现申请
+     * @param $data
+     * @return array
+     * @throws \app\common\exception\BaseException
+     */
+    public function submit($data)
+    {
+        $formData = json_decode(htmlspecialchars_decode($data), true);
+        $model = new WithdrawModel;
+        if ($model->submit($this->dealer, $formData)) {
+            return $this->renderSuccess([], '申请提现成功');
+        }
+        return $this->renderError($model->getError() ?: '提交失败');
+    }
+
+    /**
+     * 分销商提现明细
+     * @param int $status
+     * @return array
+     * @throws \think\exception\DbException
+     */
+    public function lists($status = -1)
+    {
+        $model = new WithdrawModel;
+        return $this->renderSuccess([
+            // 提现明细列表
+            'list' => $model->getList($this->user['user_id'], (int)$status),
+            // 页面文字
+            'words' => $this->setting['words']['values'],
+        ]);
+    }
+
+}

+ 41 - 0
dyu/application/api/controller/wxapp/Formid.php

@@ -0,0 +1,41 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\controller\wxapp;
+
+use app\api\controller\Controller;
+use app\api\model\wxapp\Formid as FormidModel;
+
+/**
+ * form_id 管理
+ * Class Formid
+ * @package app\api\controller\wxapp
+ */
+class Formid extends Controller
+{
+    /**
+     * 新增form_id
+     * @param $formId
+     * @return array
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function save($formId)
+    {
+        if (!$user = $this->getUser(false)) {
+            return $this->renderSuccess();
+        }
+        if (FormidModel::add($user['user_id'], $formId)) {
+            return $this->renderSuccess();
+        }
+        return $this->renderError();
+    }
+
+}

+ 96 - 0
dyu/application/api/model/Article.php

@@ -0,0 +1,96 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\exception\BaseException;
+use app\common\model\Article as ArticleModel;
+
+/**
+ * 商品评价模型
+ * Class Article
+ * @package app\api\model
+ */
+class Article extends ArticleModel
+{
+    /**
+     * 追加字段
+     * @var array
+     */
+    protected $append = [
+        'show_views',
+        'view_time'
+    ];
+
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'is_delete',
+        'wxapp_id',
+        'create_time',
+        'update_time'
+    ];
+
+    /**
+     * 文章详情:HTML实体转换回普通字符
+     * @param $value
+     * @return string
+     */
+    public function getArticleContentAttr($value)
+    {
+        return htmlspecialchars_decode($value);
+    }
+
+    public function getViewTimeAttr($value, $data)
+    {
+        return date('Y-m-d', $data['create_time']);
+    }
+
+    /**
+     * 文章详情
+     * @param $article_id
+     * @return ArticleModel|null
+     * @throws BaseException
+     * @throws \think\Exception
+     * @throws \think\exception\DbException
+     */
+    public static function detail($article_id)
+    {
+        if (!$model = parent::detail($article_id)) {
+            throw new BaseException(['msg' => '文章不存在']);
+        }
+        // 累积阅读数
+        $model->setInc('actual_views', 1);
+        return $model;
+    }
+
+    /**
+     * 获取文章列表
+     * @param int $category_id
+     * @param int $limit
+     * @return \think\Paginator
+     * @throws \think\exception\DbException
+     */
+    public function getList($category_id = 0, $limit = 15)
+    {
+        $category_id > 0 && $this->where('category_id', '=', $category_id);
+        return $this->field(['article_content'], true)
+            ->with(['image', 'category'])
+            ->where('article_status', '=', 1)
+            ->where('is_delete', '=', 0)
+            ->order(['article_sort' => 'asc', 'create_time' => 'desc'])
+            ->paginate($limit, false, [
+                'query' => \request()->request()
+            ]);
+    }
+
+}

+ 300 - 0
dyu/application/api/model/Cart.php

@@ -0,0 +1,300 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use think\Cache;
+use app\api\model\Goods as GoodsModel;
+
+use app\common\library\helper;
+use app\common\service\wechat\wow\Shoping as WowService;
+
+/**
+ * 购物车管理
+ * Class Cart
+ * @package app\api\model
+ */
+class Cart
+{
+    /* @var string $error 错误信息 */
+    public $error = '';
+
+    /* @var \think\Model|\think\Collection $user 用户信息 */
+    private $user;
+
+    /* @var int $user_id 用户id */
+    private $user_id;
+
+    /* @var int $wxapp_id 小程序商城id */
+    private $wxapp_id;
+
+    /* @var array $cart 购物车列表 */
+    private $cart = [];
+
+    /* @var bool $clear 是否清空购物车 */
+    private $clear = false;
+
+    /**
+     * 构造方法
+     * Cart constructor.
+     * @param \think\Model|\think\Collection $user
+     */
+    public function __construct($user)
+    {
+        $this->user = $user;
+        $this->user_id = $this->user['user_id'];
+        $this->wxapp_id = $this->user['wxapp_id'];
+        $this->cart = Cache::get('cart_' . $this->user_id) ?: [];
+    }
+
+    /**
+     * 购物车列表 (含商品信息)
+     * @return array
+     * @param string $cartIds 请求参数
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function getList($cartIds)
+    {
+        // 获取购物车商品列表
+        return $this->getOrderGoodsList($cartIds);
+    }
+
+    /**
+     * 获取购物车列表
+     * @param string|null $cartIds 购物车索引集 (为null时则获取全部)
+     * @return array
+     */
+    public function getCartList($cartIds = null)
+    {
+        if (empty($cartIds)) return $this->cart;
+        $cartList = [];
+        $indexArr = (strpos($cartIds, ',') !== false) ? explode(',', $cartIds) : [$cartIds];
+        foreach ($indexArr as $index) {
+            isset($this->cart[$index]) && $cartList[$index] = $this->cart[$index];
+        }
+        return $cartList;
+    }
+
+    /**
+     * 获取购物车中的商品列表
+     * @param $cartIds
+     * @return array|bool
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    private function getOrderGoodsList($cartIds)
+    {
+        // 购物车商品列表
+        $goodsList = [];
+        // 获取购物车列表
+        $cartList = $this->getCartList($cartIds);
+        if (empty($cartList)) {
+            $this->setError('当前购物车没有商品');
+            return $goodsList;
+        }
+        // 购物车中所有商品id集
+        $goodsIds = array_unique(helper::getArrayColumn($cartList, 'goods_id'));
+        // 获取并格式化商品数据
+        $sourceData = (new GoodsModel)->getListByIds($goodsIds);
+        $sourceData = helper::arrayColumn2Key($sourceData, 'goods_id');
+        // 格式化购物车数据列表
+        foreach ($cartList as $key => $item) {
+            // 判断商品不存在则自动删除
+            if (!isset($sourceData[$item['goods_id']])) {
+                $this->delete($key);
+                continue;
+            }
+            /* @var GoodsModel $goods 商品信息 */
+            $goods = clone $sourceData[$item['goods_id']];
+            // 判断商品是否已删除
+            if ($goods['is_delete']) {
+                $this->delete($key);
+                continue;
+            }
+            // 商品sku信息
+            $goods['goods_sku'] = GoodsModel::getGoodsSku($goods, $item['goods_sku_id']);
+            $goods['goods_sku_id'] = $item['goods_sku_id'];
+            $goods['spec_sku_id'] = $goods['goods_sku']['spec_sku_id'];
+            // 商品sku不存在则自动删除
+            if (empty($goods['goods_sku'])) {
+                $this->delete($key);
+                continue;
+            }
+            // 商品单价
+            $goods['goods_price'] = $goods['goods_sku']['goods_price'];
+            // 购买数量
+            $goods['total_num'] = $item['goods_num'];
+            // 商品总价
+            $goods['total_price'] = bcmul($goods['goods_price'], $item['goods_num'], 2);
+            $goodsList[] = $goods->hidden(['category', 'content', 'image', 'sku']);
+        }
+        return $goodsList;
+    }
+
+    /**
+     * 加入购物车
+     * @param int $goodsId 商品id
+     * @param int $goodsNum 加入购物车的数量
+     * @param string $goodsSkuId 商品sku索引
+     * @return bool
+     * @throws \app\common\exception\BaseException
+     * @throws \think\exception\DbException
+     */
+    public function add($goodsId, $goodsNum, $goodsSkuId)
+    {
+        // 购物车商品索引
+        $index = "{$goodsId}_{$goodsSkuId}";
+        // 加入购物车后的商品数量
+        $cartGoodsNum = $goodsNum + (isset($this->cart[$index]) ? $this->cart[$index]['goods_num'] : 0);
+        // 获取商品信息
+        $goods = GoodsModel::detail($goodsId);
+        // 验证商品能否加入
+        if (!$this->checkGoods($goods, $goodsSkuId, $cartGoodsNum)) {
+            return false;
+        }
+        // 将商品同步到好物圈
+        if (!$this->isExistGoodsId($goodsId)) {
+            (new WowService($this->wxapp_id))->add($this->user, [$goods]);
+        }
+        // 记录到购物车列表
+        $this->cart[$index] = [
+            'goods_id' => $goodsId,
+            'goods_num' => $cartGoodsNum,
+            'goods_sku_id' => $goodsSkuId,
+            'create_time' => time()
+        ];
+        return true;
+    }
+
+    /**
+     * 验证购物车中是否存在某商品
+     * @param $goodsId
+     * @return bool
+     */
+    private function isExistGoodsId($goodsId)
+    {
+        foreach ($this->cart as $item) {
+            if ($item['goods_id'] == $goodsId) return true;
+        }
+        return false;
+    }
+
+    /**
+     * 验证商品是否可以购买
+     * @param GoodsModel $goods 商品信息
+     * @param string $goodsSkuId 商品sku索引
+     * @param $cartGoodsNum
+     * @return bool
+     */
+    private function checkGoods($goods, $goodsSkuId, $cartGoodsNum)
+    {
+        // 判断商品是否下架
+        if (!$goods || $goods['is_delete'] || $goods['goods_status']['value'] != 10) {
+            $this->setError('很抱歉,商品信息不存在或已下架');
+            return false;
+        }
+        // 商品sku信息
+        $goods['goods_sku'] = GoodsModel::getGoodsSku($goods, $goodsSkuId);
+        // 判断商品库存
+        if ($cartGoodsNum > $goods['goods_sku']['stock_num']) {
+            $this->setError('很抱歉,商品库存不足');
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 减少购物车中某商品数量
+     * @param int $goodsId
+     * @param string $goodsSkuId
+     */
+    public function sub($goodsId, $goodsSkuId)
+    {
+        $index = "{$goodsId}_{$goodsSkuId}";
+        $this->cart[$index]['goods_num'] > 1 && $this->cart[$index]['goods_num']--;
+    }
+
+    /**
+     * 删除购物车中指定商品
+     * @param string $cartIds (支持字符串ID集)
+     */
+    public function delete($cartIds)
+    {
+        $indexArr = strpos($cartIds, ',') !== false ? explode(',', $cartIds) : [$cartIds];
+        foreach ($indexArr as $index) {
+            if (isset($this->cart[$index])) unset($this->cart[$index]);
+        }
+    }
+
+    /**
+     * 获取当前用户购物车商品总数量(含件数)
+     * @return int
+     */
+    public function getTotalNum()
+    {
+        return helper::getArrayColumnSum($this->cart, 'goods_num');
+    }
+
+    /**
+     * 获取当前用户购物车商品总数量(不含件数)
+     * @return int
+     */
+    public function getGoodsNum()
+    {
+        return count($this->cart);
+    }
+
+    /**
+     * 析构方法
+     * 将cart数据保存到缓存文件
+     */
+    public function __destruct()
+    {
+        $this->clear !== true && Cache::set('cart_' . $this->user_id, $this->cart, 86400 * 15);
+    }
+
+    /**
+     * 清空当前用户购物车
+     * @param null $cartIds
+     */
+    public function clearAll($cartIds = null)
+    {
+        if (empty($cartIds)) {
+            $this->clear = true;
+            Cache::rm('cart_' . $this->user_id);
+        } else {
+            $this->delete($cartIds);
+        }
+    }
+
+    /**
+     * 设置错误信息
+     * @param $error
+     */
+    private function setError($error)
+    {
+        empty($this->error) && $this->error = $error;
+    }
+
+    /**
+     * 获取错误信息
+     * @return string
+     */
+    public function getError()
+    {
+        return $this->error;
+    }
+
+}

+ 36 - 0
dyu/application/api/model/Category.php

@@ -0,0 +1,36 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\model\Category as CategoryModel;
+
+/**
+ * 商品分类模型
+ * Class Category
+ * @package app\common\model
+ */
+class Category extends CategoryModel
+{
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'wxapp_id',
+//        'create_time',
+        'update_time'
+    ];
+
+    public static function getList() {
+
+    }
+
+}

+ 237 - 0
dyu/application/api/model/Comment.php

@@ -0,0 +1,237 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\exception\BaseException;
+use app\common\model\Comment as CommentModel;
+use app\common\library\helper;
+
+/**
+ * 商品评价模型
+ * Class Comment
+ * @package app\api\model
+ */
+class Comment extends CommentModel
+{
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'status',
+        'sort',
+        'order_id',
+        'goods_id',
+        'order_goods_id',
+        'is_delete',
+        'update_time'
+    ];
+
+    /**
+     * 关联用户表
+     * @return \think\model\relation\BelongsTo
+     */
+    public function user()
+    {
+        return $this->belongsTo('User')->field(['user_id', 'nickName', 'avatarUrl']);
+    }
+
+    /**
+     * 获取指定商品评价列表
+     * @param $goods_id
+     * @param int $scoreType
+     * @return \think\Paginator
+     * @throws \think\exception\DbException
+     */
+    public function getGoodsCommentList($goods_id, $scoreType = -1)
+    {
+        // 筛选条件
+        $filter = [
+            'goods_id' => $goods_id,
+            'is_delete' => 0,
+            'status' => 1,
+        ];
+        // 评分
+        $scoreType > 0 && $filter['score'] = $scoreType;
+        return $this->with(['user', 'OrderGoods', 'image.file'])
+            ->where($filter)
+            ->order(['sort' => 'asc', 'create_time' => 'desc'])
+            ->paginate(15, false, [
+                'query' => request()->request()
+            ]);
+    }
+
+    /**
+     * 获取指定评分总数
+     * @param $goods_id
+     * @return array|false|\PDOStatement|string|\think\Model
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function getTotal($goods_id)
+    {
+        return $this->field([
+            'count(comment_id) AS `all`',
+            'count(score = 10 OR NULL) AS `praise`',
+            'count(score = 20 OR NULL) AS `review`',
+            'count(score = 30 OR NULL) AS `negative`',
+        ])->where([
+            'goods_id' => $goods_id,
+            'is_delete' => 0,
+            'status' => 1
+        ])->find();
+    }
+
+    /**
+     * 验证订单是否允许评价
+     * @param Order $order
+     * @return boolean
+     */
+    public function checkOrderAllowComment($order)
+    {
+        // 验证订单是否已完成
+        if ($order['order_status']['value'] != 30) {
+            $this->error = '该订单未完成,无法评价';
+            return false;
+        }
+        // 验证订单是否已评价
+        if ($order['is_comment'] == 1) {
+            $this->error = '该订单已完成评价';
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 根据已完成订单商品 添加评价
+     * @param Order $order
+     * @param \think\Collection|OrderGoods $goodsList
+     * @param $post
+     * @return boolean
+     * @throws \Exception
+     */
+    public function addForOrder($order, $goodsList, $post)
+    {
+        // 生成 formData
+        $formData = $this->formatFormData($post);
+        // 生成评价数据
+        $data = $this->createCommentData($order['user_id'], $order['order_id'], $goodsList, $formData);
+        if (empty($data)) {
+            $this->error = '没有输入评价内容';
+            return false;
+        }
+        return $this->transaction(function () use ($order, $goodsList, $formData, $data) {
+            // 记录评价内容
+            $result = $this->isUpdate(false)->saveAll($data);
+            // 记录评价图片
+            $this->saveAllImages($result, $formData);
+            // 更新订单评价状态
+            $isComment = count($goodsList) === count($data);
+            $this->updateOrderIsComment($order, $isComment, $result);
+            return true;
+        });
+    }
+
+    /**
+     * 更新订单评价状态
+     * @param Order $order
+     * @param $isComment
+     * @param $commentList
+     * @return array|false
+     * @throws \Exception
+     */
+    private function updateOrderIsComment($order, $isComment, $commentList)
+    {
+        // 更新订单商品
+        $orderGoodsData = [];
+        foreach ($commentList as $comment) {
+            $orderGoodsData[] = [
+                'order_goods_id' => $comment['order_goods_id'],
+                'is_comment' => 1
+            ];
+        }
+        // 更新订单
+        $isComment && $order->save(['is_comment' => 1]);
+        return (new OrderGoods)->saveAll($orderGoodsData);
+    }
+
+    /**
+     * 生成评价数据
+     * @param $user_id
+     * @param $order_id
+     * @param $goodsList
+     * @param $formData
+     * @return array
+     * @throws BaseException
+     */
+    private function createCommentData($user_id, $order_id, $goodsList, $formData)
+    {
+        $data = [];
+        foreach ($goodsList as $goods) {
+            if (!isset($formData[$goods['order_goods_id']])) {
+                throw new BaseException(['msg' => '提交的数据不合法']);
+            }
+            $item = $formData[$goods['order_goods_id']];
+            $item['content'] = trim($item['content']);
+            !empty($item['content']) && $data[$goods['order_goods_id']] = [
+                'score' => $item['score'],
+                'content' => $item['content'],
+                'is_picture' => !empty($item['uploaded']),
+                'sort' => 100,
+                'status' => 1,
+                'user_id' => $user_id,
+                'order_id' => $order_id,
+                'goods_id' => $item['goods_id'],
+                'order_goods_id' => $item['order_goods_id'],
+                'wxapp_id' => self::$wxapp_id
+            ];
+        }
+        return $data;
+    }
+
+    /**
+     * 格式化 formData
+     * @param string $post
+     * @return array
+     */
+    private function formatFormData($post)
+    {
+        $formJsonData = htmlspecialchars_decode($post);
+        return helper::arrayColumn2Key(helper::jsonDecode($formJsonData), 'order_goods_id');
+    }
+
+    /**
+     * 记录评价图片
+     * @param $commentList
+     * @param $formData
+     * @return bool
+     * @throws \Exception
+     */
+    private function saveAllImages($commentList, $formData)
+    {
+        // 生成评价图片数据
+        $imageData = [];
+        foreach ($commentList as $comment) {
+            $item = $formData[$comment['order_goods_id']];
+            foreach ($item['uploaded'] as $imageId) {
+                $imageData[] = [
+                    'comment_id' => $comment['comment_id'],
+                    'image_id' => $imageId,
+                    'wxapp_id' => self::$wxapp_id
+                ];
+            }
+        }
+        $model = new CommentImage;
+        return !empty($imageData) && $model->saveAll($imageData);
+    }
+
+}

+ 31 - 0
dyu/application/api/model/CommentImage.php

@@ -0,0 +1,31 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\model\CommentImage as CommentImageModel;
+
+/**
+ * 商品图片模型
+ * Class GoodsImage
+ * @package app\api\model
+ */
+class CommentImage extends CommentImageModel
+{
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'wxapp_id',
+        'create_time',
+    ];
+
+}

+ 94 - 0
dyu/application/api/model/Coupon.php

@@ -0,0 +1,94 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\model\Coupon as CouponModel;
+
+/**
+ * 优惠券模型
+ * Class Coupon
+ * @package app\api\model
+ */
+class Coupon extends CouponModel
+{
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'receive_num',
+        'is_delete',
+        'create_time',
+        'update_time',
+    ];
+
+    /**
+     * 获取优惠券列表
+     * @param bool $user
+     * @param null $limit
+     * @param bool $only_receive
+     * @return false|\PDOStatement|string|\think\Collection
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function getList($user = false, $limit = null, $only_receive = false)
+    {
+        // 构造查询条件
+        $this->where('is_delete', '=', 0);
+        // 只显示可领取(未过期,未发完)的优惠券
+        if ($only_receive) {
+            $this->where('	IF ( `total_num` > - 1, `receive_num` < `total_num`, 1 = 1 )')
+                ->where('IF ( `expire_type` = 20, (`end_time` + 86400) >= ' . time() . ', 1 = 1 )');
+        }
+
+        // 优惠券列表
+        $couponList = $this->order(['sort' => 'asc', 'create_time' => 'desc'])->limit($limit)->select();
+
+        // 获取用户已领取的优惠券
+        if ($user !== false) {
+            $UserCouponModel = new UserCoupon;
+            $userCouponIds = $UserCouponModel->getUserCouponIds($user['user_id']);
+            foreach ($couponList as $key => $item) {
+                $couponList[$key]['is_receive'] = in_array($item['coupon_id'], $userCouponIds);
+            }
+        }
+        return $couponList;
+    }
+
+    /**
+     * 验证优惠券是否可领取
+     * @return bool
+     */
+    public function checkReceive()
+    {
+        if ($this['total_num'] > -1 && $this['receive_num'] >= $this['total_num']) {
+            $this->error = '优惠券已发完';
+            return false;
+        }
+        if ($this['expire_type'] == 20 && ($this->getData('end_time') + 86400) < time()) {
+            $this->error = '优惠券已过期';
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 累计已领取数量
+     * @return int|true
+     * @throws \think\Exception
+     */
+    public function setIncReceiveNum()
+    {
+        return $this->setInc('receive_num');
+    }
+
+}

+ 32 - 0
dyu/application/api/model/Delivery.php

@@ -0,0 +1,32 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\model\Delivery as DeliveryModel;
+
+/**
+ * 配送模板模型
+ * Class Delivery
+ * @package app\api\model
+ */
+class Delivery extends DeliveryModel
+{
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'wxapp_id',
+        'create_time',
+        'update_time'
+    ];
+
+}

+ 32 - 0
dyu/application/api/model/DeliveryRule.php

@@ -0,0 +1,32 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\model\DeliveryRule as DeliveryRuleModel;
+
+/**
+ * 配送模板区域及运费模型
+ * Class DeliveryRule
+ * @package app\api\model
+ */
+class DeliveryRule extends DeliveryRuleModel
+{
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'wxapp_id',
+        'create_time',
+        'update_time'
+    ];
+
+}

+ 34 - 0
dyu/application/api/model/Express.php

@@ -0,0 +1,34 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\model\Express as ExpressModel;
+
+/**
+ * 物流公司模型
+ * Class Express
+ * @package app\api\model
+ */
+class Express extends ExpressModel
+{
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'express_code',
+        'sort',
+        'wxapp_id',
+        'create_time',
+        'update_time'
+    ];
+
+}

+ 184 - 0
dyu/application/api/model/Goods.php

@@ -0,0 +1,184 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\library\helper;
+use app\common\model\Goods as GoodsModel;
+use app\api\service\Goods as GoodsService;
+
+/**
+ * 商品模型
+ * Class Goods
+ * @package app\api\model
+ */
+class Goods extends GoodsModel
+{
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'spec_rel',
+        'delivery',
+        'sales_initial',
+        'sales_actual',
+        'is_delete',
+        'wxapp_id',
+        'create_time',
+        'update_time'
+    ];
+
+    /**
+     * 商品详情:HTML实体转换回普通字符
+     * @param $value
+     * @return string
+     */
+    public function getContentAttr($value)
+    {
+        return htmlspecialchars_decode($value);
+    }
+
+    /**
+     * 获取商品列表
+     * @param $param
+     * @param bool $userInfo
+     * @return mixed
+     * @throws \think\exception\DbException
+     */
+    public function getList($param, $userInfo = false)
+    {
+        // 获取商品列表
+        $data = parent::getList($param);
+        // 隐藏api属性
+        !$data->isEmpty() && $data->hidden(['category', 'content', 'image', 'sku']);
+        // 整理列表数据并返回
+        return $this->setGoodsListDataFromApi($data, true, ['userInfo' => $userInfo]);
+    }
+
+    /**
+     * 商品详情
+     * @param $goodsId
+     * @return GoodsModel
+     */
+    public static function detail($goodsId)
+    {
+        // 商品详情
+        $detail = parent::detail($goodsId);
+        // 多规格商品sku信息
+        $detail['goods_multi_spec'] = GoodsService::getSpecData($detail);
+        return $detail;
+    }
+
+    /**
+     * 获取商品详情页面
+     * @param int $goodsId 商品id
+     * @param array|bool $userInfo 用户信息
+     * @return array|bool|false|mixed|\PDOStatement|string|\think\Model
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function getDetails($goodsId, $userInfo = false)
+    {
+        // 获取商品详情
+        $detail = $this->with([
+            'category',
+            'image' => ['file'],
+            'sku' => ['image'],
+            'spec_rel' => ['spec'],
+            'delivery' => ['rule'],
+            'commentData' => function ($query) {
+                $query->with('user')->where(['is_delete' => 0, 'status' => 1])->limit(2);
+            }
+        ])->withCount(['commentData' => function ($query) {
+            $query->where(['is_delete' => 0, 'status' => 1]);
+        }])
+            ->where('goods_id', '=', $goodsId)
+            ->find();
+        // 判断商品的状态
+        if (empty($detail) || $detail['is_delete'] || $detail['goods_status']['value'] != 10) {
+            $this->error = '很抱歉,商品信息不存在或已下架';
+            return false;
+        }
+        // 设置商品展示的数据
+        $detail = $this->setGoodsListDataFromApi($detail, false, ['userInfo' => $userInfo]);
+        // 多规格商品sku信息
+        $detail['goods_multi_spec'] = GoodsService::getSpecData($detail);
+        return $detail;
+    }
+
+    /**
+     * 根据商品id集获取商品列表
+     * @param $goodsIds
+     * @param bool $userInfo
+     * @return mixed
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function getListByIdsFromApi($goodsIds, $userInfo = false)
+    {
+        // 获取商品列表
+        $data = parent::getListByIds($goodsIds, 10);
+        // 整理列表数据并返回
+        return $this->setGoodsListDataFromApi($data, true, ['userInfo' => $userInfo]);
+    }
+
+
+    /**
+     * 设置商品展示的数据 api模块
+     * @param $data
+     * @param bool $isMultiple
+     * @param array $param
+     * @return mixed
+     */
+    private function setGoodsListDataFromApi(&$data, $isMultiple, $param)
+    {
+        return parent::setGoodsListData($data, $isMultiple, function ($goods) use ($param) {
+            // 计算并设置商品会员价
+            $this->setGoodsGradeMoney($param['userInfo'], $goods);
+        });
+    }
+
+    /**
+     * 设置商品的会员价
+     * @param $user
+     * @param $goods
+     */
+    private function setGoodsGradeMoney($user, &$goods)
+    {
+        // 会员等级状态
+        $gradeStatus = (!empty($user) && $user['grade_id'] > 0 && !empty($user['grade']))
+            && (!$user['grade']['is_delete'] && $user['grade']['status']);
+        // 判断商品是否参与会员折扣
+        if (!$gradeStatus || !$goods['is_enable_grade']) {
+            $goods['is_user_grade'] = false;
+            return;
+        }
+        // 商品单独设置了会员折扣
+        if ($goods['is_alone_grade'] && isset($goods['alone_grade_equity'][$user['grade_id']])) {
+            // 折扣比例
+            $discountRatio = helper::bcdiv($goods['alone_grade_equity'][$user['grade_id']], 10);
+        } else {
+            // 折扣比例
+            $discountRatio = helper::bcdiv($user['grade']['equity']['discount'], 10);
+        }
+        if ($discountRatio > 0) {
+            // 标记参与会员折扣
+            $goods['is_user_grade'] = true;
+            // 会员折扣价
+            foreach ($goods['sku'] as &$skuItem) {
+                $skuItem['goods_price'] = helper::number2(helper::bcmul($skuItem['goods_price'], $discountRatio), true);
+            }
+        }
+    }
+
+}

+ 31 - 0
dyu/application/api/model/GoodsImage.php

@@ -0,0 +1,31 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\model\GoodsImage as GoodsImageModel;
+
+/**
+ * 商品图片模型
+ * Class GoodsImage
+ * @package app\api\model
+ */
+class GoodsImage extends GoodsImageModel
+{
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'wxapp_id',
+        'create_time',
+    ];
+
+}

+ 32 - 0
dyu/application/api/model/GoodsSku.php

@@ -0,0 +1,32 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\model\GoodsSku as GoodsSkuModel;
+
+/**
+ * 商品规格模型
+ * Class GoodsSku
+ * @package app\api\model
+ */
+class GoodsSku extends GoodsSkuModel
+{
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'wxapp_id',
+        'create_time',
+        'update_time'
+    ];
+
+}

+ 22 - 0
dyu/application/api/model/GoodsSpecRel.php

@@ -0,0 +1,22 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\model\GoodsSpecRel as GoodsSpecRelModel;
+
+/**
+ * 商品规格关系模型
+ * Class GoodsSpecRel
+ * @package app\api\model
+ */
+class GoodsSpecRel extends GoodsSpecRelModel
+{
+}

+ 390 - 0
dyu/application/api/model/Order.php

@@ -0,0 +1,390 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\api\model\User as UserModel;
+use app\api\model\Goods as GoodsModel;
+use app\api\model\Setting as SettingModel;
+use app\api\model\UserCoupon as UserCouponModel;
+use app\api\service\order\PaySuccess;
+use app\api\service\Payment as PaymentService;
+use app\api\service\order\source\Factory as OrderSourceFactory;
+use app\common\model\Order as OrderModel;
+use app\common\enum\OrderType as OrderTypeEnum;
+use app\common\enum\DeliveryType as DeliveryTypeEnum;
+use app\common\enum\order\Status as OrderStatusEnum;
+use app\common\enum\order\PayType as PayTypeEnum;
+use app\common\enum\order\PayStatus as PayStatusEnum;
+use app\common\service\goods\source\Factory as FactoryStock;
+use app\common\service\order\Complete as OrderCompleteService;
+use app\common\exception\BaseException;
+use app\common\library\helper;
+
+/**
+ * 订单模型
+ * Class Order
+ * @package app\api\model
+ */
+class Order extends OrderModel
+{
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'wxapp_id',
+        'update_time'
+    ];
+
+    /**
+     * 待支付订单详情
+     * @param $orderNo
+     * @return null|static
+     * @throws \think\exception\DbException
+     */
+    public static function getPayDetail($orderNo)
+    {
+        return self::get(['order_no' => $orderNo, 'pay_status' => 10, 'is_delete' => 0], ['goods', 'user']);
+    }
+
+    /**
+     * 订单支付事件
+     * @param int $payType
+     * @return bool
+     * @throws \think\exception\DbException
+     */
+    public function onPay($payType = PayTypeEnum::WECHAT)
+    {
+        // 判断订单状态
+        $orderSource = OrderSourceFactory::getFactory($this['order_source']);
+        if (!$orderSource->checkOrderStatusOnPay($this)) {
+            $this->error = $orderSource->getError();
+            return false;
+        }
+        // 余额支付
+        if ($payType == PayTypeEnum::BALANCE) {
+            return $this->onPaymentByBalance($this['order_no']);
+        }
+        return true;
+    }
+
+    /**
+     * 构建支付请求的参数
+     * @param $user
+     * @param $order
+     * @param $payType
+     * @return array
+     * @throws BaseException
+     * @throws \think\exception\DbException
+     */
+    public function onOrderPayment($user, $order, $payType)
+    {
+        if ($payType == PayTypeEnum::WECHAT) {
+            return $this->onPaymentByWechat($user, $order);
+        }
+        return [];
+    }
+
+    /**
+     * 构建微信支付请求
+     * @param $user
+     * @param $order
+     * @return array
+     * @throws BaseException
+     * @throws \think\exception\DbException
+     */
+    protected function onPaymentByWechat($user, $order)
+    {
+        return PaymentService::wechat(
+            $user,
+            $order['order_id'],
+            $order['order_no'],
+            $order['pay_price'],
+            OrderTypeEnum::MASTER
+        );
+    }
+
+    /**
+     * 立即购买:获取订单商品列表
+     * @param $goodsId
+     * @param $goodsSkuId
+     * @param $goodsNum
+     * @return array
+     */
+    public function getOrderGoodsListByNow($goodsId, $goodsSkuId, $goodsNum)
+    {
+        // 商品详情
+        /* @var GoodsModel $goods */
+        $goods = GoodsModel::detail($goodsId);
+        // 商品sku信息
+        $goods['goods_sku'] = GoodsModel::getGoodsSku($goods, $goodsSkuId);
+        // 商品列表
+        $goodsList = [$goods->hidden(['category', 'content', 'image', 'sku'])];
+        foreach ($goodsList as &$item) {
+            // 商品单价
+            $item['goods_price'] = $item['goods_sku']['goods_price'];
+            // 商品购买数量
+            $item['total_num'] = $goodsNum;
+            $item['spec_sku_id'] = $item['goods_sku']['spec_sku_id'];
+            // 商品购买总金额
+            $item['total_price'] = helper::bcmul($item['goods_price'], $goodsNum);
+        }
+        return $goodsList;
+    }
+
+    /**
+     * 余额支付标记订单已支付
+     * @param $orderNo
+     * @return bool
+     * @throws \think\exception\DbException
+     */
+    public function onPaymentByBalance($orderNo)
+    {
+        // 获取订单详情
+        $PaySuccess = new PaySuccess($orderNo);
+        // 发起余额支付
+        $status = $PaySuccess->onPaySuccess(PayTypeEnum::BALANCE);
+        if (!$status) {
+            $this->error = $PaySuccess->getError();
+        }
+        return $status;
+    }
+
+    /**
+     * 用户中心订单列表
+     * @param $user_id
+     * @param string $type
+     * @return \think\Paginator
+     * @throws \think\exception\DbException
+     */
+    public function getList($user_id, $type = 'all')
+    {
+        // 筛选条件
+        $filter = [];
+        // 订单数据类型
+        switch ($type) {
+            case 'all':
+                break;
+            case 'payment';
+                $filter['pay_status'] = PayStatusEnum::PENDING;
+                $filter['order_status'] = 10;
+                break;
+            case 'delivery';
+                $filter['pay_status'] = PayStatusEnum::SUCCESS;
+                $filter['delivery_status'] = 10;
+                $filter['order_status'] = 10;
+                break;
+            case 'received';
+                $filter['pay_status'] = PayStatusEnum::SUCCESS;
+                $filter['delivery_status'] = 20;
+                $filter['receipt_status'] = 10;
+                $filter['order_status'] = 10;
+                break;
+            case 'comment';
+                $filter['is_comment'] = 0;
+                $filter['order_status'] = 30;
+                break;
+        }
+        return $this->with(['goods.image'])
+            ->where('user_id', '=', $user_id)
+            ->where($filter)
+            ->where('is_delete', '=', 0)
+            ->order(['create_time' => 'desc'])
+            ->paginate(15, false, [
+                'query' => \request()->request()
+            ]);
+    }
+
+    /**
+     * 取消订单
+     * @param UserModel $user
+     * @return bool|mixed
+     */
+    public function cancel($user)
+    {
+        if ($this['delivery_status']['value'] == 20) {
+            $this->error = '已发货订单不可取消';
+            return false;
+        }
+        // 订单取消事件
+        return $this->transaction(function () use ($user) {
+            // 订单是否已支付
+            $isPay = $this['pay_status']['value'] == PayStatusEnum::SUCCESS;
+            // 未付款的订单
+            if ($isPay == false) {
+                // 回退商品库存
+                FactoryStock::getFactory($this['order_source'])->backGoodsStock($this['goods'], $isPay);
+                // 回退用户优惠券
+                $this['coupon_id'] > 0 && UserCouponModel::setIsUse($this['coupon_id'], false);
+                // 回退用户积分
+                $describe = "订单取消:{$this['order_no']}";
+                $this['points_num'] > 0 && $user->setIncPoints($this['points_num'], $describe);
+            }
+            // 更新订单状态
+            return $this->save(['order_status' => $isPay ? OrderStatusEnum::APPLY_CANCEL : OrderStatusEnum::CANCELLED]);
+        });
+    }
+
+    /**
+     * 确认收货
+     * @return bool|mixed
+     */
+    public function receipt()
+    {
+        // 验证订单是否合法
+        // 条件1: 订单必须已发货
+        // 条件2: 订单必须未收货
+        if ($this['delivery_status']['value'] != 20 || $this['receipt_status']['value'] != 10) {
+            $this->error = '该订单不合法';
+            return false;
+        }
+        return $this->transaction(function () {
+            // 更新订单状态
+            $status = $this->save([
+                'receipt_status' => 20,
+                'receipt_time' => time(),
+                'order_status' => 30
+            ]);
+//            // 获取已完成的订单
+//            $completed = self::detail($this['order_id'], [
+//                'user', 'address', 'goods', 'express',    // 用于好物圈
+//            ]);
+            // 执行订单完成后的操作
+            $OrderCompleteService = new OrderCompleteService(OrderTypeEnum::MASTER);
+            $OrderCompleteService->complete([$this], static::$wxapp_id);
+            return $status;
+        });
+    }
+
+    /**
+     * 获取订单总数
+     * @param $user
+     * @param string $type
+     * @return int|string
+     * @throws \think\Exception
+     */
+    public function getCount($user, $type = 'all')
+    {
+        if ($user === false) {
+            return false;
+        }
+        // 筛选条件
+        $filter = [];
+        // 订单数据类型
+        switch ($type) {
+            case 'all':
+                break;
+            case 'payment';
+                $filter['pay_status'] = PayStatusEnum::PENDING;
+                break;
+            case 'received';
+                $filter['pay_status'] = PayStatusEnum::SUCCESS;
+                $filter['delivery_status'] = 20;
+                $filter['receipt_status'] = 10;
+                break;
+            case 'comment';
+                $filter['order_status'] = 30;
+                $filter['is_comment'] = 0;
+                break;
+        }
+        return $this->where('user_id', '=', $user['user_id'])
+            ->where('order_status', '<>', 20)
+            ->where($filter)
+            ->where('is_delete', '=', 0)
+            ->count();
+    }
+
+    /**
+     * 订单详情
+     * @param $order_id
+     * @param null $user_id
+     * @return null|static
+     * @throws BaseException
+     * @throws \think\exception\DbException
+     */
+    public static function getUserOrderDetail($order_id, $user_id)
+    {
+        if (!$order = self::get([
+            'order_id' => $order_id,
+            'user_id' => $user_id,
+        ], [
+            'goods' => ['image', 'goods', 'refund'],
+            'address', 'express', 'extract_shop'
+        ])
+        ) {
+            throw new BaseException(['msg' => '订单不存在']);
+        }
+        return $order;
+    }
+
+    /**
+     * 判断当前订单是否允许核销
+     * @param static $order
+     * @return bool
+     */
+    public function checkExtractOrder(&$order)
+    {
+        if (
+            $order['pay_status']['value'] == PayStatusEnum::SUCCESS
+            && $order['delivery_type']['value'] == DeliveryTypeEnum::EXTRACT
+            && $order['delivery_status']['value'] == 10
+        ) {
+            return true;
+        }
+        $this->setError('该订单不能被核销');
+        return false;
+    }
+
+    /**
+     * 当前订单是否允许申请售后
+     * @return bool
+     */
+    public function isAllowRefund()
+    {
+        // 必须是已发货的订单
+        if ($this['delivery_status']['value'] != 20) {
+            return false;
+        }
+        // 允许申请售后期限(天)
+        $refundDays = SettingModel::getItem('trade')['order']['refund_days'];
+        // 不允许售后
+        if ($refundDays == 0) {
+            return false;
+        }
+        // 当前时间超出允许申请售后期限
+        if (
+            $this['receipt_status'] == 20
+            && time() > ($this['receipt_time'] + ((int)$refundDays * 86400))
+        ) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 设置错误信息
+     * @param $error
+     */
+    protected function setError($error)
+    {
+        empty($this->error) && $this->error = $error;
+    }
+
+    /**
+     * 是否存在错误
+     * @return bool
+     */
+    public function hasError()
+    {
+        return !empty($this->error);
+    }
+
+}

+ 31 - 0
dyu/application/api/model/OrderAddress.php

@@ -0,0 +1,31 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\model\OrderAddress as OrderAddressModel;
+
+/**
+ * 订单收货地址模型
+ * Class OrderAddress
+ * @package app\api\model
+ */
+class OrderAddress extends OrderAddressModel
+{
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'wxapp_id',
+        'create_time',
+    ];
+
+}

+ 23 - 0
dyu/application/api/model/OrderExtract.php

@@ -0,0 +1,23 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\model\OrderExtract as OrderExtractModel;
+
+/**
+ * 自提订单联系方式模型
+ * Class OrderExtract
+ * @package app\api\model
+ */
+class OrderExtract extends OrderExtractModel
+{
+
+}

+ 43 - 0
dyu/application/api/model/OrderGoods.php

@@ -0,0 +1,43 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\model\OrderGoods as OrderGoodsModel;
+
+/**
+ * 订单商品模型
+ * Class OrderGoods
+ * @package app\api\model
+ */
+class OrderGoods extends OrderGoodsModel
+{
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'content',
+        'wxapp_id',
+        'create_time',
+    ];
+
+    /**
+     * 获取未评价的商品
+     * @param $order_id
+     * @return OrderGoods[]|false
+     * @throws \think\exception\DbException
+     */
+    public static function getNotCommentGoodsList($order_id)
+    {
+        return self::all(['order_id' => $order_id, 'is_comment' => 0], ['orderM', 'image']);
+    }
+
+}

+ 179 - 0
dyu/application/api/model/OrderRefund.php

@@ -0,0 +1,179 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\model\OrderRefund as OrderRefundModel;
+
+/**
+ * 售后单模型
+ * Class OrderRefund
+ * @package app\api\model
+ */
+class OrderRefund extends OrderRefundModel
+{
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'wxapp_id',
+        'update_time'
+    ];
+
+    /**
+     * 追加字段
+     * @var array
+     */
+    protected $append = [
+        'state_text',   // 售后单状态文字描述
+    ];
+
+    /**
+     * 售后单状态文字描述
+     * @param $value
+     * @param $data
+     * @return string
+     */
+    public function getStateTextAttr($value, $data)
+    {
+        // 已完成
+        if ($data['status'] == 20) {
+            $text = [10 => '已同意退货并已退款', 20 => '已同意换货'];
+            return $text[$data['type']];
+        }
+        // 已取消
+        if ($data['status'] == 30) {
+            return '已取消';
+        }
+        // 已拒绝
+        if ($data['status'] == 10) {
+//            return '已拒绝';
+            return $data['type'] == 10 ? '已拒绝退货退款' : '已拒绝换货';
+        }
+        // 进行中
+        if ($data['status'] == 0) {
+            if ($data['is_agree'] == 0) {
+                return '等待审核中';
+            }
+            if ($data['type'] == 10) {
+                return $data['is_user_send'] ? '已发货,待平台确认' : '已同意退货,请及时发货';
+            }
+        }
+        return $value;
+    }
+
+    /**
+     * 获取用户售后单列表
+     * @param $user_id
+     * @param int $state
+     * @return \think\Paginator
+     * @throws \think\exception\DbException
+     */
+    public function getList($user_id, $state = -1)
+    {
+        $state > -1 && $this->where('status', '=', $state);
+        return $this->with(['order_master', 'order_goods.image'])
+            ->where('user_id', '=', $user_id)
+            ->order(['create_time' => 'desc'])
+            ->paginate(15, false, [
+                'query' => \request()->request()
+            ]);
+    }
+
+    /**
+     * 用户发货
+     * @param $data
+     * @return false|int
+     */
+    public function delivery($data)
+    {
+        if (
+            $this['type']['value'] != 10
+            || $this['is_agree']['value'] != 10
+            || $this['is_user_send'] != 0
+        ) {
+            $this->error = '当前售后单不合法,不允许该操作';
+            return false;
+        }
+        if ($data['express_id'] <= 0) {
+            $this->error = '请选择物流公司';
+            return false;
+        }
+        if (empty($data['express_no'])) {
+            $this->error = '请填写物流单号';
+            return false;
+        }
+        return $this->save([
+            'is_user_send' => 1,
+            'send_time' => time(),
+            'express_id' => (int)$data['express_id'],
+            'express_no' => $data['express_no'],
+        ]);
+    }
+
+    /**
+     * 新增售后单记录
+     * @param $user
+     * @param $goods
+     * @param $data
+     * @return bool
+     * @throws \Exception
+     */
+    public function apply($user, $goods, $data)
+    {
+        $this->startTrans();
+        try {
+            // 新增售后单记录
+            $this->save([
+                'order_goods_id' => $data['order_goods_id'],
+                'order_id' => $goods['order_id'],
+                'user_id' => $user['user_id'],
+                'type' => $data['type'],
+                'apply_desc' => $data['content'],
+                'is_agree' => 0,
+                'status' => 0,
+                'wxapp_id' => self::$wxapp_id,
+            ]);
+            // 记录凭证图片关系
+            if (isset($data['images']) && !empty($data['images'])) {
+                $this->saveImages($this['order_refund_id'], $data['images']);
+            }
+            $this->commit();
+            return true;
+        } catch (\Exception $e) {
+            $this->error = $e->getMessage();
+            $this->rollback();
+            return false;
+        }
+    }
+
+    /**
+     * 记录售后单图片
+     * @param $order_refund_id
+     * @param $images
+     * @return bool
+     * @throws \Exception
+     */
+    private function saveImages($order_refund_id, $images)
+    {
+        // 生成评价图片数据
+        $data = [];
+        foreach (explode(',', $images) as $image_id) {
+            $data[] = [
+                'order_refund_id' => $order_refund_id,
+                'image_id' => $image_id,
+                'wxapp_id' => self::$wxapp_id
+            ];
+        }
+        return !empty($data) && (new OrderRefundImage)->saveAll($data);
+    }
+
+}

+ 31 - 0
dyu/application/api/model/OrderRefundAddress.php

@@ -0,0 +1,31 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\api\model;
+
+use app\common\model\OrderRefundAddress as OrderRefundAddressModel;
+
+/**
+ * 售后单退货地址模型
+ * Class OrderRefundAddress
+ * @package app\api\model
+ */
+class OrderRefundAddress extends OrderRefundAddressModel
+{
+    /**
+     * 隐藏字段
+     * @var array
+     */
+    protected $hidden = [
+        'wxapp_id',
+        'create_time'
+    ];
+
+}

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels