diff --git a/crmeb/app/adminapi/controller/v1/marketing/StoreCouponIssue.php b/crmeb/app/adminapi/controller/v1/marketing/StoreCouponIssue.php index 67d6fd52b..e88b449b1 100644 --- a/crmeb/app/adminapi/controller/v1/marketing/StoreCouponIssue.php +++ b/crmeb/app/adminapi/controller/v1/marketing/StoreCouponIssue.php @@ -67,10 +67,11 @@ class StoreCouponIssue extends AuthController ['is_permanent', 0], ['total_count', 0], ['product_id', ''], - ['category_id', 0], + ['category_id', []], ['type', 0], ['sort', 0], ['status', 0], + ['receive_limit', 1], ]); $res = $this->services->saveCoupon($data); if ($res) return app('json')->success(100000); @@ -110,6 +111,12 @@ class StoreCouponIssue extends AuthController ]; } } + if ($info['category_id'] != '') { + $info['category_id'] = explode(',', $info['category_id']); + foreach ($info['category_id'] as &$category_id) { + $category_id = (int)$category_id; + } + } return app('json')->success($info); } diff --git a/crmeb/app/adminapi/controller/v1/order/StoreOrder.php b/crmeb/app/adminapi/controller/v1/order/StoreOrder.php index 5414daa6e..ac53fbe1f 100644 --- a/crmeb/app/adminapi/controller/v1/order/StoreOrder.php +++ b/crmeb/app/adminapi/controller/v1/order/StoreOrder.php @@ -479,9 +479,15 @@ class StoreOrder extends AuthController $orderInfo = $this->services->tidyOrder($orderInfo->toArray(), true, true); //核算优惠金额 - $vipTruePrice = array_column($orderInfo['cartInfo'], 'vip_sum_truePrice'); - $vipTruePrice = round(array_sum($vipTruePrice), 2); - $orderInfo['vip_true_price'] = $vipTruePrice ?: 0; + $vipTruePrice = $levelPrice = $memberPrice = 0; + foreach ($orderInfo['cartInfo'] as $cart) { + $vipTruePrice = bcadd((string)$vipTruePrice, (string)$cart['vip_sum_truePrice'], 2); + if ($cart['price_type'] == 'member') $memberPrice = bcadd((string)$memberPrice, (string)$cart['vip_sum_truePrice'], 2); + if ($cart['price_type'] == 'level') $levelPrice = bcadd((string)$levelPrice, (string)$cart['vip_sum_truePrice'], 2); + } + $orderInfo['vip_true_price'] = $vipTruePrice; + $orderInfo['levelPrice'] = $levelPrice; + $orderInfo['memberPrice'] = $memberPrice; $orderInfo['total_price'] = bcadd($orderInfo['total_price'], $orderInfo['vip_true_price'], 2); if ($orderInfo['store_id'] && $orderInfo['shipping_type'] == 2) { /** @var $storeServices */ diff --git a/crmeb/app/adminapi/controller/v1/system/SystemTimer.php b/crmeb/app/adminapi/controller/v1/system/SystemTimer.php new file mode 100644 index 000000000..199ea4856 --- /dev/null +++ b/crmeb/app/adminapi/controller/v1/system/SystemTimer.php @@ -0,0 +1,92 @@ +services = $services; + } + + /** + * 获取定时任务列表 + * @return mixed + */ + public function getTimerList() + { + $where = ['is_del' => 0]; + return app('json')->success($this->services->getTimerList($where)); + } + + /** + * 获取定时任务详情 + * @param $id + * @return mixed + */ + public function getTimerInfo($id) + { + return app('json')->success($this->services->getTimerInfo($id)); + } + + /** + * 获取定时任务类型 + * @return mixed + */ + public function getMarkList() + { + return app('json')->success($this->services->getMarkList()); + } + + /** + * 保存定时任务 + * @return mixed + */ + public function saveTimer() + { + $data = $this->request->postMore([ + ['id', 0], + ['name', ''], + ['mark', ''], + ['content', ''], + ['type', 0], + ['is_open', 0], + ['week', 0], + ['day', 0], + ['hour', 0], + ['minute', 0], + ['second', 0], + ]); + $this->services->saveTimer($data); + return app('json')->success(100000); + } + + /** + * 删除定时任务 + * @param $id + * @return mixed + */ + public function delTimer($id) + { + $this->services->delTimer($id); + return app('json')->success(100002); + } + + /** + * 设置定时任务状态 + * @param $id + * @param $is_open + * @return mixed + */ + public function setTimerStatus($id, $is_open) + { + $this->services->setTimerStatus($id, $is_open); + return app('json')->success(100014); + } + +} \ No newline at end of file diff --git a/crmeb/app/adminapi/controller/v1/user/UserLevel.php b/crmeb/app/adminapi/controller/v1/user/UserLevel.php index 15eb25b0c..3e21adf17 100644 --- a/crmeb/app/adminapi/controller/v1/user/UserLevel.php +++ b/crmeb/app/adminapi/controller/v1/user/UserLevel.php @@ -63,18 +63,16 @@ class UserLevel extends AuthController ['icon', ''], ['image', ''], ['is_show', ''], - ['explain', ''], ['exp_num', 0] ]); if ($data['valid_date'] == 0) $data['is_forever'] = 1;//有效时间为0的时候就是永久 if (!$data['name']) return app('json')->fail(400324); if (!$data['grade']) return app('json')->fail(400325); - if (!$data['explain']) return app('json')->fail(400326); if (!$data['icon']) return app('json')->fail(400327); if (!$data['image']) return app('json')->fail(400328); if (!$data['exp_num']) return app('json')->fail(400329); - - return app('json')->success($this->services->save((int)$data['id'], $data)); + $this->services->save((int)$data['id'], $data); + return app('json')->success(100000); } /* diff --git a/crmeb/app/adminapi/route/system.php b/crmeb/app/adminapi/route/system.php index 33de687cd..b830adeba 100644 --- a/crmeb/app/adminapi/route/system.php +++ b/crmeb/app/adminapi/route/system.php @@ -96,6 +96,21 @@ Route::group('system', function () { Route::get('upgrade_export/:id/:type', 'UpgradeController/export')->option(['real_name' => '导出备份']); //文件管理登录 Route::post('file/login', 'v1.system.SystemFile/login')->option(['real_name' => '文件管理登录']); + + /** 定时任务 */ + //定时任务列表 + Route::get('timer/list', 'v1.system.SystemTimer/getTimerList')->option(['real_name' => '定时任务列表']); + //定时任务类型 + Route::get('timer/mark', 'v1.system.SystemTimer/getMarkList')->option(['real_name' => '定时任务类型']); + //定时任务详情 + Route::get('timer/info/:id', 'v1.system.SystemTimer/getTimerInfo')->option(['real_name' => '定时任务详情']); + //定时任务添加编辑 + Route::post('timer/save', 'v1.system.SystemTimer/saveTimer')->option(['real_name' => '定时任务添加编辑']); + //删除定时任务 + Route::delete('timer/del/:id', 'v1.system.SystemTimer/delTimer')->option(['real_name' => '删除定时任务']); + //定时任务是否开启开关 + Route::get('timer/set_open/:id/:is_open', 'v1.system.SystemTimer/setTimerStatus')->option(['real_name' => '定时任务是否开启开关']); + })->middleware([ \app\http\middleware\AllowOriginMiddleware::class, \app\adminapi\middleware\AdminAuthTokenMiddleware::class, diff --git a/crmeb/app/api/controller/v1/store/StoreCouponsController.php b/crmeb/app/api/controller/v1/store/StoreCouponsController.php index bb3559e18..0cbea9a6c 100644 --- a/crmeb/app/api/controller/v1/store/StoreCouponsController.php +++ b/crmeb/app/api/controller/v1/store/StoreCouponsController.php @@ -60,7 +60,7 @@ class StoreCouponsController /** @var StoreCouponIssueServices $couponIssueService */ $couponIssueService = app()->make(StoreCouponIssueServices::class); - $couponIssueService->issueUserCoupon($couponId, $request->user()); + $couponIssueService->issueUserCoupon($couponId, $request->user(), true); return app('json')->success(410319); } diff --git a/crmeb/app/api/controller/v1/store/StoreProductController.php b/crmeb/app/api/controller/v1/store/StoreProductController.php index 99079a613..0cdcf7b3d 100644 --- a/crmeb/app/api/controller/v1/store/StoreProductController.php +++ b/crmeb/app/api/controller/v1/store/StoreProductController.php @@ -55,7 +55,8 @@ class StoreProductController [['type', 0], 0], ['ids', ''], ['selectId', ''], - ['productId', ''] + ['productId', ''], + ['coupon_category_id', ''] ]); if ($where['selectId'] && (!$where['sid'] || !$where['cid'])) { if ($services->value(['id' => $where['selectId']], 'pid')) { diff --git a/crmeb/app/dao/activity/coupon/StoreCouponIssueDao.php b/crmeb/app/dao/activity/coupon/StoreCouponIssueDao.php index b9d77c531..e97d068b7 100644 --- a/crmeb/app/dao/activity/coupon/StoreCouponIssueDao.php +++ b/crmeb/app/dao/activity/coupon/StoreCouponIssueDao.php @@ -101,7 +101,9 @@ class StoreCouponIssueDao extends BaseDao }]) ->where('type', $type) ->when($type == 1, function ($query) use ($typeId) { - if ($typeId) $query->where('category_id', 'in', $typeId); + if ($typeId) $query->where('id', 'in', function ($query) use ($typeId) { + $query->name('store_coupon_product')->whereIn('category_id', $typeId)->field(['coupon_id'])->select(); + })->whereOr('category_id', 'in', $typeId); }) ->when($type == 2, function ($query) use ($typeId) { if ($typeId) $query->whereFindinSet('product_id', $typeId); @@ -138,7 +140,9 @@ class StoreCouponIssueDao extends BaseDao $query->where('uid', $uid); }])->where(function ($query) use ($product_id, $cate_ids) { if ($product_id != 0 && $cate_ids != []) { - $query->whereFindinSet('product_id', $product_id)->whereOr('category_id', 'in', $cate_ids)->whereOr('type', 0); + $query->whereFindinSet('product_id', $product_id)->whereOr('id', 'in', function ($query) use ($cate_ids) { + $query->name('store_coupon_product')->whereIn('category_id', $cate_ids)->field(['coupon_id'])->select(); + })->whereOr('category_id', 'in', $cate_ids)->whereOr('type', 0); } })->when($limit > 0, function ($query) use ($limit) { $query->limit($limit); diff --git a/crmeb/app/dao/product/product/StoreCategoryDao.php b/crmeb/app/dao/product/product/StoreCategoryDao.php index 98992996b..6dad1eedb 100644 --- a/crmeb/app/dao/product/product/StoreCategoryDao.php +++ b/crmeb/app/dao/product/product/StoreCategoryDao.php @@ -164,18 +164,24 @@ class StoreCategoryDao extends BaseDao /** * 通过分类id 获取(自己以及下级)的所有分类 - * @param int $id + * @param $id * @param string $field * @return array * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ - public function getAllById(int $id, string $field = 'id') + public function getAllById($id, string $field = 'id') { - return $this->getModel()->where(function ($query) use ($id) { - $query->where('id', $id)->whereOr('pid', $id); - })->where('is_show', 1)->field($field)->select()->toArray(); + if (is_array($id)) { + return $this->getModel()->where(function ($query) use ($id) { + $query->whereIn('id', $id)->whereOr('pid', 'in', $id); + })->where('is_show', 1)->field($field)->select()->toArray(); + } else { + return $this->getModel()->where(function ($query) use ($id) { + $query->where('id', $id)->whereOr('pid', $id); + })->where('is_show', 1)->field($field)->select()->toArray(); + } } /** diff --git a/crmeb/app/dao/product/product/StoreProductDao.php b/crmeb/app/dao/product/product/StoreProductDao.php index fd0ade1a7..57a5f8a7d 100644 --- a/crmeb/app/dao/product/product/StoreProductDao.php +++ b/crmeb/app/dao/product/product/StoreProductDao.php @@ -124,6 +124,12 @@ class StoreProductDao extends BaseDao $query->name('store_category')->where('pid', $where['cid'])->field('id')->select(); })->field('product_id')->select(); }); + })->when(isset($where['coupon_category_id']) && $where['coupon_category_id'] != '', function ($query) use ($where) { + $query->whereIn('id', function ($query) use ($where) { + $query->name('store_product_cate')->whereIn('cate_id', function ($query) use ($where) { + $query->name('store_category')->whereIn('pid', $where['coupon_category_id'])->field('id')->select(); + })->whereOr('cate_id', 'in', $where['coupon_category_id'])->field('product_id')->select(); + }); })->when(isset($where['ids']) && $where['ids'], function ($query) use ($where) { if ((isset($where['priceOrder']) && $where['priceOrder'] != '') || (isset($where['salesOrder']) && $where['salesOrder'] != '')) { $query->whereIn('id', $where['ids']); diff --git a/crmeb/app/dao/system/timer/SystemTimerDao.php b/crmeb/app/dao/system/timer/SystemTimerDao.php new file mode 100644 index 000000000..4f8ae044f --- /dev/null +++ b/crmeb/app/dao/system/timer/SystemTimerDao.php @@ -0,0 +1,18 @@ + [\app\listener\user\UserVisit::class], //用户访问事件 'notice.notice' => [\app\listener\notice\Notice::class], //通知->消息事件 'pay.notify' => [\app\listener\pay\Notify::class],//支付异步回调 + 'SystemTimer' => [\app\listener\timer\SystemTimer::class],//定时任务事件 ], - 'subscribe' => [ - \app\subscribes\TaskSubscribe::class,//定时任务事件订阅类 - ] ]; diff --git a/crmeb/app/listener/timer/SystemTimer.php b/crmeb/app/listener/timer/SystemTimer.php new file mode 100644 index 000000000..16c52daf7 --- /dev/null +++ b/crmeb/app/listener/timer/SystemTimer.php @@ -0,0 +1,192 @@ +make(SystemTimerServices::class); + $list = $systemTimerServices->selectList(['is_del' => 0, 'is_open' => 1])->toArray(); + foreach ($list as &$item) { + //获取定时任务时间字符串 + $timeStr = $this->getTimerStr($item); + Log::error('mark:'.$item['mark']); + Log::error($timeStr); + + if ($item['mark'] == 'order_cancel') { + new Crontab($timeStr, function () { + Log::error('每隔30秒执行一次自动取消订单 '.date('Y-m-d H:i:s')); + //未支付自动取消订单 + try { + /** @var StoreOrderServices $orderServices */ + $orderServices = app()->make(StoreOrderServices::class); + $orderServices->orderUnpaidCancel(); + } catch (\Throwable $e) { + Log::error('自动取消订单失败,失败原因:' . $e->getMessage()); + } + }); + } + + if ($item['mark'] == 'pink_expiration') { + new Crontab($timeStr, function () { + Log::error('每隔1分钟执行一次拼团到期订单处理 '.date('Y-m-d H:i:s')); + //拼团到期订单处理 + try { + /** @var StorePinkServices $storePinkServices */ + $storePinkServices = app()->make(StorePinkServices::class); + $storePinkServices->statusPink(); + } catch (\Throwable $e) { + Log::error('拼团到期订单处理失败,失败原因:' . $e->getMessage()); + } + }); + } + + if ($item['mark'] == 'agent_unbind') { + new Crontab($timeStr, function () { + Log::error('每隔1分钟执行一次自动解除上级绑定 '.date('Y-m-d H:i:s')); + //自动解绑上级绑定 + try { + /** @var AgentManageServices $agentManage */ + $agentManage = app()->make(AgentManageServices::class); + $agentManage->removeSpread(); + } catch (\Throwable $e) { + Log::error('自动解除上级绑定失败,失败原因:' . $e->getMessage()); + } + }); + } + + if ($item['mark'] == 'live_product_status') { + new Crontab($timeStr, function () { + Log::error('每隔3分钟执行一次更新直播商品状态 '.date('Y-m-d H:i:s')); + //更新直播商品状态 + try { + /** @var LiveGoodsServices $liveGoods */ + $liveGoods = app()->make(LiveGoodsServices::class); + $liveGoods->syncGoodStatus(); + } catch (\Throwable $e) { + Log::error('更新直播商品状态失败,失败原因:' . $e->getMessage()); + } + }); + } + + if ($item['mark'] == 'live_room_status') { + new Crontab($timeStr, function () { + Log::error('每隔3分钟执行一次更新直播间状态 '.date('Y-m-d H:i:s')); + //更新直播间状态 + try { + /** @var LiveRoomServices $liveRoom */ + $liveRoom = app()->make(LiveRoomServices::class); + $liveRoom->syncRoomStatus(); + } catch (\Throwable $e) { + Log::error('更新直播间状态失败,失败原因:' . $e->getMessage()); + } + }); + } + + if ($item['mark'] == 'take_delivery') { + new Crontab($timeStr, function () { + Log::error('每隔5分钟执行一次自动收货 '.date('Y-m-d H:i:s')); + //自动收货 + try { + /** @var StoreOrderTakeServices $services */ + $services = app()->make(StoreOrderTakeServices::class); + $services->autoTakeOrder(); + } catch (\Throwable $e) { + Log::error('自动收货失败,失败原因:' . $e->getMessage()); + } + }); + } + + if ($item['mark'] == 'advance_off') { + new Crontab($timeStr, function () { + Log::error('每隔5分钟执行一次查询预售到期商品自动下架 '.date('Y-m-d H:i:s')); + //查询预售到期商品自动下架 + try { + /** @var StoreProductServices $product */ + $product = app()->make(StoreProductServices::class); + $product->downAdvance(); + } catch (\Throwable $e) { + Log::error('预售到期商品自动下架失败,失败原因:' . $e->getMessage()); + } + }); + } + + if ($item['mark'] == 'product_replay') { + new Crontab($timeStr, function () { + Log::error('每隔5分钟执行一次自动好评 '.date('Y-m-d H:i:s')); + //自动好评 + try { + /** @var StoreOrderServices $orderServices */ + $orderServices = app()->make(StoreOrderServices::class); + $orderServices->autoComment(); + } catch (\Throwable $e) { + Log::error('自动好评失败,失败原因:' . $e->getMessage()); + } + }); + } + + if ($item['mark'] == 'product_replay') { + new Crontab($timeStr, function () { + Log::error('每天0时30分0秒执行一次清除昨日海报 '.date('Y-m-d H:i:s')); + //清除昨日海报 + try { + /** @var SystemAttachmentServices $attach */ + $attach = app()->make(SystemAttachmentServices::class); + $attach->emptyYesterdayAttachment(); + } catch (\Throwable $e) { + Log::error('清除昨日海报失败,失败原因:' . $e->getMessage()); + } + }); + } + } + } + + public function getTimerStr($data): string + { + $timeStr = ''; + switch ($data['type']) { + case 1: + $timeStr = '*/' . $data['second'] . ' * * * * *'; + break; + case 2: + $timeStr = '0 */' . $data['minute'] . ' * * * *'; + break; + case 3: + $timeStr = '0 0 */' . $data['hour'] . ' * * *'; + break; + case 4: + $timeStr = '0 0 0 */' . $data['day'] . ' * *'; + break; + case 5: + $timeStr = $data['second'] . ' ' . $data['minute'] . ' ' . $data['hour'] . ' * * *'; + break; + case 6: + $timeStr = $data['second'] . ' ' . $data['minute'] . ' ' . $data['hour'] . ' * * ' . ($data['week'] == 7 ? 0 : $data['week']); + break; + case 7: + $timeStr = $data['second'] . ' ' . $data['minute'] . ' ' . $data['hour'] . ' ' . $data['day'] . ' * *'; + break; + } + return $timeStr; + } +} \ No newline at end of file diff --git a/crmeb/app/model/activity/coupon/StoreCouponIssue.php b/crmeb/app/model/activity/coupon/StoreCouponIssue.php index 261ad68b1..ce69c5cce 100644 --- a/crmeb/app/model/activity/coupon/StoreCouponIssue.php +++ b/crmeb/app/model/activity/coupon/StoreCouponIssue.php @@ -42,7 +42,7 @@ class StoreCouponIssue extends BaseModel */ public function used() { - return $this->hasOne(StoreCouponIssueUser::class, 'issue_coupon_id', 'id')->field('issue_coupon_id'); + return $this->hasMany(StoreCouponIssueUser::class, 'issue_coupon_id', 'id'); } /** diff --git a/crmeb/app/model/system/timer/SystemTimer.php b/crmeb/app/model/system/timer/SystemTimer.php new file mode 100644 index 000000000..bf54660a6 --- /dev/null +++ b/crmeb/app/model/system/timer/SystemTimer.php @@ -0,0 +1,23 @@ +dao->save($data); - if ($data['product_id'] !== '' && $res) { - $productIds = explode(',', $data['product_id']); + if (($data['product_id'] !== '' || $data['category_id'] !== '') && $res) { $couponData = []; - foreach ($productIds as $product_id) { - $couponData[] = ['product_id' => $product_id, 'coupon_id' => $res->id]; + if ($data['product_id'] !== '') { + $productIds = explode(',', $data['product_id']); + foreach ($productIds as $product_id) { + $couponData[] = ['product_id' => $product_id, 'coupon_id' => $res->id]; + } + } elseif ($data['category_id'] !== '') { + $categoryIds = explode(',', $data['category_id']); + foreach ($categoryIds as $category_id) { + $couponData[] = ['category_id' => $category_id, 'coupon_id' => $res->id]; + } } /** @var StoreCouponProductServices $storeCouponProductService */ $storeCouponProductService = app()->make(StoreCouponProductServices::class); @@ -237,30 +246,27 @@ class StoreCouponIssueServices extends BaseServices $ids = array_column($couponList, 'id'); /** @var StoreCouponIssueUserServices $issueUser */ $issueUser = app()->make(StoreCouponIssueUserServices::class); - $userCouponIds = $issueUser->getColumn([['uid', '=', $uid], ['issue_coupon_id', 'in', $ids]], 'issue_coupon_id') ?? []; foreach ($couponList as $item) { - if (!$userCouponIds || !in_array($item['id'], $userCouponIds)) { - $data['cid'] = $item['id']; - $data['uid'] = $uid; - $data['coupon_title'] = $item['title']; - $data['coupon_price'] = $item['coupon_price']; - $data['use_min_price'] = $item['use_min_price']; - if ($item['coupon_time']) { - $data['add_time'] = $time; - $data['end_time'] = $data['add_time'] + $item['coupon_time'] * 86400; - } else { - $data['add_time'] = $item['start_use_time']; - $data['end_time'] = $item['end_use_time']; - } - $data['type'] = 'get'; - $issue['uid'] = $uid; - $issue['issue_coupon_id'] = $item['id']; - $issue['add_time'] = $time; - $issueUserData[] = $issue; - $couponData[] = $data; - unset($data); - unset($issue); + $data['cid'] = $item['id']; + $data['uid'] = $uid; + $data['coupon_title'] = $item['title']; + $data['coupon_price'] = $item['coupon_price']; + $data['use_min_price'] = $item['use_min_price']; + if ($item['coupon_time']) { + $data['add_time'] = $time; + $data['end_time'] = $data['add_time'] + $item['coupon_time'] * 86400; + } else { + $data['add_time'] = $item['start_use_time']; + $data['end_time'] = $item['end_use_time']; } + $data['type'] = 'get'; + $issue['uid'] = $uid; + $issue['issue_coupon_id'] = $item['id']; + $issue['add_time'] = $time; + $issueUserData[] = $issue; + $couponData[] = $data; + unset($data); + unset($issue); } if ($couponData) { /** @var StoreCouponUserServices $storeCouponUser */ @@ -326,10 +332,10 @@ class StoreCouponIssueServices extends BaseServices foreach ($list as &$v) { $v['coupon_price'] = floatval($v['coupon_price']); $v['use_min_price'] = floatval($v['use_min_price']); - $v['is_use'] = $uid && isset($v['used']); + $v['is_use'] = count($v['used']); if ($v['end_use_time']) { $v['start_use_time'] = date('Y/m/d', $v['start_use_time']); - $v['end_use_time'] = $v['end_use_time'] ? date('Y/m/d', $v['end_use_time']) : date('Y/m/d', time() + 86400); + $v['end_use_time'] = date('Y/m/d', $v['end_use_time']); } if ($v['start_time']) { $v['start_time'] = date('Y/m/d', $v['start_time']); @@ -341,7 +347,16 @@ class StoreCouponIssueServices extends BaseServices return $data; } - public function issueUserCoupon($id, $user) + /** + * 领取优惠券 + * @param $id + * @param $user + * @param bool $is_receive + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function issueUserCoupon($id, $user, bool $is_receive = false) { $issueCouponInfo = $this->dao->getInfo((int)$id); $uid = $user->uid; @@ -354,9 +369,14 @@ class StoreCouponIssueServices extends BaseServices } /** @var StoreCouponIssueUserServices $issueUserService */ $issueUserService = app()->make(StoreCouponIssueUserServices::class); + if ($is_receive) { + $alreadyReceived = $issueUserService->count(['uid' => $uid, 'issue_coupon_id' => $id]); + if ($alreadyReceived >= $issueCouponInfo['receive_limit']) { + throw new ApiException(400518); + } + } /** @var StoreCouponUserServices $couponUserService */ $couponUserService = app()->make(StoreCouponUserServices::class); - if ($issueUserService->getOne(['uid' => $uid, 'issue_coupon_id' => $id])) throw new ApiException(400517); if ($issueCouponInfo->remain_count <= 0 && !$issueCouponInfo->is_permanent) throw new ApiException(400518); $this->transaction(function () use ($issueUserService, $uid, $id, $couponUserService, $issueCouponInfo) { $issueUserService->save(['uid' => $uid, 'issue_coupon_id' => $id, 'add_time' => time()]); @@ -432,29 +452,24 @@ class StoreCouponIssueServices extends BaseServices $storeCouponUser = app()->make(StoreCouponUserServices::class); /** @var StoreCouponIssueUserServices $storeCouponIssueUser */ $storeCouponIssueUser = app()->make(StoreCouponIssueUserServices::class); - $uids = $storeCouponIssueUser->getColumn(['issue_coupon_id' => $coupon['id']], 'uid'); foreach ($user as $k => $v) { - if (in_array($v, $uids)) { - continue; + $data[$k]['cid'] = $coupon['id']; + $data[$k]['uid'] = $v; + $data[$k]['coupon_title'] = $coupon['title']; + $data[$k]['coupon_price'] = $coupon['coupon_price']; + $data[$k]['use_min_price'] = $coupon['use_min_price']; + $data[$k]['add_time'] = time(); + if ($coupon['coupon_time']) { + $data[$k]['start_time'] = $data[$k]['add_time']; + $data[$k]['end_time'] = $data[$k]['add_time'] + $coupon['coupon_time'] * 86400; } else { - $data[$k]['cid'] = $coupon['id']; - $data[$k]['uid'] = $v; - $data[$k]['coupon_title'] = $coupon['title']; - $data[$k]['coupon_price'] = $coupon['coupon_price']; - $data[$k]['use_min_price'] = $coupon['use_min_price']; - $data[$k]['add_time'] = time(); - if ($coupon['coupon_time']) { - $data[$k]['start_time'] = $data[$k]['add_time']; - $data[$k]['end_time'] = $data[$k]['add_time'] + $coupon['coupon_time'] * 86400; - } else { - $data[$k]['start_time'] = $coupon['start_use_time']; - $data[$k]['end_time'] = $coupon['end_use_time']; - } - $data[$k]['type'] = 'send'; - $issueData[$k]['uid'] = $v; - $issueData[$k]['issue_coupon_id'] = $coupon['id']; - $issueData[$k]['add_time'] = time(); + $data[$k]['start_time'] = $coupon['start_use_time']; + $data[$k]['end_time'] = $coupon['end_use_time']; } + $data[$k]['type'] = 'send'; + $issueData[$k]['uid'] = $v; + $issueData[$k]['issue_coupon_id'] = $coupon['id']; + $issueData[$k]['add_time'] = time(); } if (!empty($data)) { if (!$storeCouponUser->saveAll($data)) { @@ -464,8 +479,6 @@ class StoreCouponIssueServices extends BaseServices throw new AdminException(100031); } return true; - } else { - throw new AdminException(400519); } } diff --git a/crmeb/app/services/activity/coupon/StoreCouponIssueUserServices.php b/crmeb/app/services/activity/coupon/StoreCouponIssueUserServices.php index bb93ee6a9..716dc818a 100644 --- a/crmeb/app/services/activity/coupon/StoreCouponIssueUserServices.php +++ b/crmeb/app/services/activity/coupon/StoreCouponIssueUserServices.php @@ -8,7 +8,7 @@ // +---------------------------------------------------------------------- // | Author: CRMEB Team // +---------------------------------------------------------------------- -declare (strict_types = 1); +declare (strict_types=1); namespace app\services\activity\coupon; @@ -42,6 +42,10 @@ class StoreCouponIssueUserServices extends BaseServices { [$page, $limit] = $this->getPageValue(); $list = $this->dao->getList($where, $page, $limit); + $site_url = sys_config('site_url'); + foreach ($list as &$item) { + $item['avatar'] = strpos($item['avatar'], 'http') === false ? ($site_url . $item['avatar']) : $item['avatar']; + } $count = $this->dao->count($where); return compact('list', 'count'); } diff --git a/crmeb/app/services/activity/coupon/StoreCouponUserServices.php b/crmeb/app/services/activity/coupon/StoreCouponUserServices.php index 1e75fd78e..927f50ea0 100644 --- a/crmeb/app/services/activity/coupon/StoreCouponUserServices.php +++ b/crmeb/app/services/activity/coupon/StoreCouponUserServices.php @@ -145,9 +145,10 @@ class StoreCouponUserServices extends BaseServices case 1://品类券 /** @var StoreCategoryServices $storeCategoryServices */ $storeCategoryServices = app()->make(StoreCategoryServices::class); - $cateGorys = $storeCategoryServices->getAllById((int)$coupon['category_id']); - if ($cateGorys) { - $cateIds = array_column($cateGorys, 'id'); + $coupon_category = explode(',', $coupon['category_id']); + $category_ids = $storeCategoryServices->getAllById($coupon_category); + if ($category_ids) { + $cateIds = array_column($category_ids, 'id'); foreach ($cartInfo as $cart) { if (isset($cart['productInfo']['cate_id']) && array_intersect(explode(',', $cart['productInfo']['cate_id']), $cateIds)) { $price += bcmul((string)$cart['truePrice'], (string)$cart['cart_num'], 2); @@ -302,18 +303,6 @@ class StoreCouponUserServices extends BaseServices } [$page, $limit] = $this->getPageValue(); $list = $this->dao->getCouponListByOrder($where, 'status ASC,add_time DESC', $page, $limit); - /** @var StoreCategoryServices $categoryServices */ - $categoryServices = app()->make(StoreCategoryServices::class); - $category = $categoryServices->getColumn([], 'pid,cate_name', 'id'); - foreach ($list as &$item) { - if ($item['category_id']) { - $item['category_type'] = $category[$item['category_id']]['pid'] == 0 ? 1 : 2; - $item['category_name'] = $category[$item['category_id']]['cate_name']; - } else { - $item['category_type'] = ''; - $item['category_name'] = ''; - } - } return $list ? $this->tidyCouponList($list) : []; } diff --git a/crmeb/app/services/message/NoticeService.php b/crmeb/app/services/message/NoticeService.php index 088740e71..abd9c084a 100644 --- a/crmeb/app/services/message/NoticeService.php +++ b/crmeb/app/services/message/NoticeService.php @@ -83,21 +83,32 @@ class NoticeService extends BaseServices if (!$product) { throw new AdminException(400463); } - $configdata = [ - 'clientId' => sys_config('printing_client_id', ''), - 'apiKey' => sys_config('printing_api_key', ''), - 'partner' => sys_config('develop_id', ''), - 'terminal' => sys_config('terminal_number', '') - ]; $switch = (bool)sys_config('pay_success_printing_switch'); if (!$switch) { throw new AdminException(400464); } - if (!$configdata['clientId'] || !$configdata['apiKey'] || !$configdata['partner'] || !$configdata['terminal']) { - throw new AdminException(400465); + if (sys_config('print_type', 1) == 1) { + $name = 'yi_lian_yun'; + $configData = [ + 'clientId' => sys_config('printing_client_id', ''), + 'apiKey' => sys_config('printing_api_key', ''), + 'partner' => sys_config('develop_id', ''), + 'terminal' => sys_config('terminal_number', '') + ]; + if (!$configData['clientId'] || !$configData['apiKey'] || !$configData['partner'] || !$configData['terminal']) { + throw new AdminException(400465); + } + } else { + $name = 'fei_e_yun'; + $configData = [ + 'feyUser' => sys_config('fey_user', ''), + 'feyUkey' => sys_config('fey_ukey', ''), + 'feySn' => sys_config('fey_sn', '') + ]; + if (!$configData['feyUser'] || !$configData['feyUkey'] || !$configData['feySn']) { + throw new AdminException(400465); + } } - PrintJob::dispatch('doJob', ['yi_lian_yun', $configdata, $order, $product]); + PrintJob::dispatch('doJob', [$name, $configData, $order, $product]); } - - } diff --git a/crmeb/app/services/order/StoreCartServices.php b/crmeb/app/services/order/StoreCartServices.php index e14c80eca..eadc4f27b 100644 --- a/crmeb/app/services/order/StoreCartServices.php +++ b/crmeb/app/services/order/StoreCartServices.php @@ -16,7 +16,6 @@ use app\services\activity\advance\StoreAdvanceServices; use app\services\BaseServices; use app\dao\order\StoreCartDao; use app\services\activity\coupon\StoreCouponIssueServices; -use app\services\activity\coupon\StoreCouponIssueUserServices; use app\services\shipping\ShippingTemplatesNoDeliveryServices; use app\services\system\SystemUserLevelServices; use app\services\user\member\MemberCardServices; @@ -172,11 +171,6 @@ class StoreCartServices extends BaseServices if (!$issueCoupon->getCount(['id' => $attrInfo['coupon_id'], 'status' => 1, 'is_del' => 0])) { throw new ApiException(410234); } - /** @var StoreCouponIssueUserServices $issueUserCoupon */ - $issueUserCoupon = app()->make(StoreCouponIssueUserServices::class); - if ($issueUserCoupon->getCount(['uid' => $uid, 'issue_coupon_id' => $attrInfo['coupon_id']])) { - throw new ApiException(410235); - } } $stockNum = $this->dao->value(['product_id' => $productId, 'product_attr_unique' => $unique, 'uid' => $uid, 'status' => 1], 'cart_num') ?: 0; if ($nowStock < ($cartNum + $stockNum)) { diff --git a/crmeb/app/services/order/StoreOrderComputedServices.php b/crmeb/app/services/order/StoreOrderComputedServices.php index 77bbdcf20..c9020df66 100644 --- a/crmeb/app/services/order/StoreOrderComputedServices.php +++ b/crmeb/app/services/order/StoreOrderComputedServices.php @@ -175,9 +175,10 @@ class StoreOrderComputedServices extends BaseServices case 1://品类券 /** @var StoreCategoryServices $storeCategoryServices */ $storeCategoryServices = app()->make(StoreCategoryServices::class); - $cateGorys = $storeCategoryServices->getAllById((int)$couponInfo['category_id']); - if ($cateGorys) { - $cateIds = array_column($cateGorys, 'id'); + $coupon_category = explode(',', $couponInfo['category_id']); + $category_ids = $storeCategoryServices->getAllById($coupon_category); + if ($category_ids) { + $cateIds = array_column($category_ids, 'id'); foreach ($cartInfo as $cart) { if (isset($cart['productInfo']['cate_id']) && array_intersect(explode(',', $cart['productInfo']['cate_id']), $cateIds)) { $price = bcadd($price, bcmul((string)$cart['truePrice'], (string)$cart['cart_num'], 2), 2); @@ -318,7 +319,9 @@ class StoreOrderComputedServices extends BaseServices $sumPrice = $this->getOrderSumPrice($cartInfo, 'sum_price');//获取订单原总金额 $totalPrice = $this->getOrderSumPrice($cartInfo, 'truePrice');//获取订单svip、用户等级优惠之后总金额 $costPrice = $this->getOrderSumPrice($cartInfo, 'costPrice');//获取订单成本价 - $vipPrice = $this->getOrderSumPrice($cartInfo, 'vip_truePrice');//获取订单会员优惠金额 + $vipPrice = $this->getOrderSumPrice($cartInfo, 'vip_truePrice');//获取订单等级和付费会员总优惠金额 + $levelPrice = $this->getOrderSumPrice($cartInfo, 'level');//获取会员等级优惠 + $memberPrice = $this->getOrderSumPrice($cartInfo, 'member');//获取付费会员优惠 // 判断商品包邮和固定运费 foreach ($cartInfo as $key => &$item) { @@ -513,7 +516,7 @@ class StoreOrderComputedServices extends BaseServices $storePostage = $storePostage; } } - return compact('storePostage', 'storeFreePostage', 'isStoreFreePostage', 'sumPrice', 'totalPrice', 'costPrice', 'vipPrice', 'storePostageDiscount', 'cartInfo'); + return compact('storePostage', 'storeFreePostage', 'isStoreFreePostage', 'sumPrice', 'totalPrice', 'costPrice', 'vipPrice', 'storePostageDiscount', 'cartInfo', 'levelPrice', 'memberPrice'); } /** @@ -529,7 +532,13 @@ class StoreOrderComputedServices extends BaseServices foreach ($cartInfo as $cart) { if (isset($cart['cart_info'])) $cart = $cart['cart_info']; if ($is_unit) { - $SumPrice = bcadd($SumPrice, bcmul($cart['cart_num'], $cart[$key], 2), 2); + if ($key == 'level' || $key == 'member') { + if ($cart['price_type'] == $key) { + $SumPrice = bcadd($SumPrice, bcmul($cart['cart_num'], $cart['vip_truePrice'], 2), 2); + } + } else { + $SumPrice = bcadd($SumPrice, bcmul($cart['cart_num'], $cart[$key], 2), 2); + } } else { $SumPrice = bcadd($SumPrice, $cart[$key], 2); } diff --git a/crmeb/app/services/order/StoreOrderCreateServices.php b/crmeb/app/services/order/StoreOrderCreateServices.php index 5ffc6fffe..c7ebf12d1 100644 --- a/crmeb/app/services/order/StoreOrderCreateServices.php +++ b/crmeb/app/services/order/StoreOrderCreateServices.php @@ -650,9 +650,10 @@ class StoreOrderCreateServices extends BaseServices case 1://品类券 /** @var StoreCategoryServices $storeCategoryServices */ $storeCategoryServices = app()->make(StoreCategoryServices::class); - $cateGorys = $storeCategoryServices->getAllById((int)$couponInfo['category_id']); - if ($cateGorys) { - $cateIds = array_column($cateGorys, 'id'); + $coupon_category = explode(',', $couponInfo['category_id']); + $category_ids = $storeCategoryServices->getAllById($coupon_category); + if ($category_ids) { + $cateIds = array_column($category_ids, 'id'); foreach ($cartInfo as $cart) { if (isset($cart['productInfo']['cate_id']) && array_intersect(explode(',', $cart['productInfo']['cate_id']), $cateIds)) { $total_price = bcadd((string)$total_price, (string)bcmul((string)$cart['truePrice'], (string)$cart['cart_num'], 4), 2); diff --git a/crmeb/app/services/order/StoreOrderServices.php b/crmeb/app/services/order/StoreOrderServices.php index 503c2f41b..ddb4eef3f 100644 --- a/crmeb/app/services/order/StoreOrderServices.php +++ b/crmeb/app/services/order/StoreOrderServices.php @@ -1454,16 +1454,29 @@ HTML; if (!$product) { throw new AdminException(400533); } - $data = [ - 'clientId' => sys_config('printing_client_id', ''), - 'apiKey' => sys_config('printing_api_key', ''), - 'partner' => sys_config('develop_id', ''), - 'terminal' => sys_config('terminal_number', '') - ]; - if (!$data['clientId'] || !$data['apiKey'] || !$data['partner'] || !$data['terminal']) { - throw new AdminException(400099); + if (sys_config('print_type', 1) == 1) { + $name = 'yi_lian_yun'; + $configData = [ + 'clientId' => sys_config('printing_client_id', ''), + 'apiKey' => sys_config('printing_api_key', ''), + 'partner' => sys_config('develop_id', ''), + 'terminal' => sys_config('terminal_number', '') + ]; + if (!$configData['clientId'] || !$configData['apiKey'] || !$configData['partner'] || !$configData['terminal']) { + throw new AdminException(400465); + } + } else { + $name = 'fei_e_yun'; + $configData = [ + 'feyUser' => sys_config('fey_user', ''), + 'feyUkey' => sys_config('fey_ukey', ''), + 'feySn' => sys_config('fey_sn', '') + ]; + if (!$configData['feyUser'] || !$configData['feyUkey'] || !$configData['feySn']) { + throw new AdminException(400465); + } } - $printer = new Printer('yi_lian_yun', $data); + $printer = new Printer($name, $configData); $res = $printer->setPrinterContent([ 'name' => sys_config('site_name'), 'orderInfo' => is_object($order) ? $order->toArray() : $order, @@ -2334,9 +2347,11 @@ HTML; $order['ali_pay_status'] = (bool)sys_config('ali_pay_status');//支付包支付 1 开启 0 关闭 $order['friend_pay_status'] = (int)sys_config('friend_pay_status') ?? 0;//好友代付 1 开启 0 关闭 $orderData = $this->tidyOrder($order, true, true); - $vipTruePrice = 0; + $vipTruePrice = $memberPrice = $levelPrice = 0; foreach ($orderData['cartInfo'] ?? [] as $key => $cart) { $vipTruePrice = bcadd((string)$vipTruePrice, (string)$cart['vip_sum_truePrice'], 2); + if ($cart['price_type'] == 'member') $memberPrice = bcadd((string)$memberPrice, (string)$cart['vip_sum_truePrice'], 2); + if ($cart['price_type'] == 'level') $levelPrice = bcadd((string)$levelPrice, (string)$cart['vip_sum_truePrice'], 2); if (isset($splitNum[$cart['id']])) { $orderData['cartInfo'][$key]['cart_num'] = $cart['cart_num'] - $splitNum[$cart['id']]; if ($orderData['cartInfo'][$key]['cart_num'] == 0) unset($orderData['cartInfo'][$key]); @@ -2344,6 +2359,8 @@ HTML; } $orderData['cartInfo'] = array_merge($orderData['cartInfo']); $orderData['vip_true_price'] = $vipTruePrice; + $orderData['levelPrice'] = $levelPrice; + $orderData['memberPrice'] = $memberPrice; $economize = $services->get(['order_id' => $order['order_id']], ['postage_price', 'member_price']); if ($economize) { $orderData['postage_price'] = $economize['postage_price']; diff --git a/crmeb/app/services/system/timer/SystemTimerServices.php b/crmeb/app/services/system/timer/SystemTimerServices.php new file mode 100644 index 000000000..34777e3f9 --- /dev/null +++ b/crmeb/app/services/system/timer/SystemTimerServices.php @@ -0,0 +1,187 @@ + '未支付自动取消订单', + 'pink_expiration' => '拼团到期订单处理', + 'agent_unbind' => '到期自动解绑上级', + 'live_product_status' => '自动更新直播商品状态', + 'live_room_status' => '自动更新直播间状态', + 'take_delivery' => '订单自动收货', + 'advance_off' => '预售商品到期自动下架', + 'product_replay' => '订单商品自动好评', + 'clear_poster' => '清除昨日海报', + ]; + + public function __construct(SystemTimerDao $dao) + { + $this->dao = $dao; + } + + /** + * 定时任务列表 + * @param array $where + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getTimerList(array $where = []) + { + [$page, $limit] = $this->getPageValue(); + $list = $this->dao->selectList($where, '*', $page, $limit, 'id desc'); + foreach ($list as &$item) { + $item['next_execution_time'] = date('Y-m-d H:i:s', $item['next_execution_time']); + $item['last_execution_time'] = $item['last_execution_time'] != 0 ? date('Y-m-d H:i:s', $item['last_execution_time']) : '暂未执行'; + } + $count = $this->dao->count($where); + return compact('list', 'count'); + } + + /** + * 定时任务详情 + * @param $id + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getTimerInfo($id) + { + $info = $this->dao->get($id); + if (!$info) throw new AdminException(100026); + return $info->toArray(); + } + + /** + * 定时任务类型 + * @return string[] + */ + public function getMarkList(): array + { + return $this->markList; + } + + /** + * 保存定时任务 + * @param array $data + * @return bool + */ + public function saveTimer(array $data = []) + { + if (!$data['id'] && $this->dao->getCount(['mark' => $data['mark'], 'is_del' => 0])) { + throw new AdminException('该定时任务已存在,请勿重复添加'); + } + $data['name'] = $this->markList[$data['mark']]; + $data['add_time'] = time(); + if (!$data['id']) { + unset($data['id']); + $res = $this->dao->save($data); + } else { + $res = $this->dao->update(['id' => $data['id']], $data); + } + if (!$res) throw new AdminException(100006); + return true; + } + + /** + * 删除定时任务 + * @param $id + * @return bool + */ + public function delTimer($id) + { + $res = $this->dao->update(['id' => $id], ['is_del' => 1]); + if (!$res) throw new AdminException(100008); + return true; + } + + /** + * 设置定时任务状态 + * @param $id + * @param $is_open + * @return bool + */ + public function setTimerStatus($id, $is_open) + { + $res = $this->dao->update(['id' => $id], ['is_open' => $is_open]); + if (!$res) throw new AdminException(100014); + return true; + } + + /** + * 计算定时任务下次执行时间(弃用) + * @param $data + * @param int $time + * @return false|float|int|mixed + */ + public function getTimerCycleTime($data, $time = 0) + { + if (!$time) $time = time(); + switch ($data['type']) { + case 1: // 每隔几秒 + $cycle_time = $time + $data['second']; + break; + case 2: // 每隔几分 + $cycle_time = $time + ($data['minute'] * 60); + break; + case 3: // 每隔几时 + $cycle_time = $time + ($data['hour'] * 3600); + break; + case 4: // 每隔几日 + $cycle_time = $time + ($data['day'] * 86400); + break; + case 5: // 每日几时几分几秒 + $cycle_time = strtotime(date('Y-m-d ' . $data['hour'] . ':' . $data['minute'] . ':' . $data['second'], time())); + if ($time >= $cycle_time) { + $cycle_time = $cycle_time + 86400; + } + break; + case 6: // 每周周几几时几分几秒 + $todayStart = strtotime(date('Y-m-d 00:00:00', time())); + $w = date("w"); + if ($w > $data['week']) { + $cycle_time = $todayStart + ((7 - $w + $data['week']) * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + } else if ($w == $data['week']) { + $cycle_time = $todayStart + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + if ($time >= $cycle_time) { + $cycle_time = $cycle_time + (7 * 86400); + } + } else { + $cycle_time = $todayStart + (($data['week'] - $w) * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + } + break; + case 7: // 每月几日几时几分几秒 + $d = date("d"); + $firstDate = date('Y-m-01', time()); + $maxDay = date('d', strtotime("$firstDate + 1 month -1 day")); + $todayStart = strtotime(date('Y-m-d 00:00:00', time())); + if ($d > $data['day']) { + $cycle_time = $todayStart + (($maxDay - $d + $data['day']) * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + } elseif ($d == $data['day']) { + $cycle_time = $todayStart + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + if ($time >= $cycle_time) { + $cycle_time = $cycle_time + (($maxDay - $d + $data['day']) * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + } + } else { + $cycle_time = $todayStart + (($data['day'] - $d) * 86400) + ($data['hour'] * 3600) + ($data['minute'] * 60) + $data['second']; + } + break; + default: + $cycle_time = 0; + break; + } + return $cycle_time; + } +} \ No newline at end of file diff --git a/crmeb/app/services/user/UserLevelServices.php b/crmeb/app/services/user/UserLevelServices.php index 4fe22dab4..b2eb3c7da 100644 --- a/crmeb/app/services/user/UserLevelServices.php +++ b/crmeb/app/services/user/UserLevelServices.php @@ -8,7 +8,7 @@ // +---------------------------------------------------------------------- // | Author: CRMEB Team // +---------------------------------------------------------------------- -declare (strict_types = 1); +declare (strict_types=1); namespace app\services\user; @@ -206,10 +206,10 @@ class UserLevelServices extends BaseServices { if ($id) { - $vipinfo = app()->make(SystemUserLevelServices::class)->getlevel($id); - $vipinfo->image = set_file_url($vipinfo->image); - $vipinfo->icon = set_file_url($vipinfo->icon); - if (!$vipinfo) { + $vipInfo = app()->make(SystemUserLevelServices::class)->getlevel($id); + $vipInfo->image = set_file_url($vipInfo->image); + $vipInfo->icon = set_file_url($vipInfo->icon); + if (!$vipInfo) { throw new AdminException(100026); } $field[] = Form::hidden('id', $id); @@ -217,15 +217,13 @@ class UserLevelServices extends BaseServices } else { $msg = '添加用户等级'; } - $field[] = Form::input('name', '等级名称', isset($vipinfo) ? $vipinfo->name : '')->col(24)->required(); -// $field[] = Form::number('valid_date', '有效时间(天)', isset($vipinfo) ? $vipinfo->valid_date : 0)->min(0)->col(12); - $field[] = Form::number('grade', '等级', isset($vipinfo) ? $vipinfo->grade : 0)->min(0)->precision(0)->col(8)->required(); - $field[] = Form::number('discount', '享受折扣', isset($vipinfo) ? $vipinfo->discount : 100)->min(0)->max(100)->col(8)->placeholder('输入折扣数100,代表原价,90代表9折')->required(); - $field[] = Form::number('exp_num', '解锁需经验值达到', isset($vipinfo) ? $vipinfo->exp_num : 0)->min(0)->precision(0)->col(8)->required(); - $field[] = Form::frameImage('icon', '图标', Url::buildUrl('admin/widget.images/index', array('fodder' => 'icon')), isset($vipinfo) ? $vipinfo->icon : '')->icon('ios-add')->width('950px')->height('505px')->modal(['footer-hide' => true]); - $field[] = Form::frameImage('image', '用户等级背景', Url::buildUrl('admin/widget.images/index', array('fodder' => 'image')), isset($vipinfo) ? $vipinfo->image : '')->icon('ios-add')->width('950px')->height('505px')->modal(['footer-hide' => true]); - $field[] = Form::radio('is_show', '是否显示', isset($vipinfo) ? $vipinfo->is_show : 0)->options([['label' => '显示', 'value' => 1], ['label' => '隐藏', 'value' => 0]])->col(24); - $field[] = Form::textarea('explain', '等级说明', isset($vipinfo) ? $vipinfo->explain : '')->required(); + $field[] = Form::input('name', '等级名称', isset($vipInfo) ? $vipInfo->name : '')->col(24)->required(); + $field[] = Form::number('grade', '等级', isset($vipInfo) ? $vipInfo->grade : 0)->min(0)->precision(0)->col(8)->required(); + $field[] = Form::number('discount', '享受折扣', isset($vipInfo) ? $vipInfo->discount : 100)->min(0)->max(100)->col(8)->placeholder('输入折扣数100,代表原价,90代表9折')->required(); + $field[] = Form::number('exp_num', '解锁需经验值达到', isset($vipInfo) ? $vipInfo->exp_num : 0)->min(0)->precision(0)->col(8)->required(); + $field[] = Form::frameImage('icon', '图标', Url::buildUrl('admin/widget.images/index', array('fodder' => 'icon')), isset($vipInfo) ? $vipInfo->icon : '')->icon('ios-add')->width('950px')->height('505px')->modal(['footer-hide' => true]); + $field[] = Form::frameImage('image', '用户等级背景', Url::buildUrl('admin/widget.images/index', array('fodder' => 'image')), isset($vipInfo) ? $vipInfo->image : '')->icon('ios-add')->width('950px')->height('505px')->modal(['footer-hide' => true]); + $field[] = Form::radio('is_show', '是否显示', isset($vipInfo) ? $vipInfo->is_show : 0)->options([['label' => '显示', 'value' => 1], ['label' => '隐藏', 'value' => 0]])->col(24); return create_form($msg, $field, Url::buildUrl('/user/user_level'), 'POST'); } @@ -260,7 +258,7 @@ class UserLevelServices extends BaseServices if (!$systemUserLevel->update($id, $data)) { throw new AdminException(100007); } - return '修改成功'; + return true; } else { if ($levelOne || $levelThree) { throw new AdminException(400675); @@ -273,7 +271,7 @@ class UserLevelServices extends BaseServices if (!$systemUserLevel->save($data)) { throw new AdminException(100022); } - return '添加成功'; + return true; } } @@ -291,7 +289,7 @@ class UserLevelServices extends BaseServices if (!$systemUserLevel->update($id, ['is_del' => 1])) throw new AdminException(100008); } - return '删除成功'; + return 100002; } /** diff --git a/crmeb/crmeb/command/Timer.php b/crmeb/crmeb/command/Timer.php index 139b0bfe3..60d5c170b 100644 --- a/crmeb/crmeb/command/Timer.php +++ b/crmeb/crmeb/command/Timer.php @@ -27,7 +27,7 @@ class Timer extends Command /** * @var int|float */ - protected $interval = 2; + protected $interval = 1; protected function configure() { @@ -59,35 +59,11 @@ class Timer extends Command $this->init($input, $output); Worker::$pidFile = app()->getRootPath().'runtime/timer.pid'; $task = new Worker(); + date_default_timezone_set('PRC'); $task->count = 1; - event('Task_6'); - $task->onWorkerStart = [$this, 'start']; + $task->onWorkerStart = function () { + event('SystemTimer'); + }; $task->runAll(); } - - public function stop() - { - \Workerman\Lib\Timer::del($this->timer); - } - - public function start() - { - $last = time(); - $task = [6 => $last, 10 => $last, 30 => $last, 60 => $last, 180 => $last, 300 => $last]; - $this->timer = \Workerman\Lib\Timer::add($this->interval, function () use (&$task) { - try { - $now = time(); - event('Task_2'); - foreach ($task as $sec => $time) { - if ($now - $time >= $sec) { - event('Task_' . $sec); - $task[$sec] = $now; - } - } - } catch (\Throwable $e) { - } - }); - } - - } diff --git a/crmeb/crmeb/services/pay/Pay.php b/crmeb/crmeb/services/pay/Pay.php index c90381a15..dcc3695af 100644 --- a/crmeb/crmeb/services/pay/Pay.php +++ b/crmeb/crmeb/services/pay/Pay.php @@ -20,7 +20,7 @@ use think\facade\Config; /** * 第三方支付 - * Class Pay + * Class AllinPay * @package crmeb\services\pay * @mixin AliPay * @mixin WechatPay diff --git a/crmeb/crmeb/services/printer/AccessToken.php b/crmeb/crmeb/services/printer/AccessToken.php index 3b1012c77..df93c6c7d 100644 --- a/crmeb/crmeb/services/printer/AccessToken.php +++ b/crmeb/crmeb/services/printer/AccessToken.php @@ -14,7 +14,6 @@ namespace crmeb\services\printer; use app\services\other\CacheServices; use crmeb\exceptions\AdminException; use crmeb\services\HttpService; -use think\facade\Config; use think\helper\Str; /** @@ -72,12 +71,33 @@ class AccessToken extends HttpService */ protected $apiKey; + /** + * 飞鹅云SN + * @var string + */ + protected $feySn; + + /** + * 飞鹅云UYEK + * @var string + */ + protected $feyUkey; + + /** + * 飞鹅云USER + * @var string + */ + protected $feyUser; + public function __construct(array $config = [], string $name, string $configFile) { $this->clientId = $config['clientId'] ?? null; $this->apiKey = $config['apiKey'] ?? null; $this->partner = $config['partner'] ?? null; $this->machineCode = $config['terminal'] ?? null; + $this->feyUser = $config['feyUser'] ?? null; + $this->feyUkey = $config['feyUkey'] ?? null; + $this->feySn = $config['feySn'] ?? null; $this->name = $name; $this->configFile = $configFile; } @@ -150,7 +170,7 @@ class AccessToken extends HttpService */ public function __get($name) { - if (in_array($name, ['clientId', 'apiKey', 'accessToken', 'partner', 'terminal', 'machineCode'])) { + if (in_array($name, ['clientId', 'apiKey', 'accessToken', 'partner', 'terminal', 'machineCode', 'feyUser', 'feyUkey', 'feySn'])) { return $this->{$name}; } } diff --git a/crmeb/crmeb/services/printer/storage/FeiEYun.php b/crmeb/crmeb/services/printer/storage/FeiEYun.php new file mode 100644 index 000000000..4ba0a003a --- /dev/null +++ b/crmeb/crmeb/services/printer/storage/FeiEYun.php @@ -0,0 +1,161 @@ +printerContent) { + return $this->setError('Missing print'); + } + $time = time(); + $request = $this->accessToken->postRequest('http://api.feieyun.cn/Api/Open/', [ + 'user' => $this->accessToken->feyUser, + 'stime' => $time, + 'sig' => sha1($this->accessToken->feyUser . $this->accessToken->feyUkey . $time), + 'apiname' => 'Open_printMsg', + 'sn' => $this->accessToken->feySn, + 'content' => $this->printerContent, + 'times' => 1 + ]); + $res = json_decode($request, true); + if ($res['msg'] == 'ok') { + return $res; + } else { + return $this->setError($res['msg']); + } + } + + /** + * 设置打印内容 + * @param array $config + * @return YiLianYun + */ + public function setPrinterContent(array $config): self + { + $printTime = date('Y-m-d H:i:s', time()); + $product = $config['product']; + $orderInfo = $config['orderInfo']; + $orderTime = date('Y-m-d H:i:s', $orderInfo['pay_time']); + $this->printerContent = '**' . $config['name'] . '**
'; + $this->printerContent .= '--------------------------------
'; + $this->printerContent .= '订单编号:' . $orderInfo['order_id'] . '
'; + $this->printerContent .= '打印时间: ' . $printTime . '
'; + $this->printerContent .= '付款时间: ' . $orderTime . '
'; + $this->printerContent .= '姓 名: ' . $orderInfo['real_name'] . '
'; + $this->printerContent .= '电 话: ' . $orderInfo['user_phone'] . '
'; + $this->printerContent .= '地 址: ' . $orderInfo['user_address'] . '
'; + $this->printerContent .= '赠送积分: ' . $orderInfo['gain_integral'] . '
'; + $this->printerContent .= '订单备注:' . $orderInfo['mark'] . '
'; + $this->printerContent .= '**************商品**************
'; + $this->printerContent .= '名称 单价 数量 金额
'; + $this->printerContent .= '--------------------------------
'; + foreach ($product as $item) { + $name = $item['productInfo']['store_name']; + $price = $item['truePrice']; + $num = $item['cart_num']; + $prices = bcmul((string)$item['cart_num'], (string)$item['truePrice'], 2); + $kw3 = ''; + $kw1 = ''; + $kw2 = ''; + $kw4 = ''; + $str = $name; + $blankNum = 14;//名称控制为14个字节 + $lan = mb_strlen($str, 'utf-8'); + $m = 0; + $j = 1; + $blankNum++; + $result = array(); + if (strlen($price) < 6) { + $k1 = 6 - strlen($price); + for ($q = 0; $q < $k1; $q++) { + $kw1 .= ' '; + } + $price = $price . $kw1; + } + if (strlen($num) < 3) { + $k2 = 3 - strlen($num); + for ($q = 0; $q < $k2; $q++) { + $kw2 .= ' '; + } + $num = $num . $kw2; + } + if (strlen($prices) < 6) { + $k3 = 6 - strlen($prices); + for ($q = 0; $q < $k3; $q++) { + $kw4 .= ' '; + } + $prices = $prices . $kw4; + } + for ($i = 0; $i < $lan; $i++) { + $new = mb_substr($str, $m, $j, 'utf-8'); + $j++; + if (mb_strwidth($new, 'utf-8') < $blankNum) { + if ($m + $j > $lan) { + $m = $m + $j; + $tail = $new; + $lenght = iconv("UTF-8", "GBK//IGNORE", $new); + $k = 14 - strlen($lenght); + for ($q = 0; $q < $k; $q++) { + $kw3 .= ' '; + } + if ($m == $j) { + $tail .= $kw3 . ' ' . $price . ' ' . $num . ' ' . $prices; + } else { + $tail .= $kw3 . '
'; + } + break; + } else { + $next_new = mb_substr($str, $m, $j, 'utf-8'); + if (mb_strwidth($next_new, 'utf-8') < $blankNum) continue; + else { + $m = $i + 1; + $result[] = $new; + $j = 1; + } + } + } + } + $head = ''; + foreach ($result as $key => $value) { + if ($key < 1) { + $v_lenght = iconv("UTF-8", "GBK//IGNORE", $value); + $v_lenght = strlen($v_lenght); + if ($v_lenght == 13) $value = $value . " "; + $head .= $value . ' ' . $price . ' ' . $num . ' ' . $prices; + } else { + $head .= $value . '
'; + } + } + $this->printerContent .= $head . $tail; + unset($price); + } + $this->printerContent .= '--------------------------------
'; + $this->printerContent .= '合计:' . number_format($orderInfo['total_price'], 1) . '元
'; + $this->printerContent .= '邮费:' . number_format($orderInfo['pay_postage'], 1) . '元
'; + $this->printerContent .= '优惠:' . number_format($orderInfo['coupon_price'], 1) . '元
'; + $this->printerContent .= '抵扣:' . number_format($orderInfo['deduction_price'], 1) . '元
'; + $this->printerContent .= '实际支付:' . number_format($orderInfo['pay_price'], 1) . '元
'; + $this->printerContent .= '' . $config['url'] . '';//把解析后的二维码生成的字符串用标签套上即可自动生成二维码 + return $this; + } +} diff --git a/crmeb/public/install/crmeb.sql b/crmeb/public/install/crmeb.sql index f86bb6b19..fd5947896 100644 --- a/crmeb/public/install/crmeb.sql +++ b/crmeb/public/install/crmeb.sql @@ -27857,6 +27857,7 @@ CREATE TABLE IF NOT EXISTS `eb_store_coupon_issue` ( `end_time` int(10) NOT NULL DEFAULT '0' COMMENT '优惠券领取结束时间', `total_count` int(10) NOT NULL DEFAULT '0' COMMENT '优惠券领取数量', `remain_count` int(10) NOT NULL DEFAULT '0' COMMENT '优惠券剩余领取数量', + `receive_limit` int(10) NOT NULL DEFAULT '0' COMMENT '每个人个领取的优惠券数量', `is_permanent` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否无限张数', `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1 正常 0 未开启 -1 已无效', `is_give_subscribe` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否首次关注赠送 0-否(默认) 1-是', @@ -27901,8 +27902,7 @@ INSERT INTO `eb_store_coupon_issue` (`id`, `cid`, `coupon_title`, `start_time`, CREATE TABLE IF NOT EXISTS `eb_store_coupon_issue_user` ( `uid` int(10) NOT NULL DEFAULT '0' COMMENT '领取优惠券用户ID', `issue_coupon_id` int(10) NOT NULL DEFAULT '0' COMMENT '优惠券前台领取ID', - `add_time` int(10) NOT NULL DEFAULT '0' COMMENT '领取时间', - UNIQUE KEY `uid` (`uid`,`issue_coupon_id`) USING BTREE + `add_time` int(10) NOT NULL DEFAULT '0' COMMENT '领取时间' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='优惠券前台用户领取记录表'; -- -------------------------------------------------------- @@ -27914,6 +27914,7 @@ CREATE TABLE IF NOT EXISTS `eb_store_coupon_issue_user` ( CREATE TABLE IF NOT EXISTS `eb_store_coupon_product` ( `coupon_id` int(11) NOT NULL DEFAULT '0' COMMENT '优惠卷模板id', `product_id` int(11) NOT NULL DEFAULT '0' COMMENT '商品id', + `category_id` int(11) NOT NULL DEFAULT '0' COMMENT '分类id', KEY `coupon_id` (`coupon_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='优惠卷模板关联列表'; @@ -33177,7 +33178,7 @@ INSERT INTO `eb_system_config` (`id`, `menu_name`, `type`, `input_type`, `config (383, 'tengxun_appid', 'text', 'input', 82, '', 0, '', 0, 0, '\"\"', '腾讯云APPID', '腾讯云APPID', 0, 1), (384, 'extract_type', 'checkbox', 'input', 74, '0=>银行卡\n1=>微信\n2=>支付宝', 1, '', 0, 0, '[\"0\",\"1\",\"2\"]', '提现方式', '提现方式', 0, 1), (385, 'integral_frozen', 'text', 'input', 11, '', 1, '', 100, 0, '\"0\"', '积分冻结(天)', '积分冻结(天)', 0, 1), -(386, 'print_type', 'radio', 'input', 86, '1=>易联云', 1, '', 0, 0, '\"1\"', '平台选择', '平台选择', 0, 1), +(386, 'print_type', 'radio', 'input', 86, '1=>易联云\n2=>飞鹅云', 1, '', 0, 0, '1', '平台选择', '平台选择', 0, 1), (387, 'config_export_type', 'radio', 'input', 93, '1=>一号通', 1, '', 0, 0, '\"1\"', '电子面单类型', '电子面单类型', 0, 1), (388, 'customer_corpId', 'text', 'input', 69, '', 1, '', 100, 0, '\"\"', '企业ID', '小程序需要跳转企业微信客服的话需要配置此项', 0, 1), (389, 'create_wechat_user', 'radio', 'input', 2, '1=>开启\r\n0=>关闭', 1, '', 0, 0, '0', '关注公众号是否生成用户', '关注公众号是否生成用户', 0, 1), @@ -33203,7 +33204,11 @@ INSERT INTO `eb_system_config` (`id`, `menu_name`, `type`, `input_type`, `config (416, 'reward_money', 'text', 'number', 105, '', 1, '', 0, 0, '\"0\"', '赠送余额(元)', '新用户奖励金额,必须大于等于0,0为不赠送', 0, 1), (417, 'reward_integral', 'text', 'number', 105, '', 1, '', 0, 0, '\"0\"', '赠送积分', '新用户奖励积分,必须大于等于0,0为不赠送', 0, 1), (418, 'hs_accesskey', 'text', 'input', 106, '', 1, '', 0, 0, '\"AKLTMzkzZTEzNjg3OTg2NDViM2IwNmFlYzhmNzE4MmI4YmI\"', '火山翻译AccessKey', '机器翻译仅支持火山翻译', 1, 1), -(419, 'hs_secretkey', 'text', 'input', 106, '', 1, '', 0, 0, '\"TVRneU16STFOVFV4WVRkbE5ERTJaV0pqWm1aaU1UaGlNVFppWldZeE1HUQ==\"', '火山翻译SecretKey', '机器翻译仅支持火山翻译', 0, 1); +(419, 'hs_secretkey', 'text', 'input', 106, '', 1, '', 0, 0, '\"TVRneU16STFOVFV4WVRkbE5ERTJaV0pqWm1aaU1UaGlNVFppWldZeE1HUQ==\"', '火山翻译SecretKey', '机器翻译仅支持火山翻译', 0, 1), +(420, 'fey_user', 'text', 'input', 107, '', 1, '', 0, 0, '\"\"', '飞鹅云USER', '飞鹅云后台注册账号', 10, 1), +(421, 'fey_ukey', 'text', 'input', 107, '', 1, '', 0, 0, '\"\"', '飞鹅云UYEK', '飞鹅云后台注册账号后生成的UKEY 【备注:这不是填打印机的KEY】', 7, 1), +(422, 'fey_sn', 'text', 'input', 107, '', 1, '', 100, 0, '\"\"', '飞鹅云SN', '打印机标签上的编号,必须要在管理后台里添加打印机或调用API接口添加之后,才能调用API', 0, 1); + -- -------------------------------------------------------- -- @@ -33284,7 +33289,8 @@ INSERT INTO `eb_system_config_tab` (`id`, `pid`, `title`, `eng_title`, `status`, (103, 102, '基础配置', 'out_basic', 1, 0, '', 3, 0), (104, 102, '推送配置', 'out_push', 1, 0, '', 3, 0), (105, 100, '新用户设置', 'new_user_setting', 1, 0, '', 0, 0), -(106, 5, '机器翻译配置', 'online_translation', 1, 0, '', 0, 0); +(106, 5, '机器翻译配置', 'online_translation', 1, 0, '', 0, 0), +(107, 21, '飞鹅云配置', 'fey_config', 1, 0, '', 0, 0); -- -------------------------------------------------------- @@ -34331,7 +34337,8 @@ INSERT INTO `eb_system_menus` (`id`, `pid`, `icon`, `menu_name`, `module`, `cont (1071, 56, '', '文件管理', 'admin', '', '', '', '', '[]', 0, 1, 0, 1, '/admin/system/maintain/system_file/opendir', '25/56', 1, '', 0, 'system-maintain-system-file', 0), (1072, 1064, '', '接口文档', 'admin', '', '', '', '', '[]', 0, 1, 0, 1, '/admin/setting/system_out_interface/index', '56/1064', 1, '', 0, 'setting-system-out-interface-index', 0), (1073, 25, '', '数据维护', 'admin', '', '', '', '', '[]', 7, 1, 0, 1, 'system/database/index', '25', 1, '', 0, 'system-database-index', 0), -(1075, 731, '', '会员配置', 'admin', '', '', '', '', '[]', 6, 1, 0, 1, '/admin/marketing/member/system_config/3/67', '27/731', 1, '', 0, 'marketing-member-system_config', 0); +(1075, 731, '', '会员配置', 'admin', '', '', '', '', '[]', 6, 1, 0, 1, '/admin/marketing/member/system_config/3/67', '27/731', 1, '', 0, 'marketing-member-system_config', 0), +(1076, 56, '', '定时任务', 'admin', '', '', '', '', '[]', 0, 1, 0, 1, '/admin/system/crontab', '25/56', 1, '', 0, 'system-crontab-index', 0); -- -------------------------------------------------------- @@ -34530,6 +34537,46 @@ CREATE TABLE IF NOT EXISTS `eb_system_store_staff` ( -- -------------------------------------------------------- +-- +-- 表的结构 `eb_system_timer` +-- + +CREATE TABLE IF NOT EXISTS `eb_system_timer` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL DEFAULT '' COMMENT '定时器名称', + `mark` varchar(255) NOT NULL DEFAULT '' COMMENT '标签', + `content` varchar(255) NOT NULL DEFAULT '' COMMENT '说明', + `type` tinyint(1) NOT NULL DEFAULT '0' COMMENT '周期状态 1=每隔多少秒 2=每隔多少分钟 3=每隔多少小时 4=每隔多少天 5=每天几点执行 6=每周周几几点执行 7=每月几号几点执行', + `week` int(11) NOT NULL DEFAULT '0' COMMENT '周', + `day` int(11) NOT NULL DEFAULT '0' COMMENT '日', + `hour` int(11) NOT NULL DEFAULT '0' COMMENT '时', + `minute` int(11) NOT NULL DEFAULT '0' COMMENT '分', + `second` int(11) NOT NULL DEFAULT '0' COMMENT '秒', + `last_execution_time` int(11) NOT NULL DEFAULT '0' COMMENT '上次执行时间', + `next_execution_time` int(11) NOT NULL DEFAULT '0' COMMENT '下次执行时间', + `add_time` int(11) NOT NULL DEFAULT '0' COMMENT '添加时间', + `is_del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除', + `is_open` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否开启', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COMMENT='定时器'; + +-- +-- 转存表中的数据 `eb_system_timer` +-- + +INSERT INTO `eb_system_timer` (`id`, `name`, `mark`, `content`, `type`, `week`, `day`, `hour`, `minute`, `second`, `last_execution_time`, `next_execution_time`, `add_time`, `is_del`, `is_open`) VALUES +(1, '未支付自动取消订单', 'order_cancel', '每隔30秒执行自动取消到期未支付的订单', 1, 1, 1, 1, 30, 30, 0, 1670642407, 1670642377, 0, 1), +(2, '拼团到期订单处理', 'pink_expiration', '每隔1分钟拼团到期之后的操作', 2, 1, 1, 1, 1, 0, 0, 1670642487, 1670642427, 0, 1), +(3, '到期自动解绑上级', 'agent_unbind', '每隔1分钟执行到期的绑定关系的解除', 2, 1, 1, 1, 1, 0, 0, 1670642534, 1670642474, 0, 1), +(4, '自动更新直播商品状态', 'live_product_status', '每隔3分钟执行更新直播商品状态', 2, 1, 1, 1, 3, 0, 0, 1670642694, 1670642514, 0, 1), +(5, '自动更新直播间状态', 'live_room_status', '每隔3分钟执行更新直播间状态', 2, 1, 1, 1, 3, 0, 0, 1670642709, 1670642529, 0, 1), +(6, '订单自动收货', 'take_delivery', '每隔5分钟执行订单到期自动收货', 2, 1, 1, 1, 5, 0, 0, 1670642891, 1670642591, 0, 1), +(7, '预售商品到期自动下架', 'advance_off', '每隔5分钟执行预售商品到期下架', 2, 1, 1, 1, 5, 0, 0, 1670642913, 1670642613, 0, 1), +(8, '订单商品自动好评', 'product_replay', '每隔5分钟执行订单到期商品好评', 2, 1, 1, 1, 5, 0, 0, 1670642933, 1670642633, 0, 1), +(9, '清除昨日海报', 'clear_poster', '每天0时30分0秒执行一次清除昨日海报', 5, 1, 1, 0, 30, 0, 0, 1670862600, 1670815378, 0, 1); + +-- -------------------------------------------------------- + -- -- 表的结构 `eb_system_user_level` -- diff --git a/crmeb/vendor/composer/autoload_psr4.php b/crmeb/vendor/composer/autoload_psr4.php index a54ad06b5..204fab7a7 100644 --- a/crmeb/vendor/composer/autoload_psr4.php +++ b/crmeb/vendor/composer/autoload_psr4.php @@ -16,6 +16,7 @@ return array( 'crmeb\\' => array($baseDir . '/crmeb'), 'app\\' => array($baseDir . '/app'), 'ZipStream\\' => array($vendorDir . '/maennchen/zipstream-php/src'), + 'Workerman\\Crontab\\' => array($vendorDir . '/workerman/crontab/src'), 'Workerman\\' => array($vendorDir . '/workerman/workerman'), 'Volc\\' => array($vendorDir . '/volcengine/volc-sdk-php/src'), 'Test\\' => array($vendorDir . '/volcengine/volc-sdk-php/tests'), diff --git a/crmeb/vendor/composer/autoload_static.php b/crmeb/vendor/composer/autoload_static.php index 1d15c42bf..f00d6c014 100644 --- a/crmeb/vendor/composer/autoload_static.php +++ b/crmeb/vendor/composer/autoload_static.php @@ -119,6 +119,7 @@ class ComposerStaticInitf16474ac994ccc25392f403933800b79 ), 'W' => array ( + 'Workerman\\Crontab\\' => 18, 'Workerman\\' => 10, ), 'V' => @@ -291,6 +292,10 @@ class ComposerStaticInitf16474ac994ccc25392f403933800b79 array ( 0 => __DIR__ . '/..' . '/maennchen/zipstream-php/src', ), + 'Workerman\\Crontab\\' => + array ( + 0 => __DIR__ . '/..' . '/workerman/crontab/src', + ), 'Workerman\\' => array ( 0 => __DIR__ . '/..' . '/workerman/workerman', diff --git a/crmeb/vendor/composer/installed.json b/crmeb/vendor/composer/installed.json index 4c4997d12..8dc009c66 100644 --- a/crmeb/vendor/composer/installed.json +++ b/crmeb/vendor/composer/installed.json @@ -5358,6 +5358,65 @@ "homepage": "http://www.workerman.net", "install-path": "../workerman/channel" }, + { + "name": "workerman/crontab", + "version": "v1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/walkor/crontab.git", + "reference": "28106241415049ee340a8a7cd9b640165240a2fa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/walkor/crontab/zipball/28106241415049ee340a8a7cd9b640165240a2fa", + "reference": "28106241415049ee340a8a7cd9b640165240a2fa", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.0", + "workerman/workerman": ">=3.5.0" + }, + "time": "2021-10-06T14:18:14+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Workerman\\Crontab\\": "./src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "walkor", + "email": "walkor@workerman.net", + "homepage": "http://www.workerman.net", + "role": "Developer" + } + ], + "description": "A crontab written in PHP based on workerman", + "homepage": "http://www.workerman.net", + "keywords": [ + "crontab" + ], + "support": { + "email": "walkor@workerman.net", + "forum": "http://wenda.workerman.net/", + "issues": "https://github.com/walkor/workerman/issues", + "source": "https://github.com/walkor/crontab", + "wiki": "http://doc.workerman.net/" + }, + "install-path": "../workerman/crontab" + }, { "name": "workerman/workerman", "version": "v3.5.19", diff --git a/crmeb/vendor/composer/installed.php b/crmeb/vendor/composer/installed.php index be9b29a64..9309ea020 100644 --- a/crmeb/vendor/composer/installed.php +++ b/crmeb/vendor/composer/installed.php @@ -1,9 +1,9 @@ array( 'name' => 'topthink/think', - 'pretty_version' => '4.6.0.x-dev', - 'version' => '4.6.0.9999999-dev', - 'reference' => '24e1593a45135b3f38cacaa456385e38a370f0e6', + 'pretty_version' => '4.7.0.x-dev', + 'version' => '4.7.0.9999999-dev', + 'reference' => 'a788475ebfcfc447b5f262ea3f803a6fd9b89a8d', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -827,9 +827,9 @@ 'dev_requirement' => false, ), 'topthink/think' => array( - 'pretty_version' => '4.6.0.x-dev', - 'version' => '4.6.0.9999999-dev', - 'reference' => '24e1593a45135b3f38cacaa456385e38a370f0e6', + 'pretty_version' => '4.7.0.x-dev', + 'version' => '4.7.0.9999999-dev', + 'reference' => 'a788475ebfcfc447b5f262ea3f803a6fd9b89a8d', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -934,6 +934,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'workerman/crontab' => array( + 'pretty_version' => 'v1.0.2', + 'version' => '1.0.2.0', + 'reference' => '28106241415049ee340a8a7cd9b640165240a2fa', + 'type' => 'library', + 'install_path' => __DIR__ . '/../workerman/crontab', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'workerman/workerman' => array( 'pretty_version' => 'v3.5.19', 'version' => '3.5.19.0', diff --git a/crmeb/vendor/services.php b/crmeb/vendor/services.php index d1ce1a6b8..e787b6f0f 100644 --- a/crmeb/vendor/services.php +++ b/crmeb/vendor/services.php @@ -1,5 +1,5 @@ 'think\\captcha\\CaptchaService', diff --git a/crmeb/vendor/workerman/crontab/README.md b/crmeb/vendor/workerman/crontab/README.md new file mode 100644 index 000000000..0117eb966 --- /dev/null +++ b/crmeb/vendor/workerman/crontab/README.md @@ -0,0 +1,29 @@ +# Crontab +A crontab with precision in seconds written in PHP based on [workerman](https://github.com/walkor/workerman). + +# Install +``` +composer require workerman/crontab +``` + +# Usage +start.php +```php +onWorkerStart = function () { + // Execute the function in the first second of every minute. + new Crontab('1 * * * * *', function(){ + echo date('Y-m-d H:i:s')."\n"; + }); +}; + +Worker::runAll(); +``` + +Run with commands `php start.php start` or php `start.php start -d` diff --git a/crmeb/vendor/workerman/crontab/composer.json b/crmeb/vendor/workerman/crontab/composer.json new file mode 100644 index 000000000..e4c487d32 --- /dev/null +++ b/crmeb/vendor/workerman/crontab/composer.json @@ -0,0 +1,34 @@ +{ + "name": "workerman/crontab", + "type": "library", + "keywords": [ + "crontab" + ], + "homepage": "http://www.workerman.net", + "license": "MIT", + "description": "A crontab written in PHP based on workerman", + "authors": [ + { + "name": "walkor", + "email": "walkor@workerman.net", + "homepage": "http://www.workerman.net", + "role": "Developer" + } + ], + "support": { + "email": "walkor@workerman.net", + "issues": "https://github.com/walkor/workerman/issues", + "forum": "http://wenda.workerman.net/", + "wiki": "http://doc.workerman.net/", + "source": "https://github.com/walkor/crontab" + }, + "require": { + "php": ">=7.0", + "workerman/workerman": ">=3.5.0" + }, + "autoload": { + "psr-4": { + "Workerman\\Crontab\\": "./src" + } + } +} diff --git a/crmeb/vendor/workerman/crontab/example/test.php b/crmeb/vendor/workerman/crontab/example/test.php new file mode 100644 index 000000000..e6a87edd0 --- /dev/null +++ b/crmeb/vendor/workerman/crontab/example/test.php @@ -0,0 +1,16 @@ +onWorkerStart = function () { + // Execute the function in the first second of every minute. + new Crontab('1 * * * * *', function(){ + echo date('Y-m-d H:i:s')."\n"; + }); +}; + +Worker::runAll(); diff --git a/crmeb/vendor/workerman/crontab/src/Crontab.php b/crmeb/vendor/workerman/crontab/src/Crontab.php new file mode 100644 index 000000000..e79853f42 --- /dev/null +++ b/crmeb/vendor/workerman/crontab/src/Crontab.php @@ -0,0 +1,177 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +namespace Workerman\Crontab; +use Workerman\Lib\Timer; + +/** + * Class Crontab + * @package Workerman\Crontab + */ +class Crontab +{ + /** + * @var string + */ + protected $_rule; + + /** + * @var callable + */ + protected $_callback; + + /** + * @var string + */ + protected $_name; + + /** + * @var int + */ + protected $_id; + + /** + * @var array + */ + protected static $_instances = []; + + /** + * Crontab constructor. + * @param $rule + * @param $callback + * @param null $name + */ + public function __construct($rule, $callback, $name = null) + { + $this->_rule = $rule; + $this->_callback = $callback; + $this->_name = $name; + $this->_id = static::createId(); + static::$_instances[$this->_id] = $this; + static::tryInit(); + } + + /** + * @return string + */ + public function getRule() + { + return $this->_rule; + } + + /** + * @return callable + */ + public function getCallback() + { + return $this->_callback; + } + + /** + * @return string + */ + public function getName() + { + return $this->_name; + } + + /** + * @return int + */ + public function getId() + { + return $this->_id; + } + + /** + * @return bool + */ + public function destroy() + { + return static::remove($this->_id); + } + + /** + * @return array + */ + public static function getAll() + { + return static::$_instances; + } + + /** + * @param $id + * @return bool + */ + public static function remove($id) + { + if ($id instanceof Crontab) { + $id = $id->getId(); + } + if (!isset(static::$_instances[$id])) { + return false; + } + unset(static::$_instances[$id]); + return true; + } + + /** + * @return int + */ + protected static function createId() + { + static $id = 0; + return ++$id; + } + + /** + * tryInit + */ + protected static function tryInit() + { + static $inited = false; + if ($inited) { + return; + } + $inited = true; + $parser = new Parser(); + $callback = function () use ($parser, &$callback) { + foreach (static::$_instances as $crontab) { + $rule = $crontab->getRule(); + $cb = $crontab->getCallback(); + if (!$cb || !$rule) { + continue; + } + $times = $parser->parse($rule); + $now = time(); + foreach ($times as $time) { + $t = $time-$now; + if ($t <= 0) { + $t = 0.000001; + } + Timer::add($t, $cb, null, false); + } + } + Timer::add(60 - time()%60, $callback, null, false); + }; + + $next_time = time()%60; + if ($next_time == 0) { + $next_time = 0.00001; + } else { + $next_time = 60 - $next_time; + } + Timer::add($next_time, $callback, null, false); + } + +} \ No newline at end of file diff --git a/crmeb/vendor/workerman/crontab/src/Parser.php b/crmeb/vendor/workerman/crontab/src/Parser.php new file mode 100644 index 000000000..e9a9a86ee --- /dev/null +++ b/crmeb/vendor/workerman/crontab/src/Parser.php @@ -0,0 +1,171 @@ +, group@hyperf.io + * @license: http://www.gnu.org/licenses/ + * @license: https://github.com/hyperf/hyperf/blob/master/LICENSE + * + * This is a simple script to parse crontab syntax to get the execution time + * + * Eg.: $timestamp = Crontab::parse('12 * * * 1-5'); + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * Provides basic cron syntax parsing functionality + * + * @author: Jan Konieczny , group@hyperf.io + * @license: http://www.gnu.org/licenses/ + * @license https://github.com/hyperf/hyperf/blob/master/LICENSE + */ + +namespace Workerman\Crontab; + +/** + * Class Parser + * @package Workerman\Crontab + */ +class Parser +{ + /** + * Finds next execution time(stamp) parsin crontab syntax. + * + * @param string $crontab_string : + * 0 1 2 3 4 5 + * * * * * * * + * - - - - - - + * | | | | | | + * | | | | | +----- day of week (0 - 6) (Sunday=0) + * | | | | +----- month (1 - 12) + * | | | +------- day of month (1 - 31) + * | | +--------- hour (0 - 23) + * | +----------- min (0 - 59) + * +------------- sec (0-59) + * + * @param null|int $start_time + * @throws \InvalidArgumentException + * @return int[] + */ + public function parse($crontab_string, $start_time = null) + { + if (! $this->isValid($crontab_string)) { + throw new \InvalidArgumentException('Invalid cron string: ' . $crontab_string); + } + $start_time = $start_time ? $start_time : time(); + $date = $this->parseDate($crontab_string); + if (in_array((int) date('i', $start_time), $date['minutes']) + && in_array((int) date('G', $start_time), $date['hours']) + && in_array((int) date('j', $start_time), $date['day']) + && in_array((int) date('w', $start_time), $date['week']) + && in_array((int) date('n', $start_time), $date['month']) + ) { + $result = []; + foreach ($date['second'] as $second) { + $result[] = $start_time + $second; + } + return $result; + } + return []; + } + + public function isValid(string $crontab_string): bool + { + if (! preg_match('/^((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)$/i', trim($crontab_string))) { + if (! preg_match('/^((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)$/i', trim($crontab_string))) { + return false; + } + } + return true; + } + + /** + * Parse each segment of crontab string. + */ + protected function parseSegment(string $string, int $min, int $max, int $start = null) + { + if ($start === null || $start < $min) { + $start = $min; + } + $result = []; + if ($string === '*') { + for ($i = $start; $i <= $max; ++$i) { + $result[] = $i; + } + } elseif (strpos($string, ',') !== false) { + $exploded = explode(',', $string); + foreach ($exploded as $value) { + if (strpos($value, '/') !== false || strpos($string, '-') !== false) { + $result = array_merge($result, $this->parseSegment($value, $min, $max, $start)); + continue; + } + if (trim($value) === '' || ! $this->between((int) $value, (int) ($min > $start ? $min : $start), (int) $max)) { + continue; + } + $result[] = (int) $value; + } + } elseif (strpos($string, '/') !== false) { + $exploded = explode('/', $string); + if (strpos($exploded[0], '-') !== false) { + [$nMin, $nMax] = explode('-', $exploded[0]); + $nMin > $min && $min = (int) $nMin; + $nMax < $max && $max = (int) $nMax; + } + $start < $min && $start = $min; + for ($i = $start; $i <= $max;) { + $result[] = $i; + $i += $exploded[1]; + } + } elseif (strpos($string, '-') !== false) { + $result = array_merge($result, $this->parseSegment($string . '/1', $min, $max, $start)); + } elseif ($this->between((int) $string, $min > $start ? $min : $start, $max)) { + $result[] = (int) $string; + } + return $result; + } + + /** + * Determire if the $value is between in $min and $max ? + */ + private function between(int $value, int $min, int $max): bool + { + return $value >= $min && $value <= $max; + } + + + private function parseDate(string $crontab_string): array + { + $cron = preg_split('/[\\s]+/i', trim($crontab_string)); + if (count($cron) == 6) { + $date = [ + 'second' => $this->parseSegment($cron[0], 0, 59), + 'minutes' => $this->parseSegment($cron[1], 0, 59), + 'hours' => $this->parseSegment($cron[2], 0, 23), + 'day' => $this->parseSegment($cron[3], 1, 31), + 'month' => $this->parseSegment($cron[4], 1, 12), + 'week' => $this->parseSegment($cron[5], 0, 6), + ]; + } else { + $date = [ + 'second' => [1 => 0], + 'minutes' => $this->parseSegment($cron[0], 0, 59), + 'hours' => $this->parseSegment($cron[1], 0, 23), + 'day' => $this->parseSegment($cron[2], 1, 31), + 'month' => $this->parseSegment($cron[3], 1, 12), + 'week' => $this->parseSegment($cron[4], 0, 6), + ]; + } + return $date; + } +}