Browse Source

fix:计算页面

super-yimizi 2 months ago
parent
commit
22d605901c
37 changed files with 2498 additions and 635 deletions
  1. 37 0
      application/admin/controller/lottery/Info.php
  2. 62 0
      application/admin/controller/lottery/Prize.php
  3. 214 0
      application/admin/controller/lottery/Record.php
  4. 78 0
      application/admin/model/lottery/Info.php
  5. 62 0
      application/admin/model/lottery/Prize.php
  6. 103 0
      application/admin/model/lottery/Record.php
  7. 25 0
      application/admin/model/lottery/RedbagLog.php
  8. 27 0
      application/admin/validate/lottery/Info.php
  9. 27 0
      application/admin/validate/lottery/Prize.php
  10. 27 0
      application/admin/validate/lottery/Record.php
  11. 69 0
      application/admin/view/lottery/info/add.html
  12. 72 0
      application/admin/view/lottery/info/edit.html
  13. 29 0
      application/admin/view/lottery/info/index.html
  14. 25 0
      application/admin/view/lottery/info/recyclebin.html
  15. 87 0
      application/admin/view/lottery/prize/add.html
  16. 84 0
      application/admin/view/lottery/prize/edit.html
  17. 29 0
      application/admin/view/lottery/prize/index.html
  18. 25 0
      application/admin/view/lottery/prize/recyclebin.html
  19. 69 0
      application/admin/view/lottery/record/add.html
  20. 69 0
      application/admin/view/lottery/record/edit.html
  21. 27 0
      application/admin/view/lottery/record/index.html
  22. 25 0
      application/admin/view/lottery/record/recyclebin.html
  23. 85 0
      application/api/controller/LuckLottery.php
  24. 36 49
      application/api/controller/Order.php
  25. 67 21
      application/api/validate/Order.php
  26. 8 0
      application/common/Enum/CachEnum.php
  27. 75 0
      application/common/Enum/OrderEnum.php
  28. 23 0
      application/common/Enum/PayEnum.php
  29. 0 73
      application/common/model/Carts.php
  30. 1 221
      application/common/model/Order.php
  31. 24 0
      application/common/model/OrderAddress.php
  32. 1 1
      application/common/model/UserCoupon.php
  33. 111 0
      application/common/service/Cart.php
  34. 186 270
      application/common/service/OrderService.php
  35. 275 0
      application/common/service/lottery/LuckLotteryRecordServices.php
  36. 176 0
      application/common/service/lottery/LuckLotteryServices.php
  37. 158 0
      application/common/service/lottery/LuckPrizeServices.php

+ 37 - 0
application/admin/controller/lottery/Info.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace app\admin\controller\lottery;
+
+use app\common\controller\Backend;
+
+/**
+ * 抽奖列管理
+ *
+ * @icon fa fa-circle-o
+ */
+class Info extends Backend
+{
+
+    /**
+     * Info模型对象
+     * @var \app\admin\model\lottery\Info
+     */
+    protected $model = null;
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = new \app\admin\model\lottery\Info;
+        $this->view->assign("typeList", $this->model->getTypeList());
+    }
+
+
+
+    /**
+     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
+     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
+     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
+     */
+
+
+}

+ 62 - 0
application/admin/controller/lottery/Prize.php

@@ -0,0 +1,62 @@
+<?php
+
+namespace app\admin\controller\lottery;
+
+use app\common\controller\Backend;
+
+/**
+ * 抽奖商品列管理
+ *
+ * @icon fa fa-circle-o
+ */
+class Prize extends Backend
+{
+
+    /**
+     * Prize模型对象
+     * @var \app\admin\model\lottery\Prize
+     */
+    protected $model = null;
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = new \app\admin\model\lottery\Prize;
+        $this->view->assign("typeList", $this->model->getTypeList());
+    }
+
+
+
+    /**
+     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
+     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
+     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
+     */
+
+    public function index()
+    {
+        $this->relationSearch = true;
+        $this->searchFields = "lottery.name,id";
+        if ($this->request->isAjax())
+        {
+            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
+            $total = $this->model
+                ->with(['lottery'])
+                ->where($where)
+                ->order($sort, $order)
+                ->count();
+            $list = $this->model
+                ->with(['lottery'])
+                ->where($where)
+                ->order($sort, $order)
+                ->limit($offset, $limit)
+                ->select();
+            $result = array("total" => $total, "rows" => $list, "extend" => ['money' => 1024, 'price' => 888]);
+            return json($result);
+        }
+        return $this->view->fetch();
+    }
+
+
+
+}

+ 214 - 0
application/admin/controller/lottery/Record.php

@@ -0,0 +1,214 @@
+<?php
+
+namespace app\admin\controller\lottery;
+use addons\third\model\Third;
+use app\admin\exception\RedbagException;
+use app\admin\model\lottery\RedbagLog;
+use app\services\pay\PayService;
+use think\Db;
+use think\exception\HttpResponseException;
+use app\common\controller\Backend;
+use think\Log;
+
+/**
+ * 抽奖记录管理
+ *
+ * @icon fa fa-circle-o
+ */
+class Record extends Backend
+{
+
+    /**
+     * Record模型对象
+     * @var \app\admin\model\lottery\Record
+     */
+    protected $model = null;
+    protected $relationSearch = true;
+
+
+    public function _initialize()
+    {
+
+        parent::_initialize();
+        $this->model = new \app\admin\model\lottery\Record;
+        set_addon_config('epay', ['version' => 'v3'], false);
+    }
+
+
+
+
+
+    /**
+     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
+     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
+     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
+     */
+    /**
+     * 查看
+     */
+    public function index()
+    {
+        $this->relationSearch = true;
+        $this->searchFields = "user.nickname,lottery.name,prize.name,id";
+        if ($this->request->isAjax())
+        {
+            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
+            $total = $this->model
+                ->with(['lottery','prize','user'])
+                ->where($where)
+                ->order($sort, $order)
+                ->count();
+            $list = $this->model
+                ->with(['lottery','prize','user'])
+                ->where($where)
+                ->order($sort, $order)
+                ->limit($offset, $limit)
+                ->select();
+            $result = array("total" => $total, "rows" => $list, "extend" => ['money' => 1024, 'price' => 888]);
+            return json($result);
+        }
+        return $this->view->fetch();
+    }
+
+    public function deliver()
+    {
+        if (!$this->request->isAjax()) {
+            return $this->view->fetch();
+        }
+
+        $params = $this->request->param();
+        $id = $params['ids'] ?? 0;
+        if (intval($id) <= 0){
+            $this->error(__('请上传正确的ID'));
+        }
+        // 查询第三方登录数据
+        $withdraw = $this->model->lock(true)->where('id', $id)->find();
+        if (!$withdraw) {
+            $this->error(__('No Results were found'));
+        }
+        $objThird = Third::where('user_id', $withdraw->user_id)
+            ->where('platform','wechat')
+            ->where('apptype','mp')
+            ->find();
+        if (empty($objThird)){
+            $this->error(__('用户三方数据不存在'));
+        }
+        Db::startTrans();
+        try {
+            $withdraw = $this->handleWithdraw($withdraw,$objThird);
+            Db::commit();
+        } catch (HttpResponseException $e) {
+            $data = $e->getResponse()->getData();
+            $message = $data ? ($data['msg'] ?? '') : $e->getMessage();
+            $this->error($message);
+        } catch (\Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        $this->success('处理成功');
+    }
+
+// 处理打款
+    public function handleWithdraw($withdraw, $objThird)
+    {
+
+        $withDrawStatus = false;
+        if ($withdraw->is_deliver == 1) {
+            $this->error('请勿重复操作');
+        }
+        $withDrawStatus = $this->handleTransfer($withdraw,$objThird);
+
+        if ($withDrawStatus) {
+            $withdraw->is_deliver = 1;
+            $withdraw->deliver_time = time();
+            $withdraw->save();
+            return $this->handleLog($withdraw, '已打款');
+        }
+        return $withdraw;
+    }
+    // 企业付款提现
+    private function handleTransfer($withdraw,$objThird)
+    {
+        $type = 'wechat';
+        $platform = 'WechatOfficialAccount';
+
+        $payService = new PayService($type, $platform);
+
+        $sn =  $this->get_sn($withdraw->user_id, 'W');
+        $emoji_pattern = "/[\x{1F600}-\x{1F64F}|[\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}]/u"; // Emoji表情Unicode范围
+        $objThird->openname = preg_replace($emoji_pattern, '', $objThird->openname);
+        $payload = [
+            'out_batch_no' => $sn,
+            'batch_name' => '商家转账到零钱',
+            'batch_remark' => "用户[" . ($objThird->openname ?? '') . "]中奖红包",
+            //'total_amount' => $withdraw->amount,
+            'total_amount' =>$withdraw->num,
+            'total_num' => 1,
+            'transfer_detail_list' => [
+                [
+                    'out_detail_no' => $sn,
+                    //'transfer_amount' => $withdraw->amount,
+                    'transfer_amount' => $withdraw->num,
+                    'transfer_remark' => "用户[" . ($objThird->openname ?? '') . "]中奖红包",
+                    'openid'    => $objThird->openid?? '',
+                    //'user_name' => $objThird->openname ?? '',
+                ],
+            ],
+        ];
+        try {
+            list($code, $response) = $payService->transfer($payload);
+            Log::write('transfer-origin-data:' . json_encode($response));
+            if ($code === 1) {
+                $withdraw->deliver_info = json_encode($response, JSON_UNESCAPED_UNICODE);
+                return true;
+            }
+            throw new RedbagException(json_encode($response, JSON_UNESCAPED_UNICODE));
+        } catch (HttpResponseException $e) {
+            $data = $e->getResponse()->getData();
+            $message = $data ? ($data['msg'] ?? '') : $e->getMessage();
+            Log::write('http-error-reponData:' .$message);
+            throw new RedbagException($message);
+        } catch (\Exception $e) {
+            \think\Log::error('抽奖发红包失败:' . ' 行号:' . $e->getLine() . '文件:' . $e->getFile() . '错误信息:' . $e->getMessage());
+            $this->handleLog($withdraw, '抽奖发红包失败:' . $e->getMessage());
+            throw new RedbagException($e->getMessage());
+        }
+        return false;
+    }
+
+
+    private function handleLog($withdraw, $oper_info)
+    {
+        $oper = $this->auth->id;
+
+        RedbagLog::insert([
+            'lottery_record_id' => $withdraw->id,
+            'content' => $oper_info,
+            'oper_type' => 'admin',
+            'oper_id' => $oper,
+            'createtime' => time()
+        ]);
+        return $withdraw;
+    }
+
+
+    /**
+     * 获取唯一编号
+     *
+     * @param mixed $id       唯一标识
+     * @param string $type    类型
+     * @return string
+     */
+     public  function get_sn($id, $type = '')
+    {
+        $id = (string)$id;
+
+        $rand = $id < 9999 ? mt_rand(100000, 99999999) : mt_rand(100, 99999);
+        $sn = date('Yhis') . $rand;
+
+        $id = str_pad($id, (24 - strlen($sn)), '0', STR_PAD_BOTH);
+
+        return $type . $sn . $id;
+    }
+
+}

+ 78 - 0
application/admin/model/lottery/Info.php

@@ -0,0 +1,78 @@
+<?php
+
+namespace app\admin\model\lottery;
+
+use think\Model;
+use traits\model\SoftDelete;
+
+class Info extends Model
+{
+
+    use SoftDelete;
+
+    
+
+    // 表名
+    protected $name = 'luck_lottery';
+    
+    // 自动写入时间戳字段
+    protected $autoWriteTimestamp = 'integer';
+
+    // 定义时间戳字段名
+    protected $createTime = 'createtime';
+    protected $updateTime = 'updatetime';
+    protected $deleteTime = 'deletetime';
+
+    // 追加属性
+    protected $append = [
+        'type_text',
+        'start_time_text',
+        'end_time_text'
+    ];
+    
+
+    
+    public function getTypeList()
+    {
+        return ['1' => __('幸运大转盘')];
+    }
+
+
+    public function getTypeTextAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['type']) ? $data['type'] : '');
+        $list = $this->getTypeList();
+        return isset($list[$value]) ? $list[$value] : '';
+    }
+
+
+    public function getStartTimeTextAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['start_time']) ? $data['start_time'] : '');
+        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
+    }
+
+
+    public function getEndTimeTextAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['end_time']) ? $data['end_time'] : '');
+        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
+    }
+
+    protected function setStartTimeAttr($value)
+    {
+        return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
+    }
+
+    protected function setEndTimeAttr($value)
+    {
+        return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
+    }
+
+    public function prize()
+    {
+        return $this->hasMany(Prize::class, 'lottery_id', 'id');
+    }
+
+
+}

+ 62 - 0
application/admin/model/lottery/Prize.php

@@ -0,0 +1,62 @@
+<?php
+
+namespace app\admin\model\lottery;
+
+use think\Model;
+use traits\model\SoftDelete;
+
+class Prize extends Model
+{
+
+    use SoftDelete;
+
+    
+
+    // 表名
+    protected $name = 'luck_prize';
+    
+    // 自动写入时间戳字段
+    protected $autoWriteTimestamp = 'integer';
+
+    // 定义时间戳字段名
+    protected $createTime = 'createtime';
+    protected $updateTime = 'updatetime';
+    protected $deleteTime = 'deletetime';
+
+    // 追加属性
+    protected $append = [
+        'type_text',
+        'image_full_url'
+    ];
+    
+
+    
+    public function getTypeList()
+    {
+        return ['1' => __('未中奖'),  '4' => __('红包')];
+    }
+
+
+    public function getTypeTextAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['type']) ? $data['type'] : '');
+        $list = $this->getTypeList();
+        return isset($list[$value]) ? $list[$value] : '';
+    }
+
+    public function getImageFullUrlAttr($value, $data)
+    {
+        $value = $value ?:  (isset($data['image']) ? $data['image'] : '');
+        return cdnurl($value, true);
+    }
+
+
+    public function lottery()
+    {
+        return $this->belongsTo(Info::class, 'lottery_id', 'id');
+    }
+
+
+
+
+}

+ 103 - 0
application/admin/model/lottery/Record.php

@@ -0,0 +1,103 @@
+<?php
+
+namespace app\admin\model\lottery;
+
+use app\admin\model\User;
+use think\Model;
+use traits\model\SoftDelete;
+
+class Record extends Model
+{
+
+    use SoftDelete;
+
+    
+
+    // 表名
+    protected $name = 'luck_lottery_record';
+    
+    // 自动写入时间戳字段
+    protected $autoWriteTimestamp = 'integer';
+
+    // 定义时间戳字段名
+    protected $createTime = 'createtime';
+    protected $updateTime = 'updatetime';
+    protected $deleteTime = 'deletetime';
+
+    // 追加属性
+    protected $append = [
+        'receive_time_text',
+        'deliver_time_text',
+        'create_time_text',
+        'type_text'
+    ];
+
+    public function getTypeList()
+    {
+        return ['1' => __('未中奖'),  '4' => __('红包')];
+    }
+    public function getTypeTextAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['type']) ? $data['type'] : '');
+        $list = $this->getTypeList();
+        return isset($list[$value]) ? $list[$value] : '';
+    }
+    public function getReceiveTimeTextAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['receive_time']) ? $data['receive_time'] : '');
+        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
+    }
+
+    public function getCreateTimeTextAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['createtime']) ? $data['createtime'] : '');
+        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
+    }
+
+
+    public function getDeliverTimeTextAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['deliver_time']) ? $data['deliver_time'] : '');
+        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
+    }
+
+    protected function setReceiveTimeAttr($value)
+    {
+        return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
+    }
+
+    protected function setDeliverTimeAttr($value)
+    {
+        return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
+    }
+
+    /**
+     * 关联抽奖
+     * @return \think\model\relation\HasOne
+     */
+    public function lottery()
+    {
+        return $this->hasOne(Info::class, 'id', 'lottery_id')->setEagerlyType(0)->field('id,name');
+    }
+
+    /**
+     * 关联奖品
+     * @return \think\model\relation\HasOne
+     */
+    public function prize()
+    {
+        return $this->hasOne(Prize::class, 'id', 'prize_id')->setEagerlyType(0)->field('id,name,image,type');
+    }
+
+    /**
+     * 关联用户
+     * @return \think\model\relation\HasOne
+     */
+    public function user()
+    {
+        return $this->hasOne(User::class, 'id', 'user_id')->setEagerlyType(0)->field('id,username,nickname,mobile,avatar');
+    }
+
+
+
+}

+ 25 - 0
application/admin/model/lottery/RedbagLog.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace app\admin\model\lottery;
+
+use think\Model;
+
+
+class RedbagLog extends Model
+{
+
+
+    
+
+    // 表名
+    protected $name = 'lottery_redbag_log';
+    
+    // 自动写入时间戳字段
+    protected $autoWriteTimestamp = 'integer';
+
+    // 定义时间戳字段名
+    protected $createTime = 'createtime';
+
+
+
+}

+ 27 - 0
application/admin/validate/lottery/Info.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace app\admin\validate\lottery;
+
+use think\Validate;
+
+class Info extends Validate
+{
+    /**
+     * 验证规则
+     */
+    protected $rule = [
+    ];
+    /**
+     * 提示消息
+     */
+    protected $message = [
+    ];
+    /**
+     * 验证场景
+     */
+    protected $scene = [
+        'add'  => [],
+        'edit' => [],
+    ];
+    
+}

+ 27 - 0
application/admin/validate/lottery/Prize.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace app\admin\validate\lottery;
+
+use think\Validate;
+
+class Prize extends Validate
+{
+    /**
+     * 验证规则
+     */
+    protected $rule = [
+    ];
+    /**
+     * 提示消息
+     */
+    protected $message = [
+    ];
+    /**
+     * 验证场景
+     */
+    protected $scene = [
+        'add'  => [],
+        'edit' => [],
+    ];
+    
+}

+ 27 - 0
application/admin/validate/lottery/Record.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace app\admin\validate\lottery;
+
+use think\Validate;
+
+class Record extends Validate
+{
+    /**
+     * 验证规则
+     */
+    protected $rule = [
+    ];
+    /**
+     * 提示消息
+     */
+    protected $message = [
+    ];
+    /**
+     * 验证场景
+     */
+    protected $scene = [
+        'add'  => [],
+        'edit' => [],
+    ];
+    
+}

+ 69 - 0
application/admin/view/lottery/info/add.html

@@ -0,0 +1,69 @@
+<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
+
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text" value="">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Start_time')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-start_time" data-rule="required" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[start_time]" type="text" value="{:date('Y-m-d H:i:s')}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('End_time')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-end_time" data-rule="required" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[end_time]" type="text" value="{:date('Y-m-d H:i:s')}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Desc')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-desc" data-rule="required" class="form-control" name="row[desc]" type="text" value="">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="input-group">
+                <input id="c-image" data-rule="required" class="form-control" size="50" name="row[image]" type="text" value="">
+                <div class="input-group-addon no-border no-padding">
+                    <span><button type="button" id="faupload-image" class="btn btn-danger faupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
+                    <span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
+                </div>
+                <span class="msg-box n-right" for="c-image"></span>
+            </div>
+            <ul class="row list-inline faupload-preview" id="p-image"></ul>
+        </div>
+    </div>
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Lottery_num_term')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-lottery_num_term" data-rule="required" class="form-control" name="row[lottery_num_term]" type="number" value="1">
+        </div>
+    </div>
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea id="c-content" class="form-control editor" rows="5" name="row[content]" cols="50"></textarea>
+        </div>
+    </div>
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Sort')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-sort" data-rule="required" class="form-control" name="row[sort]" type="number" value="0">
+        </div>
+    </div>
+    <div class="form-group layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
+        </div>
+    </div>
+</form>

+ 72 - 0
application/admin/view/lottery/info/edit.html

@@ -0,0 +1,72 @@
+<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
+
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text" value="{$row.name|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Start_time')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-start_time" data-rule="required" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[start_time]" type="text" value="{:$row.start_time?datetime($row.start_time):''}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('End_time')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-end_time" data-rule="required" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[end_time]" type="text" value="{:$row.end_time?datetime($row.end_time):''}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Desc')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-desc" data-rule="required" class="form-control" name="row[desc]" type="text" value="{$row.desc|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="input-group">
+                <input id="c-image" data-rule="required" class="form-control" size="50" name="row[image]" type="text" value="{$row.image|htmlentities}">
+                <div class="input-group-addon no-border no-padding">
+                    <span><button type="button" id="faupload-image" class="btn btn-danger faupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
+                    <span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
+                </div>
+                <span class="msg-box n-right" for="c-image"></span>
+            </div>
+            <ul class="row list-inline faupload-preview" id="p-image"></ul>
+        </div>
+    </div>
+
+
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Lottery_num_term')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-lottery_num_term" data-rule="required" class="form-control" name="row[lottery_num_term]" type="number" value="{$row.lottery_num_term|htmlentities}">
+        </div>
+    </div>
+
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea id="c-content" class="form-control editor" rows="5" name="row[content]" cols="50">{$row.content|htmlentities}</textarea>
+        </div>
+    </div>
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Sort')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-sort" data-rule="required" class="form-control" name="row[sort]" type="number" value="{$row.sort|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
+        </div>
+    </div>
+</form>

+ 29 - 0
application/admin/view/lottery/info/index.html

@@ -0,0 +1,29 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        <a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
+                        <a href="javascript:;" class="btn btn-success btn-add {:$auth->check('lottery/info/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
+                        <a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('lottery/info/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
+                        <a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('lottery/info/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
+                        
+
+                        
+
+                        <a class="btn btn-success btn-recyclebin btn-dialog {:$auth->check('lottery/info/recyclebin')?'':'hide'}" href="lottery/info/recyclebin" title="{:__('Recycle bin')}"><i class="fa fa-recycle"></i> {:__('Recycle bin')}</a>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover table-nowrap"
+                           data-operate-edit="{:$auth->check('lottery/info/edit')}"
+                           data-operate-del="{:$auth->check('lottery/info/del')}"
+                           width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 25 - 0
application/admin/view/lottery/info/recyclebin.html

@@ -0,0 +1,25 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar('refresh')}
+                        <a class="btn btn-info btn-multi btn-disabled disabled {:$auth->check('lottery/info/restore')?'':'hide'}" href="javascript:;" data-url="lottery/info/restore" data-action="restore"><i class="fa fa-rotate-left"></i> {:__('Restore')}</a>
+                        <a class="btn btn-danger btn-multi btn-disabled disabled {:$auth->check('lottery/info/destroy')?'':'hide'}" href="javascript:;" data-url="lottery/info/destroy" data-action="destroy"><i class="fa fa-times"></i> {:__('Destroy')}</a>
+                        <a class="btn btn-success btn-restoreall {:$auth->check('lottery/info/restore')?'':'hide'}" href="javascript:;" data-url="lottery/info/restore" title="{:__('Restore all')}"><i class="fa fa-rotate-left"></i> {:__('Restore all')}</a>
+                        <a class="btn btn-danger btn-destroyall {:$auth->check('lottery/info/destroy')?'':'hide'}" href="javascript:;" data-url="lottery/info/destroy" title="{:__('Destroy all')}"><i class="fa fa-times"></i> {:__('Destroy all')}</a>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover"
+                           data-operate-restore="{:$auth->check('lottery/info/restore')}"
+                           data-operate-destroy="{:$auth->check('lottery/info/destroy')}"
+                           width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 87 - 0
application/admin/view/lottery/prize/add.html

@@ -0,0 +1,87 @@
+<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
+        <div class="col-xs-12 col-sm-8">
+                        
+            <select  id="c-type" data-rule="required" class="form-control selectpicker" name="row[type]">
+                {foreach name="typeList" item="vo"}
+                    <option value="{$key}" {in name="key" value="1"}selected{/in}>{$vo}</option>
+                {/foreach}
+            </select>
+
+        </div>
+    </div>
+    <div class="form-group" data-favisible="type=4">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Num')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-num" data-rule="required" class="form-control" name="row[num]" type="number" value="0">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Lottery_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-lottery_id"  data-source="lottery.info/index"
+                   class="form-control selectpage" name="row[lottery_id]"
+                   type="text"
+                   value="">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text" value="">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Prompt')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-prompt" data-rule="required" class="form-control" name="row[prompt]" type="text" value="">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="input-group">
+                <input id="c-image" data-rule="required" class="form-control" size="50" name="row[image]" type="text" value="">
+                <div class="input-group-addon no-border no-padding">
+                    <span><button type="button" id="faupload-image" class="btn btn-danger faupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
+                    <span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
+                </div>
+                <span class="msg-box n-right" for="c-image"></span>
+            </div>
+            <ul class="row list-inline faupload-preview" id="p-image"></ul>
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Chance')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-chance" data-rule="required" class="form-control" name="row[chance]" type="number" value="10">
+            <p class="text-info">* 不是抽奖活动时,答题抽奖排行与这无关</p>
+        </div>
+
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Total')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-total" data-rule="required" class="form-control" name="row[total]" type="number" value="1">
+            <p class="text-info">* 不是抽奖活动时,答题抽奖排行与这无关</p>
+        </div>
+
+    </div>
+
+
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Sort')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-sort" data-rule="required" class="form-control" name="row[sort]" type="number" value="0">
+        </div>
+    </div>
+    <div class="form-group layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
+        </div>
+    </div>
+</form>

+ 84 - 0
application/admin/view/lottery/prize/edit.html

@@ -0,0 +1,84 @@
+<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
+        <div class="col-xs-12 col-sm-8">
+                        
+            <select  id="c-type" data-rule="required" class="form-control selectpicker" name="row[type]">
+                {foreach name="typeList" item="vo"}
+                    <option value="{$key}" {in name="key" value="$row.type"}selected{/in}>{$vo}</option>
+                {/foreach}
+            </select>
+
+        </div>
+    </div>
+    <div class="form-group" data-favisible="type=4">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Num')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-num" data-rule="required" class="form-control" name="row[num]" type="number" value="{$row.num|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Lottery_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-lottery_id"  data-source="lottery.info/index" class="form-control selectpage" name="row[lottery_id]" type="text" value="{$row.lottery_id|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text" value="{$row.name|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Prompt')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-prompt" data-rule="required" class="form-control" name="row[prompt]" type="text" value="{$row.prompt|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="input-group">
+                <input id="c-image" data-rule="required" class="form-control" size="50" name="row[image]" type="text" value="{$row.image|htmlentities}">
+                <div class="input-group-addon no-border no-padding">
+                    <span><button type="button" id="faupload-image" class="btn btn-danger faupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
+                    <span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
+                </div>
+                <span class="msg-box n-right" for="c-image"></span>
+            </div>
+            <ul class="row list-inline faupload-preview" id="p-image"></ul>
+        </div>
+    </div>
+    <div class="form-group"  >
+        <label class="control-label col-xs-12 col-sm-2">{:__('Chance')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-chance" data-rule="required" class="form-control" name="row[chance]" type="number" value="{$row.chance|htmlentities}">
+            <p class="text-info">* 不是抽奖活动时,答题抽奖排行与这无关</p>
+        </div>
+
+    </div>
+    <div class="form-group" >
+        <label class="control-label col-xs-12 col-sm-2">{:__('Total')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-total" data-rule="required" class="form-control" name="row[total]" type="number" value="{$row.total|htmlentities}">
+            <p class="text-info">* 不是抽奖活动时,答题抽奖排行与这无关</p>
+        </div>
+
+    </div>
+
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Sort')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-sort" data-rule="required" class="form-control" name="row[sort]" type="number" value="{$row.sort|htmlentities}">
+        </div>
+    </div>
+
+    <div class="form-group layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
+        </div>
+    </div>
+</form>

+ 29 - 0
application/admin/view/lottery/prize/index.html

@@ -0,0 +1,29 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        <a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
+                        <a href="javascript:;" class="btn btn-success btn-add {:$auth->check('lottery/prize/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
+                        <a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('lottery/prize/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
+                        <a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('lottery/prize/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
+                        
+
+                        
+
+                        <a class="btn btn-success btn-recyclebin btn-dialog {:$auth->check('lottery/prize/recyclebin')?'':'hide'}" href="lottery/prize/recyclebin" title="{:__('Recycle bin')}"><i class="fa fa-recycle"></i> {:__('Recycle bin')}</a>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover table-nowrap"
+                           data-operate-edit="{:$auth->check('lottery/prize/edit')}"
+                           data-operate-del="{:$auth->check('lottery/prize/del')}"
+                           width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 25 - 0
application/admin/view/lottery/prize/recyclebin.html

@@ -0,0 +1,25 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar('refresh')}
+                        <a class="btn btn-info btn-multi btn-disabled disabled {:$auth->check('lottery/prize/restore')?'':'hide'}" href="javascript:;" data-url="lottery/prize/restore" data-action="restore"><i class="fa fa-rotate-left"></i> {:__('Restore')}</a>
+                        <a class="btn btn-danger btn-multi btn-disabled disabled {:$auth->check('lottery/prize/destroy')?'':'hide'}" href="javascript:;" data-url="lottery/prize/destroy" data-action="destroy"><i class="fa fa-times"></i> {:__('Destroy')}</a>
+                        <a class="btn btn-success btn-restoreall {:$auth->check('lottery/prize/restore')?'':'hide'}" href="javascript:;" data-url="lottery/prize/restore" title="{:__('Restore all')}"><i class="fa fa-rotate-left"></i> {:__('Restore all')}</a>
+                        <a class="btn btn-danger btn-destroyall {:$auth->check('lottery/prize/destroy')?'':'hide'}" href="javascript:;" data-url="lottery/prize/destroy" title="{:__('Destroy all')}"><i class="fa fa-times"></i> {:__('Destroy all')}</a>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover"
+                           data-operate-restore="{:$auth->check('lottery/prize/restore')}"
+                           data-operate-destroy="{:$auth->check('lottery/prize/destroy')}"
+                           width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 69 - 0
application/admin/view/lottery/record/add.html

@@ -0,0 +1,69 @@
+<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('User_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-user_id" data-rule="required" data-source="user/user/index" data-field="nickname" class="form-control selectpage" name="row[user_id]" type="text" value="">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Lottery_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-lottery_id" data-rule="required" data-source="lottery/index" class="form-control selectpage" name="row[lottery_id]" type="text" value="">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Prize_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-prize_id" data-rule="required" data-source="prize/index" class="form-control selectpage" name="row[prize_id]" type="text" value="">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-type" data-rule="required" class="form-control" name="row[type]" type="number" value="1">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Is_receive')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-is_receive" data-rule="required" class="form-control" name="row[is_receive]" type="number" value="0">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Receive_time')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-receive_time" data-rule="required" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[receive_time]" type="text" value="{:date('Y-m-d H:i:s')}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Receive_info')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea id="c-receive_info" class="form-control " rows="5" name="row[receive_info]" cols="50"></textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Is_deliver')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-is_deliver" data-rule="required" class="form-control" name="row[is_deliver]" type="number" value="0">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Deliver_time')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-deliver_time" data-rule="required" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[deliver_time]" type="text" value="{:date('Y-m-d H:i:s')}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Deliver_info')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea id="c-deliver_info" class="form-control " rows="5" name="row[deliver_info]" cols="50"></textarea>
+        </div>
+    </div>
+    <div class="form-group layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
+        </div>
+    </div>
+</form>

+ 69 - 0
application/admin/view/lottery/record/edit.html

@@ -0,0 +1,69 @@
+<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('User_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-user_id" data-rule="required" data-source="user/user/index" data-field="nickname" class="form-control selectpage" name="row[user_id]" type="text" value="{$row.user_id|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Lottery_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-lottery_id" data-rule="required" data-source="lottery/index" class="form-control selectpage" name="row[lottery_id]" type="text" value="{$row.lottery_id|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Prize_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-prize_id" data-rule="required" data-source="prize/index" class="form-control selectpage" name="row[prize_id]" type="text" value="{$row.prize_id|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-type" data-rule="required" class="form-control" name="row[type]" type="number" value="{$row.type|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Is_receive')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-is_receive" data-rule="required" class="form-control" name="row[is_receive]" type="number" value="{$row.is_receive|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Receive_time')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-receive_time" data-rule="required" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[receive_time]" type="text" value="{:$row.receive_time?datetime($row.receive_time):''}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Receive_info')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea id="c-receive_info" class="form-control " rows="5" name="row[receive_info]" cols="50">{$row.receive_info|htmlentities}</textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Is_deliver')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-is_deliver" data-rule="required" class="form-control" name="row[is_deliver]" type="number" value="{$row.is_deliver|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Deliver_time')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-deliver_time" data-rule="required" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[deliver_time]" type="text" value="{:$row.deliver_time?datetime($row.deliver_time):''}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Deliver_info')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea id="c-deliver_info" class="form-control " rows="5" name="row[deliver_info]" cols="50">{$row.deliver_info|htmlentities}</textarea>
+        </div>
+    </div>
+    <div class="form-group layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
+        </div>
+    </div>
+</form>

+ 27 - 0
application/admin/view/lottery/record/index.html

@@ -0,0 +1,27 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        <a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
+
+                        
+
+                        
+
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover table-nowrap"
+                           data-operate-edit="{:$auth->check('lottery/record/edit')}"
+                           data-operate-del="{:$auth->check('lottery/record/del')}"
+                           data-operate-deliver="{:$auth->check('lottery/record/deliver')}"
+                           width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 25 - 0
application/admin/view/lottery/record/recyclebin.html

@@ -0,0 +1,25 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar('refresh')}
+                        <a class="btn btn-info btn-multi btn-disabled disabled {:$auth->check('lottery/record/restore')?'':'hide'}" href="javascript:;" data-url="lottery/record/restore" data-action="restore"><i class="fa fa-rotate-left"></i> {:__('Restore')}</a>
+                        <a class="btn btn-danger btn-multi btn-disabled disabled {:$auth->check('lottery/record/destroy')?'':'hide'}" href="javascript:;" data-url="lottery/record/destroy" data-action="destroy"><i class="fa fa-times"></i> {:__('Destroy')}</a>
+                        <a class="btn btn-success btn-restoreall {:$auth->check('lottery/record/restore')?'':'hide'}" href="javascript:;" data-url="lottery/record/restore" title="{:__('Restore all')}"><i class="fa fa-rotate-left"></i> {:__('Restore all')}</a>
+                        <a class="btn btn-danger btn-destroyall {:$auth->check('lottery/record/destroy')?'':'hide'}" href="javascript:;" data-url="lottery/record/destroy" title="{:__('Destroy all')}"><i class="fa fa-times"></i> {:__('Destroy all')}</a>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover"
+                           data-operate-restore="{:$auth->check('lottery/record/restore')}"
+                           data-operate-destroy="{:$auth->check('lottery/record/destroy')}"
+                           width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 85 - 0
application/api/controller/LuckLottery.php

@@ -0,0 +1,85 @@
+<?php
+
+
+namespace app\api\controller;
+
+
+use app\common\controller\Api;
+use think\Cache;
+use think\Request;
+use app\services\lottery\LuckLotteryRecordServices;
+use app\services\lottery\LuckLotteryServices;
+
+
+class LuckLottery extends Api
+{
+    protected $noNeedRight = ['*'];
+    protected $services;
+
+    public function __construct(LuckLotteryServices $services)
+    {
+        parent::__construct();
+        $this->services = $services;
+    }
+    /**
+     * 抽奖活动信息
+     * @param Request $request
+     */
+    public function LotteryInfo(Request $request)
+    {
+        $id = $request->get('id','1');
+        if (intval($id) <= 0) return  $this->error('请上传抽奖ID');
+        $lottery = $this->services->getLottery($id, '*', ['prize'], true);
+        if (!$lottery) {
+            $this->error('未获取到抽奖活动');
+        }
+        $lottery = $lottery->toArray();
+        $lotteryData = ['lottery' => $lottery];
+        $lotteryData['lottery_num'] = $this->auth->lottery_num ?? 0;
+        $this->success('获取成功', $lotteryData);
+    }
+
+    /**
+     * 参与抽奖
+     * @param Request $request
+     * @return mixed
+     */
+    public function luckLottery(Request $request)
+    {
+        $id = $request->get('id','1');
+        if (!$id) {
+            $this->error('请上传抽奖ID');
+        }
+        if ($this->auth->lottery_num <=0){
+            $this->error('抽奖次数不足');
+        }
+        $uid =$this->auth->id;
+        $key = 'lucklotter_limit_' . $uid;
+        if (Cache::get($key)) {
+            $this->error('您求的频率太过频繁,请稍后请求!');
+        }
+        Cache::set('lucklotter_limit_' . $uid, $uid, 1);
+
+        $arrUserinfo = $this->auth->getUser()->toArray();
+        list($nError,$arrData) = $this->services->luckLottery($arrUserinfo, $id);
+        if ($nError === 1 ) {
+            $this->error($arrData);
+        }
+        $this->success('', $arrData);
+    }
+
+    /**
+     * 获取抽奖记录
+     * @param Request $request
+     * @return mixed
+     */
+    public function lotteryRecord(Request $request)
+    {
+        $uid      = $this->auth->id;
+        $pageSize = (int)$this->request->param('pageSize', 10);
+        $page     = (int)$this->request->param('page', 1);
+        $lotteryRecordServices = new LuckLotteryRecordServices();
+        $arrData = $lotteryRecordServices->getRecord($uid,$page,$pageSize);
+        $this->success('', $arrData);
+    }
+}

+ 36 - 49
application/api/controller/Order.php

@@ -31,27 +31,25 @@ class Order extends Base
         }
         
         $config = get_addon_config('shop');
-        $type = $this->request->post('type'); // 计算类型:cart 或 goods
         $address_id = $this->request->post('address_id/d'); // 地址id
         $user_coupon_id = $this->request->post('user_coupon_id/d'); // 优惠券
+        $cart_ids = $this->request->post('cart_ids/a'); // 购物车ID数组
+        $goods_list = $this->request->post('goods_list/a'); // 商品列表
         
         $address = Address::get($address_id);
         $area_id = !empty($address) ? $address->area_id : 0;
         
         try {
-            // 根据类型获取标准化的商品列表
-            if ($type === 'cart') {
+            // 自动判断数据源类型并获取标准化的商品列表
+            if (!empty($cart_ids)) {
                 // 购物车模式:先转换为商品列表
-                $cart_ids = $this->request->post('cart_ids/a');
-                $goods_list = \app\common\Service\OrderService::convertCartToGoodsList($cart_ids, $this->auth->id);
-            } else {
-                // 商品规格模式:直接使用商品列表
-                $goods_list = $this->request->post('goods_list/a');
+                $goods_list = \app\common\Service\Cart::convertCartToGoodsList($cart_ids, $this->auth->id);
+            } elseif (empty($goods_list)) {
+                throw new \Exception("请提供购物车ID或商品列表");
             }
             
             // 统一调用计算方法
             $result = \app\common\Service\OrderService::calculateOrder($goods_list, $this->auth->id, $area_id, $user_coupon_id);
-            
             $orderItem = $result['orderItem'];
             $goodsList = $result['goodsList'];
             $orderInfo = $result['orderInfo'];
@@ -72,20 +70,19 @@ class Order extends Base
         }
         
         // 获取我的可以使用的优惠券
-        $goods_ids = array_column($goodsList, 'goods_id');
+        $goods_ids    = array_column($goodsList, 'goods_id');
         $category_ids = array_column($goodsList, 'category_id');
-        $brand_ids = array_column($goodsList, 'brand_id');
+        $brand_ids    = array_column($goodsList, 'brand_id');
 
         $this->success('获取成功', [
             'coupons'          => UserCoupon::myGoodsCoupon($this->auth->id, $goods_ids, $category_ids, $brand_ids),
             'goods_list'       => $goodsList,
-            'order_info'       => $orderInfo,
-            'couponTotalPrice' => floatval(!isset($config['shippingfeecoupon']) || $config['shippingfeecoupon'] == 0 ? $orderInfo['goodsprice'] : $orderInfo['amount'])
+            'order_info'       => $orderInfo,            
         ]);
     }
 
 
-    //提交订单 - 通过购物车
+    //提交订单 - 统一接口
     public function create()
     {
         // 验证请求参数
@@ -94,45 +91,35 @@ class Order extends Base
             $this->error($validate->getError());
         }
         
-        $cart_ids = $this->request->post('ids');
-        $address_id = $this->request->post('address_id/d'); //地址id
-        $user_coupon_id = $this->request->post('user_coupon_id/d'); //优惠券id
-        $memo = $this->request->post('memo');
-        
-        //为购物车id
-        //校验购物车id 合法
-        $row = (new Carts)->where('id', 'IN', $cart_ids)->where('user_id', '<>', $this->auth->id)->find();
-        if ($row) {
-            $this->error('存在不合法购物车数据');
-        }
-        
-        $order = null;
-        try {
-            $order = \app\common\Service\OrderService::createOrderByCart($address_id, $this->auth->id, $cart_ids, $user_coupon_id, $memo);
-        } catch (\Exception $e) {
-            $this->error($e->getMessage());
-        }
-        
-        $this->success('下单成功!', array_intersect_key($order->toArray(), array_flip(['order_sn', 'paystate'])));
-    }
-
-    //直接提交订单 - 通过商品规格
-    public function createByGoods()
-    {
-        // 验证请求参数
-        $validate = new \app\api\validate\Order();
-        if (!$validate->scene('createByGoods')->check($this->request->post())) {
-            $this->error($validate->getError());
-        }
-        
-        $goods_list = $this->request->post('goods_list/a'); // 商品列表
         $address_id = $this->request->post('address_id/d'); // 地址id
         $user_coupon_id = $this->request->post('user_coupon_id/d'); // 优惠券id
-        $memo = $this->request->post('memo'); // 备注
+        $remark = $this->request->post('remark','','trim'); // 备注
+        $cart_ids = $this->request->post('cart_ids/a'); // 购物车ID数组
+        $goods_list = $this->request->post('goods_list/a'); // 商品列表
         
+        $order = null;
         try {
-            // 创建订单
-            $order = \app\common\Service\OrderService::createOrderByGoods($address_id, $this->auth->id, $goods_list, $user_coupon_id, $memo);
+            if (!empty($cart_ids)) {
+                // 购物车模式 - 校验购物车id合法性
+                $row = (new Carts)->where('id', 'IN', $cart_ids)->where('user_id', '<>', $this->auth->id)->find();
+                if ($row) {
+                    $this->error('存在不合法购物车数据');
+                }
+                
+                // 先转换购物车为商品列表
+                $goods_list = \app\common\Service\Cart::convertCartToGoodsList($cart_ids, $this->auth->id);
+                
+                // 创建订单
+                $order = \app\common\Service\OrderService::createOrder($address_id, $this->auth->id, $goods_list, $user_coupon_id, $remark);
+                
+                // 购物车订单创建成功后清理购物车
+                \app\common\Service\Cart::clear($cart_ids);
+            } elseif (!empty($goods_list)) {
+                // 商品列表模式 - 直接创建订单
+                $order = \app\common\Service\OrderService::createOrder($address_id, $this->auth->id, $goods_list, $user_coupon_id, $remark);
+            } else {
+                $this->error('请提供购物车ID或商品列表');
+            }
         } catch (\Exception $e) {
             $this->error($e->getMessage());
         }

+ 67 - 21
application/api/validate/Order.php

@@ -25,12 +25,12 @@ class Order extends Validate
         'goods_list.*.goods_sku_id' => 'integer|egt:0',
         'goods_list.*.nums'         => 'require|integer|gt:0',
         
-        // 计算类型
-        'type'            => 'require|in:cart,goods',
-        
         // 计算订单数据验证
         'calculate_data'  => 'checkCalculateData',
         
+        // 创建订单数据验证
+        'create_data'     => 'checkCreateData',
+        
         // 订单操作相关
         'order_sn'        => 'require|alphaNum',
         'paytype'         => 'require|in:alipay,wechat,unionpay,balance',
@@ -67,8 +67,7 @@ class Order extends Validate
         'goods_list.*.nums.integer'     => '商品数量必须是整数',
         'goods_list.*.nums.gt'          => '商品数量必须大于0',
         
-        // 计算类型
-        'type.require'      => '计算类型不能为空',
+        // 计算类型(已废弃,保持兼容性)
         'type.in'           => '计算类型只能是cart或goods',
         
         // 订单操作相关
@@ -84,12 +83,10 @@ class Order extends Validate
      * 验证场景
      */
     protected $scene = [
-        // 通过购物车创建订单
-        'create'            => ['ids', 'address_id', 'user_coupon_id', 'memo'],
-        // 通过商品规格创建订单
-        'createByGoods'     => ['goods_list', 'address_id', 'user_coupon_id', 'memo'],
+        // 统一创建订单接口(支持购物车和商品规格两种模式)
+        'create'            => ['address_id', 'user_coupon_id', 'memo', 'create_data'],
         // 计算订单(支持购物车和商品规格两种模式)
-        'calculate'         => ['type', 'address_id', 'user_coupon_id', 'calculate_data'],
+        'calculate'         => ['address_id', 'user_coupon_id', 'calculate_data'],
         // 订单详情、确认收货、查询物流
         'detail'            => ['order_sn'],
         // 取消订单
@@ -147,21 +144,70 @@ class Order extends Validate
      */
     protected function checkCalculateData($value, $rule, $data)
     {
-        // 验证type参数
-        if (!isset($data['type']) || !in_array($data['type'], ['cart', 'goods'])) {
-            return '计算类型只能是cart或goods';
+        // 必须提供购物车ID或商品列表其中之一
+        $hasCartIds = isset($data['cart_ids']) && is_array($data['cart_ids']) && !empty($data['cart_ids']);
+        $hasGoodsList = isset($data['goods_list']) && is_array($data['goods_list']) && !empty($data['goods_list']);
+        
+        if (!$hasCartIds && !$hasGoodsList) {
+            return '请提供购物车ID或商品列表';
+        }
+        
+        if ($hasCartIds && $hasGoodsList) {
+            return '不能同时提供购物车ID和商品列表';
         }
         
-        // 根据type验证对应参数
-        if ($data['type'] === 'cart') {
-            if (!isset($data['cart_ids']) || !is_array($data['cart_ids']) || empty($data['cart_ids'])) {
-                return '购物车ID列表不能为空';
+        // 验证购物车ID格式
+        if ($hasCartIds) {
+            foreach ($data['cart_ids'] as $index => $cart_id) {
+                if (!is_numeric($cart_id) || $cart_id <= 0) {
+                    return "购物车ID第" . ($index + 1) . "项格式错误";
+                }
             }
-        } elseif ($data['type'] === 'goods') {
-            if (!isset($data['goods_list']) || !is_array($data['goods_list']) || empty($data['goods_list'])) {
-                return '商品列表不能为空';
+        }
+        
+        // 验证商品列表格式
+        if ($hasGoodsList) {
+            $result = $this->checkGoodsList($data['goods_list'], '', $data);
+            if ($result !== true) {
+                return $result;
+            }
+        }
+        
+        return true;
+    }
+
+    /**
+     * 自定义验证规则:验证创建订单参数
+     * @param $value
+     * @param $rule
+     * @param $data
+     * @return bool|string
+     */
+    protected function checkCreateData($value, $rule, $data)
+    {
+        // 必须提供购物车ID或商品列表其中之一
+        $hasCartIds = isset($data['cart_ids']) && is_array($data['cart_ids']) && !empty($data['cart_ids']);
+        $hasGoodsList = isset($data['goods_list']) && is_array($data['goods_list']) && !empty($data['goods_list']);
+        
+        if (!$hasCartIds && !$hasGoodsList) {
+            return '请提供购物车ID或商品列表';
+        }
+        
+        if ($hasCartIds && $hasGoodsList) {
+            return '不能同时提供购物车ID和商品列表';
+        }
+        
+        // 验证购物车ID格式
+        if ($hasCartIds) {
+            foreach ($data['cart_ids'] as $index => $cart_id) {
+                if (!is_numeric($cart_id) || $cart_id <= 0) {
+                    return "购物车ID第" . ($index + 1) . "项格式错误";
+                }
             }
-            // 验证商品列表格式
+        }
+        
+        // 验证商品列表格式
+        if ($hasGoodsList) {
             $result = $this->checkGoodsList($data['goods_list'], '', $data);
             if ($result !== true) {
                 return $result;

+ 8 - 0
application/common/Enum/CachEnum.php

@@ -0,0 +1,8 @@
+<?php
+
+namespace app\common\Enum;
+
+class CachEnums
+{
+
+}

+ 75 - 0
application/common/Enum/OrderEnum.php

@@ -0,0 +1,75 @@
+<?php
+
+namespace app\common\Enum;
+
+class OrderEnum
+{
+    /**
+     * 订单状态
+     */
+    const STATUS_CREATE = 101; //待付款
+    const STATUS_PAY = 201; //已付款
+    const STATUS_SHIP = 301; //已发货
+    const STATUS_CONFIRM = 401; //已收货
+    const STATUS_AUTO_CONFIRM = 402;
+
+    const STATUS_CANCEL = 102;
+    const STATUS_AUTO_CANCEL = 103;
+    const STATUS_ADMIN_CANCEL = 104;
+    const STATUS_REFUND = 202;
+    const STATUS_REFUND_CONFIRM = 203;
+    const STATUS_GROUPON_TIMEOUT = 204;
+
+
+    /**
+     * 订单枚举map
+     */
+    const STATUS_TEXT_MAP = [
+        self::STATUS_CREATE => '未付款',
+        self::STATUS_CANCEL => "已取消",
+        self::STATUS_AUTO_CANCEL => "已取消(系统)",
+        self::STATUS_ADMIN_CANCEL => "已取消(管理员)",
+        self::STATUS_PAY => "已付款",
+        self::STATUS_REFUND => "订单取消,退款中",
+        self::STATUS_REFUND_CONFIRM => "已退款",
+        self::STATUS_GROUPON_TIMEOUT => "已超时团购",
+        self::STATUS_SHIP => "已发货",
+        self::STATUS_CONFIRM => "已收货",
+        self::STATUS_AUTO_CONFIRM => "已收货(系统)",
+    ];
+
+
+    const SHOW_TYPE_ALL = 0;//全部订单
+    const SHOW_TYPE_WAIT_PAY = 1;//待付款订单
+    const SHOW_TYPE_WAIT_DELIVERY = 2;//待发货订单
+    const SHOW_TYPE_WAIT_RECEIPT = 3;//待收货订单
+
+    const SHOW_TYPE_WAIT_COMMENT = 4;//待评价订单
+
+
+    /**
+     * 订单枚举map
+     */
+    const SHOW_TYPE_STATUS_MAP = [
+        self::SHOW_TYPE_ALL => [],
+        self::SHOW_TYPE_WAIT_PAY => [self::STATUS_CREATE],
+        self::SHOW_TYPE_WAIT_DELIVERY => [self::STATUS_PAY],
+        self::SHOW_TYPE_WAIT_RECEIPT => [self::STATUS_SHIP],
+        self::SHOW_TYPE_WAIT_COMMENT => [self::STATUS_CONFIRM, self::STATUS_COMMENT],
+    ];
+
+
+    /**
+     * 支付方式 枚举
+     */
+    const METHOD_WALLET   = 'wallet';
+    const METHOD_WECHAT  = 'wechatv3';
+    /**
+     * 支付方式
+     */
+    const SHOW_PAY_TYPE_MAP = [
+        self::METHOD_WALLET => '余额支付',
+        self::METHOD_WECHAT => '微信支付',
+    ];
+
+}

+ 23 - 0
application/common/Enum/PayEnum.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace app\common\Enum;
+
+class PayEnum
+{
+  
+
+
+    /**
+     * 支付方式 枚举
+     */
+    const METHOD_WALLET   = 'wallet';
+    const METHOD_WECHAT  = 'wechatv3';
+    /**
+     * 支付方式
+     */
+    const SHOW_PAY_TYPE_MAP = [
+        self::METHOD_WALLET => '余额支付',
+        self::METHOD_WECHAT => '微信支付',
+    ];
+
+}

+ 0 - 73
application/common/model/Carts.php

@@ -21,79 +21,6 @@ class Carts extends Model
     // 追加属性
     protected $append = [];
 
-    /**
-     * @ DateTime 2021-05-31
-     * @ 获取购物车商品列表
-     * @param string  $ids
-     * @param integer $user_id
-     * @param integer $sceneval
-     * @return array
-     */
-    public static function getGoodsList($ids, $user_id)
-    {
-        return (new self())->field("c.*,GROUP_CONCAT(sp.name,':',sv.value order by sp.id asc) sku_attr")
-            ->with([
-                'Goods' => function ($query) {
-                    $query->where('status', 'normal');
-                },
-                'Sku'
-            ])
-            ->alias('c')
-            ->join('shop_goods_sku sku', 'c.goods_sku_id=sku.id', 'LEFT')
-            ->join('shop_goods_sku_spec p', "FIND_IN_SET(p.id,sku.sku_id)", 'LEFT')
-            ->join('shop_spec sp', 'sp.id=p.spec_id', 'LEFT')
-            ->join('shop_spec_value sv', 'sv.id=p.spec_value_id', 'LEFT')
-            ->where(function ($query) use ($ids) {
-                if ($ids) {
-                    $query->where('c.id', 'in', $ids);
-                }
-            })
-            ->where('c.user_id', $user_id)
-            ->order('c.createtime desc')
-            ->group('c.id')
-            ->select();
-    }
-
-    /**
-     * 添加商品到购物车
-     *
-     * @param string $goods_id     商品ID
-     * @param string $goods_sku_id 商品SKUID
-     * @param int    $nums         数量
-     * @param int    $user_id      会员ID
-     * @return mixed
-     */
-    public static function push($goods_id, $goods_sku_id, $nums = 1, $user_id = 0)
-    {
-
-        $row = (new self)->where('goods_id', $goods_id)
-            ->where('goods_sku_id', $goods_sku_id)
-            ->where('user_id', $user_id)
-            ->find();
-        //已存在,数量加
-        if ($row) {
-            $row->setInc('nums', $nums);
-        } else {
-            $row = (new self);
-            $row->save([
-                'goods_id'     => $goods_id,
-                'goods_sku_id' => $goods_sku_id,
-                'user_id'      => $user_id,
-                'nums'         => $nums
-            ]);
-        }
-        return $row->id;
-    }
-
-    /**
-     * 清空购物车
-     */
-    public static function clear($cart_ids)
-    {
-        self::where('id', 'IN', $cart_ids)->delete();
-    }
-
-
     public function Goods()
     {
         return $this->belongsTo('Goods', 'goods_id', 'id', [], 'LEFT');

+ 1 - 221
application/common/model/Order.php

@@ -133,227 +133,7 @@ class Order extends Model
     {
         return max(0, $data['expiretime'] - time());
     }
-
-    //计算购物车商品
-    public static function computeCarts(&$orderInfo, $cart_ids, $user_id, $area_id, $user_coupon_id = '')
-    {
-        $config = get_addon_config('shop');
-        $goodsList = Carts::getGoodsList($cart_ids, $user_id);
-        if (empty($goodsList)) {
-            throw new \Exception("未找到商品");
-        }
-        $orderInfo['amount'] = 0;
-        $orderInfo['goodsprice'] = 0;
-        $orderInfo['shippingfee'] = 0;
-        $orderInfo['discount'] = 0;
-        $orderItem = [];
-        $shippingTemp = [];
-        $userCoupon = null;
-        //校验领取和是否可使用
-        if ($user_coupon_id) {
-            $userCouponModel = new UserCoupon();
-            $userCoupon = $userCouponModel->checkUserOrUse($user_coupon_id, $user_id);
-            $orderInfo['user_coupon_id'] = $user_coupon_id;
-        }
-        //判断商品库存和状态
-        foreach ($goodsList as $item) {
-            $goodsItem = [];
-            if (empty($item->goods) && empty($item->sku)) {
-                throw new \Exception("商品已下架");
-            }
-            //规格
-            if ($item->goods_sku_id && empty($item->sku)) {
-                throw new \Exception("商品规格不存在");
-            }
-            if (!empty($item->sku)) { //规格计算
-                if ($item->sku->stocks < $item->nums) {
-                    throw new \Exception("有商品库存不足,请返回购物车重新修改");
-                }
-                $goodsItem['image'] = !empty($item->sku->image) ? $item->sku->image : $item->goods->image;
-                $goodsItem['price'] = $item->sku->price;
-                $goodsItem['marketprice'] = $item->sku->marketprice;
-                $goodsItem['goods_sn'] = $item->sku->goods_sn;
-                $amount = bcmul($item->sku->price, $item->nums, 2);
-            } else { //商品默认计算
-                if ($item->goods->stocks < $item->nums) {
-                    throw new \Exception("有商品库存不足,请返回购物车重新修改");
-                }
-                $goodsItem['image'] = !empty($item->sku->image) ? $item->sku->image : $item->goods->image;
-                $goodsItem['price'] = $item->goods->price;
-                $goodsItem['marketprice'] = $item->goods->marketprice;
-                $goodsItem['goods_sn'] = $item->goods->goods_sn;
-                $amount = bcmul($item->goods->price, $item->nums, 2);
-            }
-            $goodsItem['amount'] = $amount;
-            //订单总价
-            $orderInfo['amount'] = bcadd($orderInfo['amount'], $amount, 2);
-            //商品总价
-            $orderInfo['goodsprice'] = bcadd($orderInfo['goodsprice'], $amount, 2);
-
-            $freight_id = $item->goods->freight_id;
-            //计算邮费【合并运费模板】
-            if (!isset($shippingTemp[$freight_id])) {
-                $shippingTemp[$freight_id] = [
-                    'nums'   => $item->nums,
-                    'weight' => $item->goods->weight,
-                    'amount' => $amount
-                ];
-            } else {
-                $shippingTemp[$freight_id] = [
-                    'nums'   => bcadd($shippingTemp[$freight_id]['nums'], $item->nums, 2),
-                    'weight' => bcadd($shippingTemp[$freight_id]['weight'], $item->goods->weight, 2),
-                    'amount' => bcadd($shippingTemp[$freight_id]['amount'], $amount, 2)
-                ];
-            }
-            //创建订单商品数据
-            $orderItem[] = array_merge($goodsItem, [
-                'order_sn'     => $orderInfo['order_sn'],
-                'goods_id'     => $item->goods_id,
-                'title'        => $item->goods->title,
-                'url'          => $item->goods->url,
-                'nums'         => $item->nums,
-                'goods_sku_id' => $item->goods_sku_id,
-                'attrdata'     => $item->sku_attr,
-                'weight'       => $item->goods->weight,
-                'category_id'  => $item->goods->category_id,
-                'brand_id'     => $item->goods->brand_id,
-            ]);
-        }
-        //按运费模板计算
-        foreach ($shippingTemp as $key => $item) {
-            $shippingfee = Freight::calculate($key, $area_id, $item['nums'], $item['weight'], $item['amount']);
-            $orderInfo['shippingfee'] = bcadd($orderInfo['shippingfee'], $shippingfee, 2);
-        }
-
-        //订单总价(含邮费)
-        $orderInfo['amount'] = bcadd($orderInfo['goodsprice'], $orderInfo['shippingfee'], 2);
-
-        if (!empty($userCoupon)) {
-            //校验优惠券
-            $goods_ids = array_column($orderItem, 'goods_id');
-            $category_ids = array_column($orderItem, 'category_id');
-            $brand_ids = array_column($orderItem, 'brand_id');
-            $couponModel = new Coupon();
-            $coupon = $couponModel->getCoupon($userCoupon['coupon_id'])
-                ->checkCoupon()
-                ->checkOpen()
-                ->checkUseTime($userCoupon['createtime'])
-                ->checkConditionGoods($goods_ids, $user_id, $category_ids, $brand_ids);
-
-            //计算折扣金额,判断是使用不含运费,还是含运费的金额
-            $amount = !isset($config['shippingfeecoupon']) || $config['shippingfeecoupon'] == 0 ? $orderInfo['goodsprice'] : $orderInfo['amount'];
-            list($new_money, $coupon_money) = $coupon->doBuy($amount);
-
-            //判断优惠金额是否超出总价,超出则直接设定优惠金额为总价
-            $orderInfo['discount'] = $coupon_money > $amount ? $amount : $coupon_money;
-        }
-
-        //计算订单的应付金额【减去折扣】
-        $orderInfo['saleamount'] = max(0, bcsub($orderInfo['amount'], $orderInfo['discount'], 2));
-        $orderInfo['discount'] = bcadd($orderInfo['discount'], 0, 2);
-
-        return [
-            $orderItem,
-            $goodsList,
-            $userCoupon
-        ];
-    }
-
-    /**
-     * @ DateTime 2021-05-28
-     * @ 创建订单
-     * @param int    $address_id
-     * @param int    $user_id
-     * @param mixed  $cart_ids
-     * @param string $memo
-     * @return Order|null
-     */
-    public static function createOrder($address_id, $user_id, $cart_ids, $user_coupon_id, $memo)
-    {
-        $address = Address::get($address_id);
-        if (!$address || $address['user_id'] != $user_id) {
-            throw new \Exception("地址未找到");
-        }
-        $config = get_addon_config('shop');
-        $order_sn = date("Ymdhis") . sprintf("%08d", $user_id) . mt_rand(1000, 9999);
-        //订单主表
-        $orderInfo = [
-            'user_id'     => $user_id,
-            'order_sn'    => $order_sn,
-            'address_id'  => $address->id,
-            'province_id' => $address->province_id,
-            'city_id'     => $address->city_id,
-            'area_id'     => $address->area_id,
-            'receiver'    => $address->receiver,
-            'mobile'      => $address->mobile,
-            'address'     => $address->address,
-            'zipcode'     => $address->zipcode,
-            'goodsprice'  => 0, //商品金额 (不含运费)
-            'amount'      => 0, //总金额 (含运费)
-            'shippingfee' => 0, //运费
-            'discount'    => 0, //优惠金额
-            'saleamount'  => 0,
-            'memo'        => $memo,
-            'expiretime'  => time() + $config['order_timeout'], //订单失效
-            'status'      => 'normal'
-        ];
-
-        //订单详细表
-        list($orderItem, $goodsList, $userCoupon) = self::computeCarts($orderInfo, $cart_ids, $user_id, $address->area_id, $user_coupon_id);
-        $order = null;
-        Db::startTrans();
-        try {
-            //创建订单
-            $order = Order::create($orderInfo, true);
-            //减库存
-            foreach ($goodsList as $index => $item) {
-                if ($item->sku) {
-                    $item->sku->setDec('stocks', $item->nums);
-                }
-                $item->goods->setDec("stocks", $item->nums);
-            }
-            //计算单个商品折扣后的价格
-            $saleamount = bcsub($order['saleamount'], $order['shippingfee'], 2);
-            $saleratio = $order['goodsprice'] > 0 ? bcdiv($saleamount, $order['goodsprice'], 10) : 1;
-            $saleremains = $saleamount;
-            foreach ($orderItem as $index => &$item) {
-                if (!isset($orderItem[$index + 1])) {
-                    $saleprice = $saleremains;
-                } else {
-                    $saleprice = $order['discount'] == 0 ? bcmul($item['price'], $item['nums'], 2) : bcmul(bcmul($item['price'], $item['nums'], 2), $saleratio, 2);
-                }
-                $saleremains = bcsub($saleremains, $saleprice, 2);
-                $item['realprice'] = $saleprice;
-            }
-            unset($item);
-            //创建订单商品数据
-            foreach ($orderItem as $index => $item) {
-                OrderGoods::create($item, true);
-            }
-            //修改地址使用次数
-            $address->setInc('usednums');
-            //优惠券已使用
-            if (!empty($userCoupon)) {
-                $userCoupon->save(['is_used' => 2]);
-            }
-            //提交事务
-            Db::commit();
-        } catch (Exception $e) {
-            Db::rollback();
-            throw new Exception($e->getMessage());
-        }
-        //清空购物车
-        Carts::clear($cart_ids);
-        //记录操作
-        OrderAction::push($order_sn, '系统', '订单创建成功');
-        //订单应付金额为0时直接结算
-        if ($order['saleamount'] == 0) {
-            self::settle($order->order_sn, 0);
-            $order = Order::get($order->id);
-        }
-        return $order;
-    }
-
+    
     /**
      * @ DateTime 2021-05-31
      * @ 订单信息

+ 24 - 0
application/common/model/OrderAddress.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace app\common\model;
+
+use think\Model;
+
+use traits\model\SoftDelete;
+
+/**
+ * 模型
+ */
+class OrderAddress extends Model
+{
+    use SoftDelete;
+
+    // 表名
+    protected $name = 'shop_order_address';
+    // 开启自动写入时间戳字段
+    protected $autoWriteTimestamp = 'int';
+    // 定义时间戳字段名
+    protected $createTime = 'createtime';
+    protected $updateTime = 'updatetime';
+    protected $deleteTime = 'deletetime';
+}

+ 1 - 1
application/common/model/UserCoupon.php

@@ -90,7 +90,7 @@ class UserCoupon extends Model
     //我的可以使用的优惠券【过滤掉条件不符合的】
     public static function myGoodsCoupon($user_id, $goods_ids, $category_ids, $brand_ids)
     {
-        $order = (new Order())->where('user_id', $user_id)->where('paytime', '>', 0)->count();
+        $order = (new Order())->where('user_id', $user_id)->where('pay_time', '>', 0)->count();
         if ($order) {
             $type = 3; //老用户
         } else {

+ 111 - 0
application/common/service/Cart.php

@@ -0,0 +1,111 @@
+<?php
+
+namespace app\common\Service;
+
+use app\common\model\Carts;
+use think\Exception;
+
+class Cart
+{
+        /**
+     * 将购物车数据转换为标准的商品列表格式
+     * @param array $cart_ids 购物车ID列表
+     * @param int $user_id 用户ID
+     * @return array
+     * @throws Exception
+     */
+    public static function convertCartToGoodsList($cart_ids, $user_id)
+    {
+        // 查询购物车数据
+        $cartItems = Carts::where('id', 'in', $cart_ids)
+            ->where('user_id', $user_id)
+            ->select();
+            
+        if (empty($cartItems)) {
+            throw new Exception("购物车数据不存在");
+        }
+        
+        $goods_list = [];
+        foreach ($cartItems as $cart) {
+            $goods_list[] = [
+                'goods_id' => $cart->goods_id,
+                'goods_sku_id' => $cart->goods_sku_id,
+                'nums' => $cart->nums
+            ];
+        }
+        
+        return $goods_list;
+    }
+
+       /**
+     * @ DateTime 2021-05-31
+     * @ 获取购物车商品列表
+     * @param string  $ids
+     * @param integer $user_id
+     * @param integer $sceneval
+     * @return array
+     */
+    public static function getGoodsList($ids, $user_id)
+    {
+        return Carts::field("c.*,GROUP_CONCAT(sp.name,':',sv.value order by sp.id asc) sku_attr")
+            ->with([
+                'Goods' => function ($query) {
+                    $query->where('status', 'normal');
+                },
+                'Sku'
+            ])
+            ->alias('c')
+            ->join('shop_goods_sku sku', 'c.goods_sku_id=sku.id', 'LEFT')
+            ->join('shop_goods_sku_spec p', "FIND_IN_SET(p.id,sku.sku_id)", 'LEFT')
+            ->join('shop_spec sp', 'sp.id=p.spec_id', 'LEFT')
+            ->join('shop_spec_value sv', 'sv.id=p.spec_value_id', 'LEFT')
+            ->where(function ($query) use ($ids) {
+                if ($ids) {
+                    $query->where('c.id', 'in', $ids);
+                }
+            })
+            ->where('c.user_id', $user_id)
+            ->order('c.createtime desc')
+            ->group('c.id')
+            ->select();
+    }
+
+    /**
+     * 添加商品到购物车
+     *
+     * @param string $goods_id     商品ID
+     * @param string $goods_sku_id 商品SKUID
+     * @param int    $nums         数量
+     * @param int    $user_id      会员ID
+     * @return mixed
+     */
+    public static function push($goods_id, $goods_sku_id, $nums = 1, $user_id = 0)
+    {
+        $row = Carts::where('goods_id', $goods_id)
+            ->where('goods_sku_id', $goods_sku_id)
+            ->where('user_id', $user_id)
+            ->find();
+        //已存在,数量加
+        if ($row) {
+            $row->setInc('nums', $nums);
+        } else {
+            $row = new Carts();
+            $row->save([
+                'goods_id'     => $goods_id,
+                'goods_sku_id' => $goods_sku_id,
+                'user_id'      => $user_id,
+                'nums'         => $nums
+            ]);
+        }
+        return $row->id;
+    }
+
+    /**
+     * 清空购物车
+     */
+    public static function clear($cart_ids)
+    {
+        Carts::where('id', 'IN', $cart_ids)->delete();
+    }
+
+}

+ 186 - 270
application/common/service/OrderService.php

@@ -6,122 +6,24 @@ use app\common\Enum\GoodsEnum;
 use app\common\model\Order;
 use app\common\model\OrderGoods;
 use app\common\model\OrderAction;
-use app\common\model\Carts;
 use app\common\model\Address;
 use app\common\model\UserCoupon;
 use app\common\model\Goods;
 use app\common\model\Sku;
 use app\common\model\Freight;
 use app\common\model\Coupon;
+use app\common\model\Carts;
 use think\Db;
 use think\Exception;
-
+use app\common\model\OrderAddress;
 /**
  * 订单服务类
  * 封装订单创建相关逻辑
  */
 class OrderService
 {
-    
-    /**
-     * 统一的创建订单方法
-     * @param int $address_id 地址ID
-     * @param int $user_id 用户ID
-     * @param array $goods_list 标准化的商品列表
-     * @param int $user_coupon_id 优惠券ID
-     * @param string $memo 备注
-     * @param array $cart_ids 购物车ID数组(如果是购物车模式需要清空)
-     * @return Order
-     * @throws Exception
-     */
-    public static function createOrder($address_id, $user_id, $goods_list, $user_coupon_id = 0, $memo = '', $cart_ids = [])
-    {
-        $address = Address::get($address_id);
-        if (!$address || $address['user_id'] != $user_id) {
-            throw new Exception("地址未找到");
-        }
-
-        if (empty($goods_list)) {
-            throw new Exception("商品列表不能为空");
-        }
-
-        $config = get_addon_config('shop');
-        $order_sn = date("Ymdhis") . sprintf("%08d", $user_id) . mt_rand(1000, 9999);
-
-        // 订单主表信息
-        $orderInfo = [
-            'user_id'     => $user_id,
-            'order_sn'    => $order_sn,
-            'address_id'  => $address->id,
-            'province_id' => $address->province_id,
-            'city_id'     => $address->city_id,
-            'area_id'     => $address->area_id,
-            'receiver'    => $address->receiver,
-            'mobile'      => $address->mobile,
-            'address'     => $address->address,
-            'zipcode'     => $address->zipcode,
-            'goodsprice'  => 0, // 商品金额 (不含运费)
-            'amount'      => 0, // 总金额 (含运费)
-            'shippingfee' => 0, // 运费
-            'discount'    => 0, // 优惠金额
-            'saleamount'  => 0,
-            'memo'        => $memo,
-            'expiretime'  => time() + $config['order_timeout'], // 订单失效
-            'status'      => 'normal'
-        ];
-
-        // 通过商品列表计算订单明细
-        list($orderItem, $goodsList, $userCoupon) = self::computeGoods($orderInfo, $goods_list, $user_id, $address->area_id, $user_coupon_id);
-        
-        // 创建订单
-        $order = self::createOrderWithTransaction($orderInfo, $orderItem, $goodsList, $userCoupon);
-        
-        // 如果是购物车模式,需要清空购物车
-        if (!empty($cart_ids)) {
-            Carts::clear($cart_ids);
-        }
-        
-        return $order;
-    }
-
-    /**
-     * 通过购物车创建订单
-     * @param int $address_id 地址ID
-     * @param int $user_id 用户ID
-     * @param array $cart_ids 购物车ID数组
-     * @param int $user_coupon_id 优惠券ID
-     * @param string $memo 备注
-     * @return Order
-     * @throws Exception
-     */
-    public static function createOrderByCart($address_id, $user_id, $cart_ids, $user_coupon_id = 0, $memo = '')
-    {
-        if (empty($cart_ids)) {
-            throw new Exception("购物车列表不能为空");
-        }
-
-        // 将购物车数据转换为标准的商品列表格式
-        $goods_list = self::convertCartToGoodsList($cart_ids, $user_id);
-        
-        return self::createOrder($address_id, $user_id, $goods_list, $user_coupon_id, $memo, $cart_ids);
-    }
-
-    /**
-     * 直接通过商品规格数量创建订单
-     * @param int $address_id 地址ID
-     * @param int $user_id 用户ID
-     * @param array $goods_list 商品列表 [['goods_id'=>1, 'goods_sku_id'=>0, 'nums'=>1], ...]
-     * @param int $user_coupon_id 优惠券ID
-     * @param string $memo 备注
-     * @return Order
-     * @throws Exception
-     */
-    public static function createOrderByGoods($address_id, $user_id, $goods_list, $user_coupon_id = 0, $memo = '')
-    {
-        return self::createOrder($address_id, $user_id, $goods_list, $user_coupon_id, $memo);
-    }
 
-    /**
+        /**
      * 根据商品列表计算订单明细
      * @param array $orderInfo 订单基础信息
      * @param array $goods_list 商品列表
@@ -131,44 +33,41 @@ class OrderService
      * @return array
      * @throws Exception
      */
-    protected static function computeGoods(&$orderInfo, $goods_list, $user_id, $area_id, $user_coupon_id = 0)
+    protected static function computeGoods(&$orderInfo, $goodsList, $userId, $areaId, $userCouponId = 0)
     {
         $config = get_addon_config('shop');
         $orderInfo['amount'] = 0;
-        $orderInfo['goodsprice'] = 0;
-        $orderInfo['shippingfee'] = 0;
-        $orderInfo['discount'] = 0;
+        $orderInfo['goods_price'] = 0;
+        $orderInfo['goods_num'] = 0;
+        $orderInfo['express_fee'] = 0;
+        $orderInfo['discount_fee'] = 0;
+        $orderInfo['coupon_discount_fee'] = 0;
+        $orderInfo['order_amount'] = 0;
         $orderItem = [];
         $shippingTemp = [];
         $userCoupon = null;
-        $goodsList = [];
-
+        $processedGoodsList = []; // 处理后的商品列表,避免与参数$goodsList冲突
         // 校验优惠券
-        if ($user_coupon_id) {
+        if ($userCouponId) {
             $userCouponModel = new UserCoupon();
-            $userCoupon = $userCouponModel->checkUserOrUse($user_coupon_id, $user_id);
-            $orderInfo['user_coupon_id'] = $user_coupon_id;
+            $userCoupon = $userCouponModel->checkUserOrUse($userCouponId, $userId);
+            $orderInfo['user_coupon_id'] = $userCouponId;
         }
 
         // 提取所有商品ID和SKU ID,进行批量查询
-        $goods_ids = array_column($goods_list, 'goods_id');
-        $sku_ids = [];
-        $goods_without_sku = []; // 记录没有指定SKU ID的商品,需要查询默认SKU
-        
-        foreach ($goods_list as $index => $item) {
+        $goodsIds = array_column($goodsList, 'goods_id');
+        $skuIds = [];
+        foreach ($goodsList as $index => $item) {
             if (isset($item['goods_sku_id']) && $item['goods_sku_id'] > 0) {
-                $sku_ids[] = $item['goods_sku_id'];
-            } else {
-                // 没有指定SKU ID的商品,记录下来后续查询默认SKU
-                $goods_without_sku[$index] = $item['goods_id'];
+                $skuIds[] = $item['goods_sku_id'];
             }
         }
 
         // 批量查询商品信息
         $goodsData = [];
-        if (!empty($goods_ids)) {
+        if (!empty($goodsIds)) {
             $goodsCollection = Goods::with(['category', 'brand'])
-                ->where('id', 'in', $goods_ids)
+                ->where('id', 'in', $goodsIds)
                 ->where('status', GoodsEnum::STATUS_ON_SALE)
                 ->select();
             foreach ($goodsCollection as $goods) {
@@ -179,8 +78,8 @@ class OrderService
         // 批量查询SKU信息
         $skuData = [];
         $multiSpecSkuIds = []; // 用于存储多规格商品的SKU ID
-        if (!empty($sku_ids)) {
-            $skuCollection = Sku::where('id', 'in', $sku_ids)->select();
+        if (!empty($skuIds)) {
+            $skuCollection = Sku::where('id', 'in', $skuIds)->select();
             foreach ($skuCollection as $sku) {               
                 $skuData[$sku->id] = $sku;
                 // 过滤出有规格值的SKU ID(spec_value_ids不为空)
@@ -189,30 +88,6 @@ class OrderService
                 }
             }
         }
-        
-        // 查询没有指定SKU ID的商品的默认SKU(单规格商品或多规格商品的默认SKU)
-        if (!empty($goods_without_sku)) {
-            $defaultSkuCollection = Sku::where('goods_id', 'in', array_values($goods_without_sku))
-                ->where('is_default', 1)
-                ->select();
-            foreach ($defaultSkuCollection as $sku) {
-                $skuData[$sku->id] = $sku;
-                // 更新对应的goods_list项,补充SKU ID
-                foreach ($goods_without_sku as $list_index => $goods_id) {
-                    if ($sku->goods_id == $goods_id) {
-                        $goods_list[$list_index]['goods_sku_id'] = $sku->id;
-                        $sku_ids[] = $sku->id; // 添加到sku_ids中用于后续查询规格属性
-                        // 如果默认SKU有规格值,也加入到多规格SKU列表
-                        if (!empty($sku->spec_value_ids)) {
-                            $multiSpecSkuIds[] = $sku->id;
-                        }
-                        unset($goods_without_sku[$list_index]);
-                        break;
-                    }
-                }
-            }
-        }
-
         // 批量查询规格属性字符串(只查询多规格商品的SKU)
         $skuAttrData = [];
         if (!empty($multiSpecSkuIds)) {
@@ -220,7 +95,7 @@ class OrderService
         }
 
         // 验证并构建商品数据
-        foreach ($goods_list as $item) {
+        foreach ($goodsList as $item) {
             $goods_id = $item['goods_id'];
             $goods_sku_id = $item['goods_sku_id']; // 现在所有商品都应该有SKU ID
             $nums = $item['nums'];
@@ -259,11 +134,11 @@ class OrderService
                 'sku_attr' => $sku_attr
             ];
 
-            $goodsList[] = $goodsItem;
+            $processedGoodsList[] = $goodsItem;
         }
-       
+    
         // 计算商品价格和运费(统一使用SKU进行计算)
-        foreach ($goodsList as $item) {
+        foreach ($processedGoodsList as $item) {
             $goodsItemData = [];
             
             if (empty($item->goods) || empty($item->sku)) {
@@ -278,15 +153,17 @@ class OrderService
             // 统一使用SKU数据进行计算
             $goodsItemData['image'] = !empty($item->sku->image) ? $item->sku->image : $item->goods->image;
             $goodsItemData['price'] = $item->sku->price;
-            $goodsItemData['lineation_price'] = $item->sku->lineation_price;
+            // $goodsItemData['lineation_price'] = $item->sku->lineation_price;
             $goodsItemData['sku_sn'] = $item->sku->sku_sn;
             $amount = bcmul($item->sku->price, $item->nums, 2);
             
             $goodsItemData['amount'] = $amount;
-            // 订单总价
+            // 订单应付金额
             $orderInfo['amount'] = bcadd($orderInfo['amount'], $amount, 2);
             // 商品总价
-            $orderInfo['goodsprice'] = bcadd($orderInfo['goodsprice'], $amount, 2);
+            $orderInfo['goods_price'] = bcadd($orderInfo['goods_price'], $amount, 2);
+            // 商品数量累计
+            $orderInfo['goods_num'] += $item->nums;
 
             $freight_id = $item->goods->express_template_id;
             // 计算邮费【合并运费模板】
@@ -304,30 +181,43 @@ class OrderService
                 ];
             }
             
-            // 创建订单商品数据
-            $orderItem[] = array_merge($goodsItemData, [
-                'order_sn'     => $orderInfo['order_sn'],
-                'goods_id'     => $item->goods_id,
-                'title'        => $item->goods->title,
-                'url'          => $item->goods->url,
-                'nums'         => $item->nums,
-                'goods_sku_id' => $item->goods_sku_id,
-                'attrdata'     => $item->sku_attr,
-                'weight'       => $item->sku->weight,
-                'category_id'  => $item->goods->category_id,
-                'brand_id'     => $item->goods->brand_id,
-            ]);
+            // 创建订单商品数据 (基于正确的表结构)
+            $orderItemData = [
+                'user_id'              => $userId,
+                'order_sn'             => '', // 将在订单创建后补充
+                'goods_sn'             => $item->goods->goods_sn ?: '', // 商品货号
+                'sku_sn'               => $item->sku->sku_sn ?: '', // SKU编号
+                'goods_type'           => $item->goods->type ?: 0, // 商品类型
+                'goods_id'             => $item->goods->id,
+                'goods_sku_id'         => $item->sku->id,
+                'goods_title'          => $item->goods->title,
+                'goods_market_price'   => $item->sku->market_price ?: 0, // 市场价
+                'goods_original_price' => $item->sku->price, // 商城售价
+                'goods_price'          => $amount, // 实付金额
+                'goods_image'          => $goodsItemData['image'],
+                'goods_weight'         => $item->sku->weight ?: 0,
+                'nums'                 => $item->nums,
+                'sale_status'          => 0, // 销售状态:0=待申请
+                'comment_status'       => 0, // 评论状态:0=未评论
+                'status'               => 1, // 状态
+                // 添加分类和品牌信息用于优惠券计算 (临时字段,不会保存到数据库)
+                'category_id'          => $item->goods->category_id,
+                'brand_id'             => $item->goods->brand_id,
+            ];
+            
+            $orderItem[] = $orderItemData;
         }
     
-
         // 按运费模板计算
         foreach ($shippingTemp as $key => $item) {
-            $shippingfee = Freight::calculate($key, $area_id, $item['nums'], $item['weight'], $item['amount']);
-            $orderInfo['shippingfee'] = bcadd($orderInfo['shippingfee'], $shippingfee, 2);
+            $shippingfee = Freight::calculate($key, $areaId, $item['nums'], $item['weight'], $item['amount']);
+            $orderInfo['express_fee'] = bcadd($orderInfo['express_fee'], $shippingfee, 2);
         }
 
-        // 订单总价(含邮费)
-        $orderInfo['amount'] = bcadd($orderInfo['goodsprice'], $orderInfo['shippingfee'], 2);
+        // 订单金额(商品价格+运费)
+        $orderInfo['order_amount'] = bcadd($orderInfo['goods_price'], $orderInfo['express_fee'], 2);
+        // 订单应付金额(暂时等于订单金额,后续会减去优惠)
+        $orderInfo['amount'] = $orderInfo['order_amount'];
 
         if (!empty($userCoupon)) {
             // 校验优惠券
@@ -339,27 +229,93 @@ class OrderService
                 ->checkCoupon()
                 ->checkOpen()
                 ->checkUseTime($userCoupon['createtime'])
-                ->checkConditionGoods($goods_ids, $user_id, $category_ids, $brand_ids);
+                ->checkConditionGoods($goods_ids, $userId, $category_ids, $brand_ids);
 
             // 计算折扣金额,判断是使用不含运费,还是含运费的金额
-            $amount = !isset($config['shippingfeecoupon']) || $config['shippingfeecoupon'] == 0 ? $orderInfo['goodsprice'] : $orderInfo['amount'];
+            $amount = !isset($config['shippingfeecoupon']) || $config['shippingfeecoupon'] == 0 ? $orderInfo['goods_price'] : $orderInfo['order_amount'];
             list($new_money, $coupon_money) = $coupon->doBuy($amount);
 
             // 判断优惠金额是否超出总价,超出则直接设定优惠金额为总价
-            $orderInfo['discount'] = $coupon_money > $amount ? $amount : $coupon_money;
+            $orderInfo['coupon_discount_fee'] = $coupon_money > $amount ? $amount : $coupon_money;
+            $orderInfo['discount_fee'] = $orderInfo['coupon_discount_fee'];
         }
 
-        // 计算订单的应付金额【减去折扣】
-        $orderInfo['saleamount'] = max(0, bcsub($orderInfo['amount'], $orderInfo['discount'], 2));
-        $orderInfo['discount'] = bcadd($orderInfo['discount'], 0, 2);
+        // 计算最终应付金额【订单金额减去折扣】
+        $orderInfo['amount'] = max(0, bcsub($orderInfo['order_amount'], $orderInfo['discount_fee'], 2));
+        $orderInfo['pay_amount'] = $orderInfo['amount']; // 实际付款金额等于应付金额
+        $orderInfo['discount_fee'] = bcadd($orderInfo['discount_fee'], 0, 2);
 
         return [
             $orderItem,
-            $goodsList,
+            $processedGoodsList,
             $userCoupon
         ];
     }
 
+    
+    /**
+     * 统一的创建订单方法
+     * @param int $address_id 地址ID
+     * @param int $user_id 用户ID
+     * @param array $goods_list 标准化的商品列表
+     * @param int $user_coupon_id 优惠券ID
+     * @param string $memo 备注
+     * @param array $cart_ids 购物车ID数组(如果是购物车模式需要清空)
+     * @return Order
+     * @throws Exception
+     */
+    public static function createOrder($addressId, $userId, $goodsList, $userCouponId = 0, $remark = '')
+    {
+        $address = Address::get($addressId);
+        if (!$address || $address['user_id'] != $userId) {
+            throw new Exception("地址未找到");
+        }
+
+        if (empty($goodsList)) {
+            throw new Exception("商品列表不能为空");
+        }
+
+        $config = get_addon_config('shop');
+        $orderSn = date("Ymdhis") . sprintf("%08d", $userId) . mt_rand(1000, 9999);
+
+        // 订单主表信息 (基于新表结构)
+        $orderInfo = [
+            'type'                 => 1, // 1:普通订单
+            'source'               => 'H5', // 订单来源 (暂定H5,可根据实际情况调整)
+            'order_sn'             => $orderSn,
+            'user_id'              => $userId,
+            'amount'               => 0, // 订单应付金额
+            'goods_price'          => 0, // 商品总费用
+            'goods_num'            => 0, // 商品数量
+            'discount_fee'         => 0, // 优惠金额
+            'coupon_discount_fee'  => 0, // 优惠券金额
+            'promo_discount_fee'   => 0, // 营销金额
+            'order_amount'         => 0, // 订单金额
+            'pay_amount'           => 0, // 实际付款金额
+            'pay_type'             => '', // 支付方式
+            'pay_time'             => null, // 支付时间
+            'delivery_type'        => 1, // 发货方式
+            'express_name'         => '', // 快递名称
+            'express_no'           => '', // 快递单号
+            'express_fee'          => 0, // 配送费用
+            'expire_time'          => time() + $config['order_timeout'], // 过期时间
+            'order_status'         => \app\common\Enum\OrderEnum::STATUS_CREATE, // 待付款
+            'invoice_status'       => 0, // 发票开具状态
+            'remark'               => $remark, // 用户备注
+            'user_coupon_id'       => $userCouponId ?: null,
+            'ip'                   => request()->ip(), // IP地址
+            'status'               => 'normal'
+        ];
+      
+
+        // 通过商品列表计算订单明细
+        list($orderItem, $calculatedGoodsList, $userCoupon) = self::computeGoods($orderInfo, $goodsList, $userId, $address->area_id, $userCouponId);
+        // 创建订单
+        $order = self::createOrderWithTransaction($orderInfo, $orderItem, $calculatedGoodsList, $userCoupon, $address);
+        
+        return $order;
+    }
+
 
     /**
      * 在事务中创建订单
@@ -367,10 +323,11 @@ class OrderService
      * @param array $orderItem 订单商品列表
      * @param array $goodsList 商品列表
      * @param object $userCoupon 优惠券
+     * @param object $address 地址信息
      * @return Order
      * @throws Exception
      */
-    protected static function createOrderWithTransaction($orderInfo, $orderItem, $goodsList, $userCoupon)
+    protected static function createOrderWithTransaction($orderInfo, $orderItem, $goodsList, $userCoupon, $address)
     {
         $order = null;
         Db::startTrans();
@@ -378,6 +335,30 @@ class OrderService
             // 创建订单
             $order = Order::create($orderInfo, true);
             
+            // 为每个订单商品添加订单ID和订单号
+            foreach ($orderItem as &$item) {
+                $item['order_id'] = $order->id;
+                $item['order_sn'] = $order->order_sn;
+                // 移除临时字段
+                unset($item['category_id'], $item['brand_id']);
+            }
+            unset($item);
+            // 创建订单地址信息
+            $orderAddressData = [
+                'order_id'      => $order->id,
+                'user_id'       => $orderInfo['user_id'],
+                'consignee'     => $address->receiver,
+                'mobile'        => $address->mobile,
+                'province_name' => $address->province->name ?? '',
+                'city_name'     => $address->city->name ?? '',
+                'district_name' => $address->area->name ?? '',
+                'address'       => $address->address,
+                'province_id'   => $address->province_id,
+                'city_id'       => $address->city_id,
+                'district_id'   => $address->area_id,
+            ];
+            OrderAddress::create($orderAddressData);
+            
             // 减库存
             foreach ($goodsList as $index => $item) {
                 if ($item->sku) {
@@ -386,29 +367,28 @@ class OrderService
                 $item->goods->setDec("stocks", $item->nums);
             }
             
-            // 计算单个商品折扣后的价格
-            $saleamount = bcsub($order['saleamount'], $order['shippingfee'], 2);
-            $saleratio = $order['goodsprice'] > 0 ? bcdiv($saleamount, $order['goodsprice'], 10) : 1;
+            // 计算单个商品折扣后的价格 (基于新字段名)
+            $saleamount = bcsub($order['amount'], $order['express_fee'], 2);
+            $saleratio = $order['goods_price'] > 0 ? bcdiv($saleamount, $order['goods_price'], 10) : 1;
             $saleremains = $saleamount;
             
             foreach ($orderItem as $index => &$item) {
                 if (!isset($orderItem[$index + 1])) {
                     $saleprice = $saleremains;
                 } else {
-                    $saleprice = $order['discount'] == 0 ? bcmul($item['price'], $item['nums'], 2) : bcmul(bcmul($item['price'], $item['nums'], 2), $saleratio, 2);
+                    $saleprice = $order['discount_fee'] == 0 ? bcmul($item['goods_original_price'], $item['nums'], 2) : bcmul(bcmul($item['goods_original_price'], $item['nums'], 2), $saleratio, 2);
                 }
                 $saleremains = bcsub($saleremains, $saleprice, 2);
-                $item['realprice'] = $saleprice;
+                $item['goods_price'] = $saleprice;
             }
             unset($item);
             
-            // 创建订单商品数据
-            foreach ($orderItem as $index => $item) {
-                OrderGoods::create($item, true);
+            // 批量创建订单商品数据
+            if (!empty($orderItem)) {
+                (new OrderGoods())->saveAll($orderItem);
             }
             
             // 修改地址使用次数
-            $address = Address::get($orderInfo['address_id']);
             if ($address) {
                 $address->setInc('usednums');
             }
@@ -429,7 +409,7 @@ class OrderService
         OrderAction::push($orderInfo['order_sn'], '系统', '订单创建成功');
         
         // 订单应付金额为0时直接结算
-        if ($order['saleamount'] == 0) {
+        if ($order['amount'] == 0) {
             Order::settle($order->order_sn, 0);
             $order = Order::get($order->id);
         }
@@ -472,100 +452,36 @@ class OrderService
      * @return array
      * @throws Exception
      */
-    public static function calculateOrder($goods_list, $user_id, $area_id = 0, $user_coupon_id = 0)
+    public static function calculateOrder($goodsList, $userId, $areaId = 0, $userCouponId = 0)
     {
-        if (empty($goods_list)) {
+        if (empty($goodsList)) {
             throw new Exception("商品列表不能为空");
         }
-        
+      
         // 验证商品列表格式
-        self::validateGoodsList($goods_list);
-
-        $order_sn = date("Ymdhis") . sprintf("%08d", $user_id) . mt_rand(1000, 9999);
+        self::validateGoodsList($goodsList);
 
-        // 订单基础信息
+        // 订单基础信息(用于计算,不包含订单号)
         $orderInfo = [
-            'order_sn'    => $order_sn,
-            'goodsprice'  => 0, // 商品金额 (不含运费)
-            'amount'      => 0, // 总金额 (含运费)
-            'shippingfee' => 0, // 运费
-            'discount'    => 0, // 优惠金额
-            'saleamount'  => 0  // 应付金额
-        ];
+            'amount'               => 0, // 应付金额
+            'goods_price'          => 0, // 商品金额 (不含运费)
+            'goods_num'            => 0, // 商品数量
+            'discount_fee'         => 0, // 总优惠金额
+            'coupon_discount_fee'  => 0, // 优惠券金额
+            'promo_discount_fee'   => 0, // 营销金额
+            'order_amount'         => 0, // 总金额 (含运费)
+            'express_fee'          => 0, // 运费
+        ];       
 
         // 计算商品明细
-        list($orderItem, $goodsList, $userCoupon) = self::computeGoods($orderInfo, $goods_list, $user_id, $area_id, $user_coupon_id);
+        list($orderItem, $calculatedGoodsList, $userCoupon) = self::computeGoods($orderInfo, $goodsList, $userId, $areaId, $userCouponId);
 
         return [
             'orderItem' => $orderItem,
-            'goodsList' => $goodsList,
+            'goodsList' => $calculatedGoodsList,
             'orderInfo' => $orderInfo,
             'userCoupon' => $userCoupon
         ];
     }
 
-    /**
-     * 通过商品规格计算订单明细(用于预览订单)
-     * @param array $goods_list 商品列表
-     * @param int $user_id 用户ID
-     * @param int $area_id 地区ID
-     * @param int $user_coupon_id 优惠券ID
-     * @return array
-     * @throws Exception
-     */
-    public static function calculateOrderByGoods($goods_list, $user_id, $area_id = 0, $user_coupon_id = 0)
-    {
-        return self::calculateOrder($goods_list, $user_id, $area_id, $user_coupon_id);
-    }
-
-    /**
-     * 通过购物车计算订单明细(用于预览订单)
-     * @param array $cart_ids 购物车ID列表
-     * @param int $user_id 用户ID
-     * @param int $area_id 地区ID
-     * @param int $user_coupon_id 优惠券ID
-     * @return array
-     * @throws Exception
-     */
-    public static function calculateOrderByCart($cart_ids, $user_id, $area_id = 0, $user_coupon_id = 0)
-    {
-        if (empty($cart_ids)) {
-            throw new Exception("购物车列表不能为空");
-        }
-
-        // 将购物车数据转换为标准的商品列表格式
-        $goods_list = self::convertCartToGoodsList($cart_ids, $user_id);
-        
-        return self::calculateOrder($goods_list, $user_id, $area_id, $user_coupon_id);
-    }
-
-    /**
-     * 将购物车数据转换为标准的商品列表格式
-     * @param array $cart_ids 购物车ID列表
-     * @param int $user_id 用户ID
-     * @return array
-     * @throws Exception
-     */
-    public static function convertCartToGoodsList($cart_ids, $user_id)
-    {
-        // 查询购物车数据
-        $cartItems = Carts::where('id', 'in', $cart_ids)
-            ->where('user_id', $user_id)
-            ->select();
-            
-        if (empty($cartItems)) {
-            throw new Exception("购物车数据不存在");
-        }
-        
-        $goods_list = [];
-        foreach ($cartItems as $cart) {
-            $goods_list[] = [
-                'goods_id' => $cart->goods_id,
-                'goods_sku_id' => $cart->goods_sku_id,
-                'nums' => $cart->nums
-            ];
-        }
-        
-        return $goods_list;
-    }
 } 

+ 275 - 0
application/common/service/lottery/LuckLotteryRecordServices.php

@@ -0,0 +1,275 @@
+<?php
+
+
+namespace app\services\lottery;
+
+
+use app\common\model\lottery\Record;
+
+/**
+ *  抽奖记录
+ * Class LuckLotteryRecordServices
+ *
+ */
+class LuckLotteryRecordServices
+{
+
+
+
+    /**
+     * 获取抽奖记录列表
+     * @param array $where
+     * @return array
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function getList(array $where)
+    {
+        [$page, $limit] = $this->getPageValue();
+        /** @var LuckLotteryServices $luckServices */
+        $luckServices = app()->make(LuckLotteryServices::class);
+        $where['lottery_id'] = $where['factor'] == '' ? '' : $luckServices->value(['factor' => $where['factor']], 'id');
+        unset($where['factor']);
+        $list = $this->dao->getList($where, '*', ['lottery', 'prize', 'user'], $page, $limit);
+        foreach ($list as &$item) {
+            $item['add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', $item['add_time']) : '';
+        }
+        $count = $this->dao->count($where);
+        return compact('list', 'count');
+    }
+
+    /**
+     * 获取中奖记录
+     * @param array $where
+     * @param int $limit
+     * @return array
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function getWinList(array $where, int $limit = 20)
+    {
+        $where = $where + ['not_type' => 1];
+        $list = $this->dao->getList($where, 'id,uid,prize_id,lottery_id,receive_time,add_time', ['user', 'prize'], 0, $limit);
+        foreach ($list as &$item) {
+            $item['receive_time'] = $item['receive_time'] ? date('Y-m-d H:i:s', $item['receive_time']) : '';
+            $item['add_time'] = $item['add_time'] ? date('Y-m-d H:i', $item['add_time']) : '';
+        }
+        return $list;
+    }
+
+    /**
+     * 参与抽奖数据统计
+     * @param int $lottery_id
+     * @return int[]
+     */
+    public function getLotteryRecordData(int $lottery_id)
+    {
+        $data = ['all' => 0, 'people' => 0, 'win' => 0];
+        if ($lottery_id) {
+            $where = [['lottery_id', '=', $lottery_id]];
+            $data['all'] = $this->dao->getCount($where);
+            $data['people'] = $this->dao->getCount($where, 'uid');
+            $data['win'] = $this->dao->getCount($where + [['type', '>', 1]], 'uid');
+        }
+        return $data;
+    }
+
+    /**
+     * 写入中奖纪录
+     * @param int $uid
+     * @param array $prize
+     * @param array $userInfo
+     * @return mixed
+     */
+    public function insertPrizeRecord(int $uid, array $prize, array $userInfo = [])
+    {
+        if (!$userInfo) {
+          return [1,'请上传用户信息'];
+        }
+        if (!$prize) {
+            return [1,'请上传奖品信息'];
+        }
+        $data = [];
+        $data['user_id'] = $uid;
+        $data['lottery_id'] = $prize['lottery_id'];
+        $data['prize_id'] = $prize['id'];
+        $data['type'] = $prize['type'];
+        $data['num'] = $prize['num'];
+        $data['createtime'] = time();
+        $record = new Record();
+        if (! $record->save($data)) {
+            return [1,'记录日志数据接口失败'];
+        }
+        return [0,$record];
+    }
+
+    /**
+     * 领取奖品
+     * @param int $uid
+     * @param int $lottery_record_id
+     * @param string $receive_info
+     * @return bool
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function receivePrize(int $uid, int $lottery_record_id, array $receive_info = [])
+    {
+        /** @var UserServices $userServices */
+        $userServices = app()->make(UserServices::class);
+        $userInfo = $userServices->getUserInfo($uid);
+        if (!$userInfo) {
+            throw new ApiException(410032);
+        }
+        $lotteryRecord = $this->dao->get($lottery_record_id, ['*'], ['prize']);
+        if (!$lotteryRecord || !isset($lotteryRecord['prize'])) {
+            throw new ApiException(410050);
+        }
+        if ($lotteryRecord['is_receive'] == 1) {
+            throw new ApiException(410051);
+        }
+        $data = ['is_receive' => 1, 'receive_time' => time(), 'receive_info' => $receive_info];
+        $prize = $lotteryRecord['prize'];
+        $this->transaction(function () use ($uid, $userInfo, $lottery_record_id, $data, $prize, $userServices, $receive_info) {
+            //奖品类型1:未中奖2:积分3:余额4:红包5:优惠券6:站内商品7:等级经验8:用户等级 9:svip天数
+            switch ($prize['type']) {
+                case 1:
+                    break;
+                case 2:
+                    /** @var UserBillServices $userBillServices */
+                    $userBillServices = app()->make(UserBillServices::class);
+                    $userBillServices->income('lottery_give_integral', $uid, $prize['num'], $userInfo['integral'] + $prize['num'], $prize['id']);
+                    $userServices->update($uid, ['integral' => bcadd((string)$userInfo['integral'], (string)$prize['num'], 0)], 'uid');
+                    break;
+                case 3:
+                    /** @var UserMoneyServices $userMoneyServices */
+                    $userMoneyServices = app()->make(UserMoneyServices::class);
+                    $now_money = bcadd((string)$userInfo['now_money'], (string)$prize['num'], 2);
+                    $userMoneyServices->income('lottery_give_money', $uid, $prize['num'], $now_money, $prize['id']);
+                    $userServices->update($uid, ['now_money' => $now_money], 'uid');
+                    break;
+                case 4:
+                    /** @var WechatUserServices $wechatServices */
+                    $wechatServices = app()->make(WechatUserServices::class);
+                    $openid = $wechatServices->uidToOpenid((int)$uid, 'wechat');
+                    $type = 'JSAPI';
+                    if (!$openid) {
+                        $openid = $wechatServices->uidToOpenid((int)$uid, 'routine');
+                        $type = 'mini';
+                    }
+                    if (!$openid) {
+                        $openid = $wechatServices->uidToOpenid((int)$uid, 'app');
+                        $type = 'APP';
+                    }
+                    if ($openid) {
+                        /** @var StoreOrderCreateServices $services */
+                        $services = app()->make(StoreOrderCreateServices::class);
+                        $wechat_order_id = $services->getNewOrderId();
+                        /** @var CapitalFlowServices $capitalFlowServices */
+                        $capitalFlowServices = app()->make(CapitalFlowServices::class);
+                        $capitalFlowServices->setFlow([
+                            'order_id' => $wechat_order_id,
+                            'uid' => $uid,
+                            'price' => bcmul('-1', (string)$prize['num'], 2),
+                            'pay_type' => 'weixin',
+                            'nickname' => $userInfo['nickname'],
+                            'phone' => $userInfo['phone']
+                        ], 'luck');
+
+                        if (sys_config('pay_wechat_type')) {
+                            $pay = new Pay('v3_wechat_pay');
+                            $pay->merchantPay($openid, $wechat_order_id, $prize['num'], [
+                                'type' => $type,
+                                'batch_name' => '抽奖中奖红包',
+                                'batch_remark' => '您于' . date('Y-m-d H:i:s') . '中奖.' . $prize['num'] . '元'
+                            ]);
+                        } else {
+                            WechatService::merchantPay($openid, $wechat_order_id, $prize['num'], '抽奖中奖红包');
+                        }
+                    }
+                    break;
+                case 5:
+                    /** @var StoreCouponIssueServices $couponIssueService */
+                    $couponIssueService = app()->make(StoreCouponIssueServices::class);
+                    try {
+                        $couponIssueService->issueUserCoupon($prize['coupon_id'], $userInfo);
+                    } catch (\Throwable $e) {
+                        Log::error('抽奖领取优惠券失败,原因:' . $e->getMessage());
+                    }
+                    break;
+                case 6:
+                    if (!$receive_info['name'] || !$receive_info['phone'] || !$receive_info['address']) {
+                        throw new ApiException(410052);
+                    }
+                    if (!check_phone($receive_info['phone'])) {
+                        throw new ApiException(410053);
+                    }
+                    break;
+            }
+            $this->dao->update($lottery_record_id, $data, 'id');
+        });
+        return true;
+    }
+
+    /**
+     * 发货、备注
+     * @param int $lottery_record_id
+     * @param array $data
+     * @return bool
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function setDeliver(int $lottery_record_id, array $data)
+    {
+        $lotteryRecord = $this->dao->get($lottery_record_id);
+        if (!$lotteryRecord) {
+            throw new ApiException(410054);
+        }
+        $deliver_info = $lotteryRecord['deliver_info'];
+        $edit = [];
+        //备注
+        if ($data['deliver_name'] && $data['deliver_number']) {
+            if ($lotteryRecord['type'] != 6 && ($data['deliver_name'] || $data['deliver_number'])) {
+                throw new ApiException(410055);
+            }
+            if ($lotteryRecord['type'] == 6 && (!$data['deliver_name'] || !$data['deliver_number'])) {
+                throw new ApiException(410056);
+            }
+            $deliver_info['deliver_name'] = $data['deliver_name'];
+            $deliver_info['deliver_number'] = $data['deliver_number'];
+            $edit['is_deliver'] = 1;
+            $edit['deliver_time'] = time();
+        }
+        $deliver_info['mark'] = $data['mark'];
+        $edit['deliver_info'] = $deliver_info;
+        if (!$this->dao->update($lottery_record_id, $edit, 'id')) {
+            throw new ApiException(100005);
+        }
+        return true;
+    }
+
+    /**
+     * 获取中奖记录
+     * @param int $uid
+     * @param array $where
+     * @return array
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function getRecord( $uid = 0,$page =1, $pageSize = 10)
+    {
+        $list =  Record::with(['lottery','prize','user'])
+            ->where('user_id',$uid)
+            ->field('*')->order("createtime desc")
+            ->paginate($pageSize, false, ['page' => $page]);
+        $list->each(function($item, $key){
+            $item->deliver_time =  $item['deliver_time'] ? date('Y-m-d H:i:s', $item['deliver_time']) : '';;
+            $item->receive_time =  $item['receive_time'] ? date('Y-m-d H:i:s', $item['receive_time']) : '';
+        });
+        return $list;
+    }
+}

+ 176 - 0
application/common/service/lottery/LuckLotteryServices.php

@@ -0,0 +1,176 @@
+<?php
+
+
+namespace app\services\lottery;
+use app\admin\model\lottery\Info;
+use app\admin\model\lottery\Record;
+use app\admin\model\User;
+use think\Db;
+
+/**
+ *
+ * Class LuckLotteryServices
+ * @package app\services\activity\lottery
+ */
+class LuckLotteryServices
+{
+    /**
+     * 抽奖形式,奖品数量
+     * @var int[]
+     */
+    protected $lottery_type = [
+        '1' => 8 //九宫格
+    ];
+    /**
+     * 抽奖类型
+     * @var string[]
+     */
+    protected $lottery_factor = [
+        '1' => '积分',
+        '2' => '余额',
+        '3' => '下单支付成功',
+        '4' => '订单评价',
+        '5' => '关注公众号'
+    ];
+
+    public function getLottery($id, $field = '*',$with = ['prize'])
+    {
+        $time = time();
+        return Info::where('id',$id)
+            ->with($with)
+            ->where('status', 1)
+            ->where('start_time', '<=', $time)
+            ->where('end_time', '>=', $time)
+            ->find();
+    }
+
+    public function getLotteryInfo($id, $field = '*',$with = ['prize'])
+    {
+        return Info::where('id',$id)
+            ->where('status', 1)
+            ->find();
+    }
+
+
+
+
+    /**
+     * 抽奖
+     * @param int $uid
+     * @param int $lottery_id
+     * @return mixed
+     * @throws \Psr\SimpleCache\InvalidArgumentException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function luckLottery( $userInfo,  $lottery_id)
+    {
+
+        $lottery = $this->getLotteryInfo($lottery_id, '*', [], true);
+        if (!$lottery) {
+           return [1,'抽奖活动不存在'];
+        }
+
+        $uid  = $userInfo['id'];
+        $lottery = $lottery->toArray();
+        if ( $lottery['lottery_num_term'] > 0 &&  $this->getPaperDateGradeCount($lottery_id,$uid) >= $lottery['lottery_num_term']) {
+            return [1,'当前抽奖次数已达今日上限,明天再来吧~'];
+        }
+
+        $lotteryPrizeServices = new LuckPrizeServices();
+        $lotteryPrize = $lotteryPrizeServices->getLotteryPrizeList($lottery_id);
+        if (!$lotteryPrize) {
+            return [1,'抽奖奖品不存在'];
+        }
+        $lotteryPrize = collection($lotteryPrize)->toArray();
+
+        return Db::transaction(function () use ($uid, $lotteryPrize, $userInfo, $lottery) {
+            $luckPrizeServices =new LuckPrizeServices();
+            //随机抽奖
+            $prize = $luckPrizeServices->getLuckPrize($lotteryPrize);
+            if (!$prize) {
+                return [1,'抽奖异常'];
+            }
+            //中奖扣除积分、余额
+            list($nError,$msg) = $this->lotteryFactor($uid, $userInfo, $lottery);
+            if ($nError ==  1) {
+                return [1,$msg];
+            }
+            //中奖减少奖品数量
+            list($nError,$msg) = $luckPrizeServices->decPrizeNum($prize['id'], $prize);
+            if ($nError ==  1) {
+                return [1,$msg];
+            }
+            $lotteryRecordServices = new LuckLotteryRecordServices();
+            //中奖写入记录
+            list($nError,$record) = $lotteryRecordServices->insertPrizeRecord($uid, $prize, $userInfo);
+            if ($nError ==  1) {
+                return [1,$record];
+            }
+            //不是站内商品直接领奖
+            /*if ($prize['type'] != 6) {
+                $lotteryRecordServices->receivePrize($uid, (int)$record->id);
+            }*/
+            $prize['lottery_record_id'] = $record->id;
+            return [0,$prize];
+        });
+    }
+
+
+    /**
+     * 次数
+     * @param int    $paper_id 试卷ID
+     * @param string $date     日期
+     * @return int|string
+     */
+    public static function getPaperDateGradeCount($lottery_id,$uid)
+    {
+        if (!$lottery_id) {
+            return 0;
+        }
+        return Record::where('lottery_id', $lottery_id)->where('user_id',$uid)->whereTime('createtime', 'today')->count();
+    }
+
+    /**
+     * 抽奖消耗扣除用户积分、余额等
+     * @param int $uid
+     * @param array $userInfo
+     * @param array $lottery
+     * @return bool
+     * @throws \Psr\SimpleCache\InvalidArgumentException
+     */
+    public function lotteryFactor(int $uid, array $userInfo, array $lottery)
+    {
+        if (!$userInfo || !$lottery) {
+            return true;
+        }
+        if (!User::where('id',$uid)->setDec('lottery_num')) {
+            return [1,'抽奖次数修改失败'];
+        }
+        return [0,'抽奖次数修改成功'];
+
+    }
+
+    /**
+     * 增加抽奖次数
+     * @param int $uid
+     * @param array $userInfo
+     * @param array $lottery
+     * @return bool
+     * @throws \Psr\SimpleCache\InvalidArgumentException
+     */
+    public function lotteryNum( $uid)
+    {
+        if (!User::where('id',$uid)->setInc('lottery_num')) {
+            return [1,'抽奖次数增加失败'];
+        }
+        return [0,'抽奖次数成功增加'];
+
+    }
+
+
+
+
+
+}

+ 158 - 0
application/common/service/lottery/LuckPrizeServices.php

@@ -0,0 +1,158 @@
+<?php
+
+
+namespace app\services\lottery;
+
+use app\admin\model\lottery\Prize;
+
+/**
+ *
+ * Class LuckPrizeServices
+ *
+ */
+class LuckPrizeServices
+{
+    /**
+     * @var array 1:未中奖2:积分3:余额4:红包5:优惠券6:站内商品7:等级经验8:用户等级 9:svip天数
+     */
+    public $prize_type = [
+        '1' => '未中奖',
+        '2' => '积分',
+        '3' => '余额',
+        '4' => '红包',
+        '5' => '优惠券',
+        '6' => '站内商品',
+        '7' => '等级经验',
+        '8' => '用户等级',
+        '9' => 'svip天数'
+    ];
+
+    /**
+     * 奖品数据字段
+     * @var array
+     */
+    public $prize = [
+        'id' => 0,
+        'type' => 1,
+        'lottery_id' => 0,
+        'name' => '',
+        'prompt' => '',
+        'image' => '',
+        'chance' => 0,
+        'total' => 0,
+        'coupon_id' => 0,
+        'product_id' => 0,
+        'unique' => '',
+        'num' => 1,
+        'sort' => 0,
+        'status' => 1,
+        'is_del' => 0,
+        'add_time' => 0,
+    ];
+    /**
+     * 奖品数据验证
+     * @param array $data
+     */
+    public function checkPrizeData(array $data)
+    {
+        $data = array_merge($this->prize, array_intersect_key($data, $this->prize));
+        if (!isset($data['name']) || !$data['name']) {
+            return [1,'奖品不存在'];
+        }
+        if (!isset($data['image']) || !$data['image']) {
+            return [1,'奖品不存在'];
+        }
+        if (!isset($data['chance']) || !$data['chance']) {
+            return [1,'奖品不存在'];
+        }
+        if (!isset($data['type']) || !isset($this->prize_type[$data['type']])) {
+            return [1,'奖品不存在'];
+        }
+        if (in_array($data['type'], [2, 3, 4]) && (!isset($data['num']) || !$data['num'])) {
+            $msg = '';
+            switch ($data['type']) {
+                case 2:
+                    $msg = '积分';
+                    break;
+                case 3:
+                    $msg = '余额';
+                    break;
+                case 4:
+                    $msg = '红包';
+                    break;
+            }
+            return [1,'type' => $msg];
+        }
+        return [0,$data];
+    }
+
+    /**
+     * 获取某个抽奖活动的所有奖品
+     * @param int $lottery_id
+     * @param string $field
+     */
+    public function getLotteryPrizeList(int $lottery_id, string $field = '*')
+    {
+        $where = ['status' => 1,'lottery_id' => $lottery_id];
+        return Prize::where($where)->field($field)->order('sort desc,id desc')->select();
+    }
+
+
+    /**
+     * 随机奖品
+     * @param array $data
+     * @return array|mixed
+     */
+    function getLuckPrize(array $data)
+    {
+        $prize = [];
+        if (!$data) return $prize;
+        $totalChance = array_sum(array_column($data, 'chance'));
+        if (!$totalChance) return $prize;
+        $startChance = 0;
+        mt_srand();
+        $prizeChance = rand(0, $totalChance);
+        $newPrize = array_combine(array_column($data, 'type'), $data);
+        foreach ($data as $item) {
+            $newStartChance = $item['chance'] + $startChance;
+            //随机数在这个基数端内 且该商品数量大于0 中奖
+            if ($prizeChance >= $startChance && $prizeChance < $newStartChance) {
+                //随机到不是未中奖奖品-》设置了奖品数量-》数量不足时 返回未中奖奖品   || 抽到优惠券 数量不足
+                if (($item['type'] != 1 && $item['total'] != -1 && $item['total'] <= 0)
+                    ) {
+                    $prize = $newPrize[1] ?? [];
+                } else {
+                    $prize = $item;
+                }
+                break;
+            }
+            $startChance = $newStartChance;
+        }
+        return $prize;
+    }
+
+    /**
+     * 中奖后减少奖品数量
+     * @param int $id
+     * @param array $prize
+     * @return array
+     */
+    public function decPrizeNum(int $id, array $prize = [])
+    {
+        if (!$id) return [1,'请上传奖品'];
+        if (!$prize) {
+            $prize = Prize::find($id);
+        }
+        if (!$prize) {
+           return [1,'奖品不存在'];
+        }
+        //不是未中奖奖品 减少奖品数量
+        if ($prize['type'] != 1 && $prize['total'] >= 1) {
+            $total = $prize['total'] - 1;
+            if (! Prize::where('id',$id)->update(['total' => $total] )) {
+                return [1,'修改奖品数量失败'];
+            }
+        }
+        return [0,'减少奖品数量成功'];
+    }
+}